diff --git a/.github/workflows/preview-sdks.yml b/.github/workflows/preview-sdks.yml index b42d63901..297e51730 100644 --- a/.github/workflows/preview-sdks.yml +++ b/.github/workflows/preview-sdks.yml @@ -17,6 +17,11 @@ jobs: - name: Setup node uses: actions/setup-node@v3 + - name: Setup pnpm + uses: pnpm/action-setup@v2 + with: + version: 8 + - name: Download Fern run: npm install -g fern-api @@ -30,9 +35,9 @@ jobs: env: FERN_TOKEN: ${{ secrets.FERN_TOKEN }} run: | - cd fern/apis/api/.preview/fern-typescript-node-sdk - yarn install - yarn build + cd fern/apis/api/.preview/fern-typescript-sdk + pnpm install + pnpm build preview-python: runs-on: ubuntu-latest diff --git a/.github/workflows/release-csharp-sdk.yml b/.github/workflows/release-csharp-sdk.yml index 2258bb5fd..a2498ba2e 100644 --- a/.github/workflows/release-csharp-sdk.yml +++ b/.github/workflows/release-csharp-sdk.yml @@ -4,8 +4,8 @@ on: workflow_call: inputs: makePR: - description: Make Pull Request - default: false + description: "Compatibility input; SDK releases always open pull requests for manual approval" + default: true type: boolean version: description: "The version of the C# SDK that you would like to release" @@ -17,11 +17,6 @@ on: description: "The version of the C# SDK that you would like to release" required: true type: string - makePR: - description: Make Pull Request - required: true - default: false - type: boolean jobs: release: @@ -41,8 +36,4 @@ jobs: FERN_TOKEN: ${{ secrets.FERN_TOKEN }} NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }} run: | - if [ "${{ github.event.inputs.makePR }}" = "true" ]; then - fern generate --api api --group csharp-sdk --version ${{ inputs.version }} --mode pull-request --log-level debug - else - fern generate --api api --group csharp-sdk --version ${{ inputs.version }} --log-level debug - fi \ No newline at end of file + fern generate --api api --group csharp-sdk --version ${{ inputs.version }} --mode pull-request --log-level debug diff --git a/.github/workflows/release-go-sdk.yml b/.github/workflows/release-go-sdk.yml index 8a82753cc..113b210ad 100644 --- a/.github/workflows/release-go-sdk.yml +++ b/.github/workflows/release-go-sdk.yml @@ -4,8 +4,8 @@ on: workflow_call: inputs: makePR: - description: Make Pull Request - default: false + description: "Compatibility input; SDK releases always open pull requests for manual approval" + default: true type: boolean version: description: "The version of the Go SDK that you would like to release (optional - will auto-increment patch version if not provided)" @@ -17,11 +17,6 @@ on: description: "The version of the Go SDK that you would like to release (optional - will auto-increment patch version if not provided)" required: false type: string - makePR: - description: Make Pull Request - required: true - default: false - type: boolean jobs: determine-version: @@ -86,10 +81,5 @@ jobs: env: FERN_TOKEN: ${{ secrets.FERN_TOKEN }} run: | - if [ "${{ github.event.inputs.makePR }}" = "true" ]; then - echo "Generating Go SDK for version ${{ needs.determine-version.outputs.version }} in pull request mode" - fern generate --api api --group go-sdk --version ${{ needs.determine-version.outputs.version }} --mode pull-request --log-level debug - else - echo "Generating Go SDK for version ${{ needs.determine-version.outputs.version }}" - fern generate --api api --group go-sdk --version ${{ needs.determine-version.outputs.version }} --log-level debug - fi \ No newline at end of file + echo "Generating Go SDK for version ${{ needs.determine-version.outputs.version }} in pull request mode" + fern generate --api api --group go-sdk --version ${{ needs.determine-version.outputs.version }} --mode pull-request --log-level debug diff --git a/.github/workflows/release-java-sdk.yml b/.github/workflows/release-java-sdk.yml index bc2f90b0f..c648cfb63 100644 --- a/.github/workflows/release-java-sdk.yml +++ b/.github/workflows/release-java-sdk.yml @@ -4,11 +4,11 @@ on: workflow_call: inputs: makePR: - description: Make Pull Request - default: false + description: "Compatibility input; SDK releases always open pull requests for manual approval" + default: true type: boolean version: - description: "The version of the C# SDK that you would like to release" + description: "The version of the Java SDK that you would like to release" required: true type: string workflow_dispatch: @@ -17,11 +17,6 @@ on: description: "The version of the Java SDK that you would like to release" required: true type: string - makePR: - description: Make Pull Request - required: true - default: false - type: boolean jobs: release: @@ -42,8 +37,4 @@ jobs: MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }} MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }} run: | - if [ "${{ github.event.inputs.makePR }}" = "true" ]; then - fern generate --api api --group java-sdk --version ${{ inputs.version }} --mode pull-request --log-level debug - else - fern generate --api api --group java-sdk --version ${{ inputs.version }} --log-level debug - fi \ No newline at end of file + fern generate --api api --group java-sdk --version ${{ inputs.version }} --mode pull-request --log-level debug diff --git a/.github/workflows/release-php-sdk.yml b/.github/workflows/release-php-sdk.yml new file mode 100644 index 000000000..7fc44e859 --- /dev/null +++ b/.github/workflows/release-php-sdk.yml @@ -0,0 +1,31 @@ +name: Release PHP SDK + +on: + workflow_call: + inputs: + version: + description: "The version of the PHP SDK that you would like to release" + required: true + type: string + workflow_dispatch: + inputs: + version: + description: "The version of the PHP SDK that you would like to release" + required: true + type: string + +jobs: + release: + runs-on: ubuntu-latest + steps: + - name: Checkout repo + uses: actions/checkout@v4 + + - name: Download Fern + run: npm install -g fern-api + + - name: Release PHP SDK + env: + FERN_TOKEN: ${{ secrets.FERN_TOKEN }} + run: | + fern generate --group php-sdk --version ${{ inputs.version }} --mode pull-request --log-level debug diff --git a/.github/workflows/release-python-sdk.yml b/.github/workflows/release-python-sdk.yml index b17ffdc59..2942139e3 100644 --- a/.github/workflows/release-python-sdk.yml +++ b/.github/workflows/release-python-sdk.yml @@ -4,8 +4,8 @@ on: workflow_call: inputs: makePR: - description: Make Pull Request - default: false + description: "Compatibility input; SDK releases always open pull requests for manual approval" + default: true type: boolean version: description: "The version of the Python SDK that you would like to release (optional - will auto-increment patch version if not provided)" @@ -17,11 +17,6 @@ on: description: "The version of the Python SDK that you would like to release (optional - will auto-increment patch version if not provided)" required: false type: string - makePR: - description: Make Pull Request - required: true - default: false - type: boolean jobs: determine-version: @@ -87,8 +82,4 @@ jobs: FERN_TOKEN: ${{ secrets.FERN_TOKEN }} PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }} run: | - if [ "${{ github.event.inputs.makePR }}" = "true" ]; then - fern generate --api api --group python-sdk --version ${{ needs.determine-version.outputs.version }} --mode pull-request --log-level debug - else - fern generate --api api --group python-sdk --version ${{ needs.determine-version.outputs.version }} --log-level debug - fi + fern generate --api api --group python-sdk --version ${{ needs.determine-version.outputs.version }} --mode pull-request --log-level debug diff --git a/.github/workflows/release-ruby-sdk.yml b/.github/workflows/release-ruby-sdk.yml index 15d6c64fe..5724f2d99 100644 --- a/.github/workflows/release-ruby-sdk.yml +++ b/.github/workflows/release-ruby-sdk.yml @@ -4,11 +4,11 @@ on: workflow_call: inputs: makePR: - description: Make Pull Request - default: false + description: "Compatibility input; SDK releases always open pull requests for manual approval" + default: true type: boolean version: - description: "The version of the C# SDK that you would like to release" + description: "The version of the Ruby SDK that you would like to release" required: true type: string workflow_dispatch: @@ -17,11 +17,6 @@ on: description: "The version of the Ruby SDK that you would like to release" required: true type: string - makePR: - description: Make Pull Request - required: true - default: false - type: boolean jobs: release: @@ -41,8 +36,4 @@ jobs: FERN_TOKEN: ${{ secrets.FERN_TOKEN }} RUBYGEMS_API_KEY: ${{ secrets.RUBYGEMS_API_KEY }} run: | - if [ "${{ github.event.inputs.makePR }}" = "true" ]; then - fern generate --api api --group ruby-sdk --version ${{ inputs.version }} --mode pull-request --log-level debug - else - fern generate --api api --group ruby-sdk --version ${{ inputs.version }} --log-level debug - fi \ No newline at end of file + fern generate --api api --group ruby-sdk --version ${{ inputs.version }} --mode pull-request --log-level debug diff --git a/.github/workflows/release-swift-sdk.yml b/.github/workflows/release-swift-sdk.yml new file mode 100644 index 000000000..85bf67a5c --- /dev/null +++ b/.github/workflows/release-swift-sdk.yml @@ -0,0 +1,31 @@ +name: Release Swift SDK + +on: + workflow_call: + inputs: + version: + description: "The version of the Swift SDK that you would like to release" + required: true + type: string + workflow_dispatch: + inputs: + version: + description: "The version of the Swift SDK that you would like to release" + required: true + type: string + +jobs: + release: + runs-on: ubuntu-latest + steps: + - name: Checkout repo + uses: actions/checkout@v4 + + - name: Download Fern + run: npm install -g fern-api + + - name: Release Swift SDK + env: + FERN_TOKEN: ${{ secrets.FERN_TOKEN }} + run: | + fern generate --group swift-sdk --version ${{ inputs.version }} --mode pull-request --log-level debug diff --git a/.github/workflows/release-ts-sdk.yml b/.github/workflows/release-ts-sdk.yml index 1d9c0ca2b..45a8845ac 100644 --- a/.github/workflows/release-ts-sdk.yml +++ b/.github/workflows/release-ts-sdk.yml @@ -4,11 +4,11 @@ on: workflow_call: inputs: makePR: - description: Make Pull Request - default: false + description: "Compatibility input; SDK releases always open pull requests for manual approval" + default: true type: boolean version: - description: "The version of the C# SDK that you would like to release" + description: "The version of the TypeScript SDK that you would like to release" required: true type: string workflow_dispatch: @@ -17,11 +17,6 @@ on: description: "The version of the TypeScript SDK that you would like to release" required: true type: string - makePR: - description: Make Pull Request - required: true - default: false - type: boolean jobs: release: @@ -41,8 +36,4 @@ jobs: FERN_TOKEN: ${{ secrets.FERN_TOKEN }} NPM_TOKEN: ${{ secrets.NPM_TOKEN }} run: | - if [ "${{ github.event.inputs.makePR }}" = "true" ]; then - fern generate --api api --group ts-sdk --version ${{ inputs.version }} --mode pull-request --log-level debug - else - fern generate --api api --group ts-sdk --version ${{ inputs.version }} --log-level debug - fi \ No newline at end of file + fern generate --api api --group ts-sdk --version ${{ inputs.version }} --mode pull-request --log-level debug diff --git a/.github/workflows/update-openapi.yml b/.github/workflows/update-openapi.yml index 7d83b663d..8dc3484a8 100644 --- a/.github/workflows/update-openapi.yml +++ b/.github/workflows/update-openapi.yml @@ -16,9 +16,21 @@ jobs: with: token: ${{ secrets.GITHUB_TOKEN }} - name: Update OpenAPI Spec - uses: fern-api/sync-openapi@v2 + id: sync-openapi + uses: fern-api/sync-openapi@v4 with: token: ${{ secrets.GITHUB_TOKEN }} branch: 'update-openapi-spec' update_from_source: true - add_timestamp: true \ No newline at end of file + add_timestamp: true + - name: Enable auto-merge + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + PR_NUMBER=$(gh pr list --json number,headRefName --jq '[.[] | select(.headRefName | startswith("update-openapi-spec"))] | sort_by(.number) | last | .number') + if [ -n "$PR_NUMBER" ] && [ "$PR_NUMBER" != "null" ]; then + echo "Found PR #$PR_NUMBER, enabling auto-merge" + gh pr merge "$PR_NUMBER" --auto --squash + else + echo "No PR found for branch starting with update-openapi-spec" + fi diff --git a/.gitignore b/.gitignore index 74231d1ff..587625b32 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,9 @@ node_modules/ dist/ .env -.DS_Store \ No newline at end of file +.DS_Store +.tool-versions + +# Fern AI-generated examples (regenerated on each build; not committed) +fern/apis/api/ai_examples_override.yml +fern/apis/webhooks/ai_examples_override.yml diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..4a728d29b --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 Vapi + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 393cf32a0..f5fdbeae5 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,7 @@ You can suggest edits by making a pull request. To run a local development server with hot-reloading you can run the following command ```sh +npm install -g fern-api fern docs dev ``` diff --git a/fern/advanced/sip/sip-chime.mdx b/fern/advanced/sip/sip-chime.mdx new file mode 100644 index 000000000..1526c7841 --- /dev/null +++ b/fern/advanced/sip/sip-chime.mdx @@ -0,0 +1,308 @@ +--- +title: Amazon Chime SDK SIP Integration +subtitle: How to integrate Amazon Chime SDK Voice Connector with Vapi +slug: advanced/sip/amazon-chime +--- + +This guide walks you through setting up both outbound and inbound SIP trunking between Amazon Chime SDK and Vapi using a Voice Connector. + +This is a **Voice Connector-only** integration — inbound and outbound calls work with no Lambda functions or custom logic required. Vapi handles the AI assistant entirely. This approach is best for straightforward AI assistants on a phone number where no additional integration is needed. + + +This integration does not support passing custom SIP headers, metadata, or enriched escalation data (e.g., human transfer with SIP header context). For those use cases, use a **SIP Media Application** with **CallAndBridge** instead. + + +## Prerequisites + +- An AWS account with access to the [Amazon Chime SDK console](https://console.aws.amazon.com/chime-sdk/) +- A Vapi account with a [private API key](/security-and-privacy/api-keys) +- AWS CLI configured, or access to the Chime SDK console +- A phone number provisioned in Amazon Chime SDK (or the ability to order one) +- A Vapi assistant already created (for inbound calls) + +## Outbound calls (Chime SDK to Vapi) + +### Chime SDK configuration + + + + + +In the Amazon Chime SDK console, navigate to **Voice Connectors** and create a new one. + +Configure the following settings: +- **Encryption:** Enabled (default) +- **Network Type:** IPV4_ONLY + +![Create Voice Connector](../../static/images/sip/sip-chime-create-voice-connector.png) + +Save the **Outbound host name** from the Voice Connector details — you need it when configuring the Vapi SIP trunk. + + + + + +Navigate to the **Termination** tab of your Voice Connector and enable it. + +Add Vapi's static IP addresses for your Vapi region to the allowed host list: + +![Whitelist IP 1](../../static/images/sip/sip-chime-ip-1.png) + +![Whitelist IP 2](../../static/images/sip/sip-chime-ip-2.png) + +| Region | IP addresses | +| --- | --- | +| US | `44.229.228.186/32`, `44.238.177.138/32` | +| EU | `63.182.83.170/32` | + + + + + +In the **Termination** tab, scroll to the calling plan section and select the countries you want to allow outbound calls to. + + + + + +Still in the **Termination** tab, create a new credential with a username and password. Save these credentials — you need them for the Vapi SIP trunk configuration. + +![Create Credential](../../static/images/sip/sip-chime-create-credential.png) + + + + + +Navigate to the **Phone numbers** tab and click **Assign from inventory** to attach a phone number to this Voice Connector. + +![Phone Numbers Tab](../../static/images/sip/sip-chime-phone-number.png) + +Select the phone number you want to assign and confirm. + +![Assign Phone Number](../../static/images/sip/sip-chime-assign-phone-number.png) + + +If you don't have any phone numbers in your inventory, order them from **Amazon Chime SDK → Phone Number Management → Orders → Provision Phone Numbers**. + + + + + + +### Vapi configuration + + + + + +Get a [Vapi API key](/security-and-privacy/api-keys) to authenticate the API requests in this guide. + + + + + +Use the following API call to create a SIP trunk credential. Replace the placeholders with your Chime SDK Voice Connector details: + +```bash +curl -X POST https://api.vapi.ai/credential \ +-H "Content-Type: application/json" \ +-H "Authorization: Bearer YOUR_VAPI_API_KEY" \ +-d '{ + "provider": "byo-sip-trunk", + "name": "Chime SDK Trunk", + "outboundLeadingPlusEnabled": true, + "outboundAuthenticationPlan": { + "authUsername": "YOUR_CHIME_CREDENTIAL_USERNAME", + "authPassword": "YOUR_CHIME_CREDENTIAL_PASSWORD" + }, + "gateways": [ + { + "ip": "YOUR_CHIME_OUTBOUND_HOSTNAME", + "outboundEnabled": true, + "outboundProtocol": "tls/srtp", + "inboundEnabled": false, + "optionsPingEnabled": true + } + ] +}' +``` + +Note the `id` (credential ID) from the response for the next step. + + +The `outboundProtocol` must be set to `tls/srtp` when encryption is enabled on the Voice Connector (the default). + + + + + + +Associate your Chime SDK phone number with the Vapi SIP trunk: + +```bash +curl -X POST https://api.vapi.ai/phone-number \ +-H "Content-Type: application/json" \ +-H "Authorization: Bearer YOUR_VAPI_API_KEY" \ +-d '{ + "provider": "byo-phone-number", + "name": "Chime SDK SIP Number", + "number": "YOUR_CHIME_PHONE_NUMBER", + "numberE164CheckEnabled": true, + "credentialId": "YOUR_CREDENTIAL_ID" +}' +``` + +Note the phone number ID from the response for making calls. + + +The phone number must be in E.164 format (e.g., `+18312168445`). + + + + + + +You can make outbound calls in two ways: + +**Using the Vapi Dashboard:** + +The phone number appears in your dashboard. Select your assistant and enter the destination number you want to call. + +**Using the API:** + +```bash +curl -X POST https://api.vapi.ai/call/phone \ +-H "Content-Type: application/json" \ +-H "Authorization: Bearer YOUR_VAPI_API_KEY" \ +-d '{ + "assistantId": "YOUR_ASSISTANT_ID", + "customer": { + "number": "DESTINATION_PHONE_NUMBER", + "numberE164CheckEnabled": false + }, + "phoneNumberId": "YOUR_PHONE_NUMBER_ID" +}' +``` + + + + + +## Inbound calls (Chime SDK to Vapi) + +For inbound calls, a caller dials your Chime SDK phone number. The Voice Connector routes the call to Vapi through its origination settings — no Lambda or SIP Media Application required: + +```mermaid +graph LR + A[Caller] --> B[Chime Phone Number] + B --> C[Voice Connector] + C --> D[Regional Vapi SIP host] + D --> E[Vapi AI Assistant] +``` + +### Vapi configuration + + + + + +Vapi needs to know which IP addresses are allowed to send SIP traffic to it. Since the Voice Connector originates calls from its regional signaling IPs, you must register those IPs as a BYO SIP trunk credential in Vapi. + +Look up the **SIP signaling subnet** for your Voice Connector's region from the [Chime SDK Voice Connector network configuration docs](https://docs.aws.amazon.com/chime-sdk/latest/ag/network-config.html). + +Create the credential via the Vapi API: + +```bash +curl -X POST https://api.vapi.ai/credential \ +-H "Content-Type: application/json" \ +-H "Authorization: Bearer YOUR_VAPI_API_KEY" \ +-d '{ + "provider": "byo-sip-trunk", + "name": "Amazon Chime SDK Trunk", + "gateways": [ + { + "ip": "YOUR_VOICE_CONNECTOR_SIGNALING_IP", + "netmask": 24, + "inboundEnabled": true, + "outboundEnabled": false, + "outboundProtocol": "tls/srtp", + "optionsPingEnabled": true + } + ] +}' +``` + +Replace the `ip` and `netmask` with the values for your Voice Connector's region. For example: +- **US West (Oregon):** `99.77.253.0` with netmask `24` +- **US East (N. Virginia):** `3.80.16.0` with netmask `23` + +Set `outboundProtocol` to `tls/srtp` if your Voice Connector has encryption enabled (the default), or `udp` if not. + +Save the returned `id` — this is your **Credential ID** used in the following steps. + + + + + +Register your Chime SDK phone number in Vapi, linking it to the credential and your assistant: + +```bash +curl -X POST https://api.vapi.ai/phone-number \ +-H "Content-Type: application/json" \ +-H "Authorization: Bearer YOUR_VAPI_API_KEY" \ +-d '{ + "provider": "byo-phone-number", + "name": "Chime SDK Number", + "number": "YOUR_CHIME_PHONE_NUMBER", + "numberE164CheckEnabled": true, + "credentialId": "YOUR_CREDENTIAL_ID", + "assistantId": "YOUR_ASSISTANT_ID" +}' +``` + + +The `number` field must exactly match the E.164 phone number assigned to your Voice Connector (e.g., `+18312168445`). Inbound calls will fail to route if the numbers don't match. + + + + + + +### Chime SDK configuration + + + + + +Navigate to your Voice Connector's **Origination** tab and set **Origination status** to **Enabled**. + +![Enable Origination](../../static/images/sip/sip-chime-enable-origination.png) + +Click **New** to add an inbound route pointing to Vapi's SIP server for your region: + +- **Host (US):** `YOUR_CREDENTIAL_ID.sip.vapi.ai` +- **Host (EU):** `YOUR_CREDENTIAL_ID.sip.eu.vapi.ai` +- **Port:** `5061` (for encrypted connections) +- **Protocol:** TCP + +![Create Inbound Route](../../static/images/sip/sip-chime-create-inbound-route.png) + + + + + +Call your Chime SDK phone number from any phone. The call routes through the Voice Connector's origination settings to your regional Vapi SIP host, where your Vapi assistant answers. + +To debug issues, enable **SIP logging** on the Voice Connector (under the **Logging** tab) for detailed SIP message traces. + + + + + +## Next steps + +Now that you have Amazon Chime SDK SIP trunking configured: + +- **[SIP trunking overview](/advanced/sip/sip-trunk):** Learn more about SIP trunk concepts and configuration options. +- **[Networking and firewall](/advanced/sip/sip-networking):** Review network requirements and firewall rules. +- **[Troubleshoot SIP trunk credential errors](/advanced/sip/troubleshoot-sip-trunk-credential-errors):** Debug common SIP integration issues. diff --git a/fern/advanced/sip/sip-didlogic.mdx b/fern/advanced/sip/sip-didlogic.mdx new file mode 100644 index 000000000..0f1568e12 --- /dev/null +++ b/fern/advanced/sip/sip-didlogic.mdx @@ -0,0 +1,107 @@ +--- +title: didlogic SIP integration +subtitle: Connect didlogic SIP trunks and phone numbers to Vapi +description: Configure didlogic and Vapi for inbound calls, outbound calls, and SIP REFER transfers. +slug: advanced/sip/didlogic +--- + +Connect your didlogic SIP trunk to Vapi so your assistants can receive and place phone calls. This guide covers outbound calling through didlogic, inbound routing to Vapi, and optional SIP REFER transfers. + +For SIP trunking concepts and network requirements, see the [SIP trunking guide](/advanced/sip/sip-trunk). + + +Use the Vapi dashboard, SIP hostname, and API resources for the region where your organization is hosted. This guide provides both US and EU SIP routing formats. + + +## Prerequisites + +Before you begin, make sure you have: + +- An active [didlogic account](https://didlogic.com/get-started?utm_source=vapi_docs) with a positive balance +- At least one purchased phone number in the didlogic customer portal +- An active didlogic SIP account +- A Vapi account and assistant + +## Configure outbound calling + + + + In the [Vapi dashboard](https://dashboard.vapi.ai), select your organization name, then go to **Settings → Integrations → SIP Trunk** and click **Configure New SIP Trunk**. + + Configure the credential with your didlogic SIP account details: + + - **Name:** A descriptive name, such as `didlogic` + - **IP Address / Domain:** A [didlogic regional SIP gateway](https://docs.didlogic.com/docs/guides/getting-started/outbound-calling#our-sip-gateways), such as `sip.nl.didlogic.net` + - **Username:** Your five-digit didlogic SIP username + - **Password:** Your didlogic SIP password + + Save the credential and note its credential ID. You will use this ID when configuring inbound routing. + + + + To place outbound calls with the SIP trunk credential, the didlogic phone number must be available in Vapi. Go to [Phone Numbers](https://dashboard.vapi.ai/phone-numbers). If your didlogic number is not already listed, click **Create Phone Number** and select **BYO SIP Trunk Number**. If the number is already listed, open it to update its configuration. + + Enter or confirm your didlogic phone number and select the didlogic credential in the **SIP Trunk Credential** dropdown. If the number will also receive inbound calls, assign the assistant that should answer them. Save the phone number. + + + +## Configure inbound call routing + + + + Sign in to the [didlogic customer portal](https://app.didlogic.com), go to **Purchased**, find the phone number you imported into Vapi, and click **Edit** in the **Destination** section. + + + + Set **Destination Type** to **SIP URI**, then enter the URI for your Vapi region: + + ```text + # US organization + YOUR_PHONE_NUMBER@YOUR_CREDENTIAL_ID.sip.vapi.ai + + # EU organization + YOUR_PHONE_NUMBER@YOUR_CREDENTIAL_ID.sip.eu.vapi.ai + ``` + + Replace `YOUR_PHONE_NUMBER` with the didlogic number you imported and `YOUR_CREDENTIAL_ID` with the Vapi SIP trunk credential ID. Do not use a Vapi private API key in the SIP URI. + + Click **Add** to save the destination. + + + +## Test the integration + +### Test outbound calling + +1. In Vapi, select an assistant and the imported didlogic phone number. +2. Place a test call to a phone you can answer. +3. Verify that the call connects and displays the expected caller ID. + +### Test inbound calling + +1. Dial your didlogic phone number from an external phone. +2. Verify that Vapi receives the call and the assistant assigned to the number answers. + +## Configure SIP REFER transfers + +To transfer an active call through didlogic, ask your didlogic account manager to enable SIP REFER for your account. + + +didlogic may restrict SIP REFER transfers to other didlogic numbers. Confirm the supported destinations and required routing with your didlogic account manager. + + + + + In Vapi, go to **Tools → Create Tool → Transfer Call**. Add a **SIP** destination and enter a URI in the following format: + + ```text + sip:+E164_NUMBER@YOUR_didlogic_GATEWAY + ``` + + For example, `sip:+31203691111@sip.nl.didlogic.net`. + + + + Add a customer message and destination description, keep **Blind Transfer** selected so the transfer uses SIP REFER, and save the tool. Add the transfer tool to your assistant and publish the assistant. + + diff --git a/fern/advanced/sip/sip-didww.mdx b/fern/advanced/sip/sip-didww.mdx new file mode 100644 index 000000000..996763e7f --- /dev/null +++ b/fern/advanced/sip/sip-didww.mdx @@ -0,0 +1,309 @@ +--- +title: DIDWW SIP integration +subtitle: Connect DIDWW SIP trunks to Vapi so your assistants can receive calls, place outbound calls, and transfer active calls with SIP REFER. +description: Set up DIDWW SIP trunking with Vapi. Create inbound and outbound trunks, allowlist signaling IPs, and configure authenticated SIP REFER call transfers. +slug: advanced/sip/didww +--- + +## Before you begin + +- An active DIDWW account is required. [Sign in](https://my.didww.com/users/sign_in) or [create an account](https://my.didww.com/users/sign_up#/users/sign_up). +- Access to [DIDWW Outbound Trunks](https://doc.didww.com/voice/outbound-trunks/get-access.html) is required. +- A Vapi account and assistant is required. + +## 1. Route incoming calls to Vapi + +Create a DIDWW inbound SIP trunk that sends calls from your DIDWW numbers to Vapi. + + + + In the [DIDWW User Panel](https://my.didww.com/#/trunks), go to **Voice → Inbound Trunks** and select **Create New → SIP Trunk**. + + + + In the **General** tab, configure every field below: + + | Field | Value | + | --- | --- | + | **Name** | A descriptive name, such as `Vapi` | + | **Endpoint type** | **Static Endpoint** | + | **Host** | `sip.vapi.ai` for US organizations or `sip.eu.vapi.ai` for EU organizations | + | **Transport** | **UDP**, **TCP**, or **TLS** | + | **Port** | `5060` for UDP/TCP or `5061` for TLS | + | **Network Protocol** | Match the IP version allowed on the DIDWW outbound trunk; use **Prefer IPv4 over IPv6** or **IPv4 only** when allowlisting IPv4 addresses | + + + DIDWW inbound SIP trunk General tab with host, endpoint type, transport, and port fields configured for Vapi + + + + + {/* "Signalling" (double-l) intentionally matches DIDWW's on-screen tab label shown in the screenshot; do not change it. Use single-l "signaling" for our own prose everywhere else. */} + In the **Signalling** tab, set **Max transfers** to `1` or higher. This permits the in-dialog SIP REFER requests used for call transfers. + + + DIDWW inbound trunk Signalling tab with Max transfers set to 1 + + + + + Click **Create**. For additional DIDWW options, see the [inbound SIP trunk guide](https://doc.didww.com/voice/inbound-trunks/creating-a-new-sip-trunk.html). + + + +## 2. Enable outbound calling through DIDWW + +Create a DIDWW outbound trunk for Vapi calls and for authenticated SIP REFER transfers. + + + + In the DIDWW User Panel, go to **Voice → Outbound Trunks** and click **Create New**. + + + + Set a **Friendly Name**, such as `Vapi`, and keep **Credentials & IP-based** authentication selected. + + Under **Allowed SIP IP addresses**, add the signaling addresses for your Vapi region: + + | Region | Vapi signaling IPs | + | --- | --- | + | US | `44.229.228.186/32`, `44.238.177.138/32` | + | EU | `63.182.83.170/32` | + + To support call transfers, also add all DIDWW inbound signaling addresses: + + ```text + 46.19.209.14 + 46.19.210.14 + 46.19.212.14 + 46.19.213.14 + 46.19.214.14 + 46.19.215.14 + 185.238.173.14 + ``` + + + DIDWW outbound trunk Allowed SIP IP addresses list containing the Vapi and DIDWW signaling addresses + + + {/* The #sip-signalling anchor is intentionally double-l to match the current sip-networking heading; switch to #sip-signaling when that page is standardized to single-l (tracked as a separate issue). */} + + Do not use `0.0.0.0/0` in production. Restrict the trunk to the current [Vapi signaling IPs](/advanced/sip/sip-networking#sip-signalling) and [DIDWW SIP servers](https://doc.didww.com/voice/inbound-trunks/technical-data/sip.html#service-did-sip). + + + + + Click **Create** to save it. + + + + On **Voice → Outbound Trunks**, click the key icon in the trunk's **Credentials** column. Copy the **Username** and **Password**; you will use both in DIDWW and Vapi. + + + DIDWW outbound trunk credentials dialog showing the username and password fields + + + + + Edit the Vapi inbound trunk and open **Authorization**. Turn on **Enable Authorization**, paste the outbound trunk **Username** and **Password** into **Auth User** and **Auth Password**, then click **Submit**. + + + DIDWW inbound trunk Authorization tab with Enable Authorization turned on and the Auth User and Auth Password fields filled + + + For more detail, see [Add outbound credentials to the inbound trunk](https://doc.didww.com/integrations/vapi/index.html#step-5-add-outbound-credentials-to-the-inbound-trunk). + + + +## 3. Connect the SIP trunks in Vapi + +Use the same transport and port on both sides. In API examples, use `https://api.vapi.ai` for US organizations or replace it with `https://api.eu.vapi.ai` for EU organizations. + +### Step 1: Create the outbound trunk + + + + In the [Vapi dashboard](https://dashboard.vapi.ai), select your organization name in the top left, then click **Settings**. Under organization settings, go to **Integrations → SIP Trunk** and click **Configure New SIP Trunk**. + + 1. Set **Name** to `DIDWW Outbound Trunk`. + 2. Set **IP Address / Domain** to a [DIDWW outbound endpoint](https://doc.didww.com/voice/outbound-trunks/technical-data/sip-details.html#voice-out-signaling-endpoints), such as `fra.eu.out.didww.com`. + 3. Select the transport and port: `5060` for UDP/TCP or `5061` for TLS. + 4. Turn off **Allow inbound calls** and leave **Allow outbound calls** on. + + + Vapi SIP trunk configuration with the DIDWW outbound endpoint, transport, port, and outbound calls enabled + + + 5. Under **Authentication**, enter the DIDWW outbound username and password. Leave SIP registration off and save the trunk. + + + Vapi SIP trunk Authentication section with the DIDWW outbound username and password entered + + + + + ```bash + curl -X POST https://api.vapi.ai/credential \ + -H "Authorization: Bearer YOUR_VAPI_PRIVATE_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "provider": "byo-sip-trunk", + "name": "DIDWW Outbound Trunk", + "gateways": [ + { + "ip": "YOUR_DIDWW_OUTBOUND_ENDPOINT", + "port": 5060, + "inboundEnabled": false, + "outboundEnabled": true, + "outboundProtocol": "udp" + } + ], + "outboundAuthenticationPlan": { + "authUsername": "YOUR_DIDWW_TRUNK_USERNAME", + "authPassword": "YOUR_DIDWW_TRUNK_PASSWORD" + } + }' + ``` + + Replace the endpoint with the DIDWW signaling endpoint selected for your deployment. + + + +### Step 2: Create the inbound trunk + + + + Create another Vapi SIP trunk named `DIDWW Inbound Trunk`. + + 1. Add one gateway for each DIDWW IP below, using netmask `32` and the same port as the DIDWW inbound trunk. + 2. For every gateway, turn on **Allow inbound calls** and turn off **Allow outbound calls**. + + + Vapi SIP trunk with one inbound gateway per DIDWW signaling IP address + + + 3. Under **Authentication**, enter the DIDWW outbound username and password, then save the trunk. + + ```text + 46.19.209.14 + 46.19.210.14 + 46.19.212.14 + 46.19.213.14 + 46.19.214.14 + 46.19.215.14 + 185.238.173.14 + ``` + + + Vapi inbound SIP trunk Authentication section with the DIDWW credentials entered + + + + + ```bash + curl -X POST https://api.vapi.ai/credential \ + -H "Authorization: Bearer YOUR_VAPI_PRIVATE_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "provider": "byo-sip-trunk", + "name": "DIDWW Inbound Trunk", + "gateways": [ + { "ip": "46.19.209.14", "port": 5060, "netmask": 32, "inboundEnabled": true, "outboundEnabled": false }, + { "ip": "46.19.210.14", "port": 5060, "netmask": 32, "inboundEnabled": true, "outboundEnabled": false }, + { "ip": "46.19.212.14", "port": 5060, "netmask": 32, "inboundEnabled": true, "outboundEnabled": false }, + { "ip": "46.19.213.14", "port": 5060, "netmask": 32, "inboundEnabled": true, "outboundEnabled": false }, + { "ip": "46.19.214.14", "port": 5060, "netmask": 32, "inboundEnabled": true, "outboundEnabled": false }, + { "ip": "46.19.215.14", "port": 5060, "netmask": 32, "inboundEnabled": true, "outboundEnabled": false }, + { "ip": "185.238.173.14", "port": 5060, "netmask": 32, "inboundEnabled": true, "outboundEnabled": false } + ], + "outboundAuthenticationPlan": { + "authUsername": "YOUR_DIDWW_TRUNK_USERNAME", + "authPassword": "YOUR_DIDWW_TRUNK_PASSWORD" + } + }' + ``` + + Save the returned credential `id`; it is required when you [import the DIDWW number](/phone-numbers/didww). + + + +### Step 3: Create a call transfer tool + + + + In Vapi, go to **Tools → Create Tool → Transfer Call**. + + 1. Enter a tool name and describe when the assistant should transfer the caller. + 2. Add a **SIP** destination. + 3. Set **SIP URI** to `sip:+E164_NUMBER@OUTBOUND_ENDPOINT`, for example `sip:+447700900123@fra.eu.out.didww.com`. + 4. Add the customer message and destination description, keep **Blind Transfer**, and save. + + + Vapi Transfer Call tool with a SIP destination whose URI points to a DIDWW outbound endpoint + + + + + ```bash + curl -X POST https://api.vapi.ai/tool \ + -H "Authorization: Bearer YOUR_VAPI_PRIVATE_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "type": "transferCall", + "destinations": [ + { + "type": "sip", + "sipUri": "sip:+447700900123@YOUR_DIDWW_OUTBOUND_ENDPOINT", + "message": "Please wait while I transfer your call.", + "description": "Use when the caller asks to speak with a live person.", + "transferPlan": { + "mode": "blind-transfer", + "sipVerb": "refer" + } + } + ] + }' + ``` + + Save the returned tool `id` for the next step. + + + +### Step 4: Add the transfer tool to your assistant + + + + Open the assistant, go to **Tools → Add tool**, and select the transfer tool. Click **Publish**, then confirm the publication. + + + Vapi assistant Tools section with the DIDWW transfer tool added + + + + + Retrieve the assistant, add the transfer tool ID to `model.toolIds`, and PATCH the complete model back. The example uses `jq` to preserve the existing model configuration and tool IDs. + + ```bash + VAPI_API_BASE="https://api.vapi.ai" + ASSISTANT_ID="YOUR_ASSISTANT_ID" + TRANSFER_TOOL_ID="YOUR_TRANSFER_TOOL_ID" + + CURRENT_MODEL=$(curl -s "$VAPI_API_BASE/assistant/$ASSISTANT_ID" \ + -H "Authorization: Bearer YOUR_VAPI_PRIVATE_KEY" | jq '.model') + + UPDATED_MODEL=$(printf '%s' "$CURRENT_MODEL" | jq \ + --arg toolId "$TRANSFER_TOOL_ID" \ + '.toolIds = (((.toolIds // []) + [$toolId]) | unique)') + + jq -n --argjson model "$UPDATED_MODEL" '{model: $model}' | \ + curl -X PATCH "$VAPI_API_BASE/assistant/$ASSISTANT_ID" \ + -H "Authorization: Bearer YOUR_VAPI_PRIVATE_KEY" \ + -H "Content-Type: application/json" \ + --data-binary @- + ``` + + + +## Next step + +**[Import a number from DIDWW](/phone-numbers/didww):** Purchase or select a DIDWW number, assign the inbound trunk, and import the number into Vapi. diff --git a/fern/advanced/sip/sip-networking.mdx b/fern/advanced/sip/sip-networking.mdx new file mode 100644 index 000000000..e70088476 --- /dev/null +++ b/fern/advanced/sip/sip-networking.mdx @@ -0,0 +1,156 @@ +--- +title: SIP networking and firewall configuration +subtitle: Learn to configure your network to allow SIP signalling and media traffic with Vapi +slug: advanced/sip/sip-networking +--- + +## Overview + +When you integrate a SIP trunk with Vapi, your firewall and network infrastructure must allow SIP signalling and media (RTP) traffic to flow between your environment and Vapi's SIP servers. This page provides the complete set of IP addresses, ports, and protocols you need to configure. + +**In this reference, you'll find:** + +- All IP addresses and ports used by Vapi for SIP signalling +- RTP media port ranges, directionality details, and regional IP behavior +- Recommended firewall rules for inbound and outbound traffic + + + These networking details apply to **all** SIP trunk integrations with Vapi, regardless of your SIP provider. For provider-specific setup instructions, see the [SIP trunking](/advanced/sip/sip-trunk) guide. + + +## Quick reference + +The table below summarizes every IP address, port, and protocol you need to allowlist. Use the row that matches the Vapi region where your organization is hosted. + +| Traffic type | Region | Hostname | IP addresses | Ports | Protocol | Direction | +| --- | --- | --- | --- | --- | --- | --- | +| SIP signalling | US | `sip.vapi.ai` | `44.229.228.186`, `44.238.177.138` | `5060` | UDP/TCP | Bidirectional | +| SIP signalling | EU | `sip.eu.vapi.ai` | `63.182.83.170` | `5060` | UDP/TCP | Bidirectional | +| SIP signalling (TLS) | US | `sip.vapi.ai` | `44.229.228.186`, `44.238.177.138` | `5061` | TLS | Bidirectional | +| SIP signalling (TLS) | EU | `sip.eu.vapi.ai` | `63.182.83.170` | `5061` | TLS | Bidirectional | +| RTP media | US | N/A | No static IPs (dynamic) | `40000`-`60000` | UDP | Bidirectional | +| RTP media | EU | N/A | `63.182.83.170` | `40000`-`60000` | UDP | Bidirectional | + +Use your region's SIP hostname when configuring SIP URIs or SIP peers. If your firewall or SIP provider requires IP-based allowlisting, add the static signalling IP addresses for your region. For media, EU traffic can be allowlisted to `63.182.83.170`; US media uses dynamic source IPs and should be allowed by UDP port range. + +## SIP signalling + +Vapi's SIP infrastructure uses static IP addresses for signalling traffic in each region: + +| Region | Hostname | IP addresses | +| --- | --- | --- | +| US | `sip.vapi.ai` | `44.229.228.186/32`, `44.238.177.138/32` | +| EU | `sip.eu.vapi.ai` | `63.182.83.170/32` | + +These are the public IPs of Vapi's SBC (Session Border Controller) nodes. All SIP `INVITE`, `REGISTER`, `BYE`, and other signalling messages originate from and are received at the addresses for your region. + +### Ports + +| Port | Protocol | Use case | +| --- | --- | --- | +| **5060** | UDP/TCP | Default SIP signalling. UDP and TCP are both supported in US and EU. | +| **5061** | TLS | SIP over TLS (SIPS) signalling. | + +Use port **5060** unless your provider or security requirements mandate encrypted signalling. For TLS/SIPS in either region, use port **5061** with TLS. + +### Hostnames and allowlisting + +Configure your SIP client or PBX to point to the hostname for your region. For firewall rules and carrier allowlists, use the static IP addresses listed for your region. In the EU, `sip.eu.vapi.ai` currently resolves to `63.182.83.170`. + + + Allowlist every IP address for your region explicitly. DNS A records may not match every static IP that Vapi can use for carrier or firewall allowlisting. + + + + Do not use `sip-web.eu.vapi.ai` for SIP signalling or media. It is used for portal and API traffic and resolves through Cloudflare/WAF, not to Vapi's SIP infrastructure. + + +## SIP media (RTP) + +RTP media IP behavior depends on your region: + +- **US:** Vapi does not use static IP addresses for RTP media. Media source IPs are dynamically assigned and may change between calls. +- **EU:** RTP media uses the same static public IP as SIP signalling: `63.182.83.170`. + + + For US RTP media, allow traffic based on port ranges rather than specific source IPs. For EU RTP media, allowlist `63.182.83.170` with the full UDP port range. + + +### Port range + +Vapi uses **UDP ports 40000 through 60000** for RTP media traffic. + +| Setting | Value | +| --- | --- | +| Local RTP port range | `40000`-`60000` (UDP) | +| Direction | Bidirectional | + +- **Inbound RTP**: Vapi listens on ports `40000`-`60000` for incoming media packets. +- **Outbound RTP**: Vapi sends media from ports in the `40000`-`60000` range. The destination IP and port are determined by the remote SDP offer/answer, so Vapi can send to any IP and port your provider advertises. + + + Vapi does not restrict the remote RTP port range. Your provider may use any port for its RTP traffic. The `40000`-`60000` range applies only to Vapi's local ports. + + +## Firewall rules + +Configure your firewall to allow the following traffic. Every SIP signalling IP address for your region must be allowlisted. For RTP media, allow traffic on the full port range. US media uses dynamic IPs; EU media uses `63.182.83.170`. + +### Inbound rules (traffic from Vapi to your network) + +Allow these if your SIP provider or PBX needs to receive traffic from Vapi: + +| Rule | Region | Source IP | Destination | Port(s) | Protocol | +| --- | --- | --- | --- | --- | --- | +| SIP signalling | US | `44.229.228.186`, `44.238.177.138` | Your SIP server | `5060` | UDP/TCP | +| SIP signalling | EU | `63.182.83.170` | Your SIP server | `5060` | UDP/TCP | +| SIP signalling (TLS) | US | `44.229.228.186`, `44.238.177.138` | Your SIP server | `5061` | TLS | +| SIP signalling (TLS) | EU | `63.182.83.170` | Your SIP server | `5061` | TLS | +| RTP media | US | Any (dynamic) | Your media server | `40000`-`60000` | UDP | +| RTP media | EU | `63.182.83.170` | Your media server | `40000`-`60000` | UDP | + +### Outbound rules (traffic from your network to Vapi) + +Allow these if your firewall restricts outbound connections: + +| Rule | Region | Source | Destination IP | Port(s) | Protocol | +| --- | --- | --- | --- | --- | --- | +| SIP signalling | US | Your SIP server | `44.229.228.186`, `44.238.177.138` | `5060` | UDP/TCP | +| SIP signalling | EU | Your SIP server | `63.182.83.170` | `5060` | UDP/TCP | +| SIP signalling (TLS) | US | Your SIP server | `44.229.228.186`, `44.238.177.138` | `5061` | TLS | +| SIP signalling (TLS) | EU | Your SIP server | `63.182.83.170` | `5061` | TLS | +| RTP media | US | Your media server | Any (dynamic) | `40000`-`60000` | UDP | +| RTP media | EU | Your media server | `63.182.83.170` | `40000`-`60000` | UDP | + + + Allow every SIP signalling IP address for your region in your firewall rules. For RTP media, configure your firewall to allow the full port range (`40000`-`60000` UDP). US RTP media uses dynamic IPs. EU RTP media uses `63.182.83.170`. Contact support if you need a stricter media firewall policy. + + +## FAQ + + + + Use your region's hostname for SIP URI and peer configuration. For IP-based firewall rules, add the static IP addresses for your region explicitly. DNS-based firewall rules depend on TTL and caching behavior, and DNS A records may not match every static IP that Vapi can use for allowlisting. US RTP media uses dynamic IPs that cannot be resolved via DNS. EU RTP media uses `63.182.83.170`. + + + Yes. Vapi's RTP stack dynamically allocates ports within this range for each call. You cannot predict which specific port a given call will use, so the entire range must be open for reliable media flow. + + + It depends on the region. In the EU, SIP signalling and RTP media both use `63.182.83.170`. In the US, SIP signalling uses static IP addresses, but RTP media source IPs are dynamically assigned and may vary between calls. + + + Vapi supports TLS for SIP signalling on port 5061 in both US and EU regions. For encrypted media (SRTP), configure your SIP trunk gateway with the `tls/srtp` outbound protocol option. See the [gateway configuration reference](/advanced/sip/troubleshoot-sip-trunk-credential-errors#gateway-configuration-reference) for details. + + + These are standard SIP response codes, not Vapi-specific error codes. A `403 Forbidden` means a system in the SIP signaling path refused the request. A `404 Not Found` means the responding system could not find the requested user or domain. The exact cause depends on which system returned the response. See [Troubleshoot SIP response codes](/advanced/sip/troubleshoot-sip-response-codes) for the Vapi, provider, routing, and destination checks to perform. + + + +## Next steps + +Now that you have your network configured for Vapi SIP traffic: + +- **Set up a SIP trunk:** Follow the [SIP trunking](/advanced/sip/sip-trunk) guide to create your trunk credential and phone number +- **Configure a provider:** Set up with [Twilio](/advanced/sip/twilio), [Telnyx](/advanced/sip/telnyx), [Plivo](/advanced/sip/plivo), or [Zadarma](/advanced/sip/zadarma) +- **Troubleshoot errors:** Resolve gateway issues with the [SIP trunk credential troubleshooting](/advanced/sip/troubleshoot-sip-trunk-credential-errors) guide +- **Troubleshoot response codes:** Identify the likely failure point with the [SIP response code troubleshooting](/advanced/sip/troubleshoot-sip-response-codes) guide diff --git a/fern/advanced/sip/sip-plivo.mdx b/fern/advanced/sip/sip-plivo.mdx index 86dc7f8f9..14d0cbacb 100644 --- a/fern/advanced/sip/sip-plivo.mdx +++ b/fern/advanced/sip/sip-plivo.mdx @@ -39,13 +39,12 @@ Indian phone numbers cannot be used with Plivo on Vapi due to TRAI regulations. 2. **Fill out the form:** - **Name:** Enter a descriptive name (for example, `VAPI-IP-Group`). - - **IP Address List:** Add each of the following IP addresses one at a time: - ``` -44.229.228.186/32 - ``` - ``` -44.238.177.138/32 - ``` + - **IP Address List:** Add each IP address for the Vapi region where your organization is hosted: + + | Region | IP addresses | + | --- | --- | + | US | `44.229.228.186/32`, `44.238.177.138/32` | + | EU | `63.182.83.170/32` | 3. **Click** **Create ACL** to save. ![Plivo IP Access Control List](../../static/images/sip/sip-plivo-ip-acl.png) @@ -80,8 +79,8 @@ Indian phone numbers cannot be used with Plivo on Vapi due to TRAI regulations. ## Vapi Configuration - - Sign in to the dashboard and [get your API key](https://dashboard.vapi.ai/org/api-keys). + + Get a [Vapi API key](/security-and-privacy/api-keys) to authenticate the API requests in this guide. 1. Copy the following API call. @@ -192,7 +191,7 @@ Indian phone numbers cannot be used with Plivo on Vapi due to TRAI regulations. 2. **Fill out the form:** - **Name:** Enter a descriptive name (for example, `Vapi Inbound`). - - **URI:** Enter this origination URI exactly: `sip.vapi.ai;transport=udp` + - **URI:** Enter the origination URI for your Vapi region: `sip.vapi.ai;transport=udp` for US or `sip.eu.vapi.ai;transport=udp` for EU. 3. **Click** **Create URI** to save. ![Create New IP URI](../../static/images/sip/sip-plivo-create-new-ip-uri.png) @@ -223,8 +222,8 @@ Indian phone numbers cannot be used with Plivo on Vapi due to TRAI regulations. ## Vapi Configuration - - Sign into the dashboard and [get your api key](https://dashboard.vapi.ai/org/api-keys). + + Get a [Vapi API key](/security-and-privacy/api-keys) to authenticate the API requests in this guide. ```bash diff --git a/fern/advanced/sip/sip-telnyx.mdx b/fern/advanced/sip/sip-telnyx.mdx index 693f22e6d..96d60713b 100644 --- a/fern/advanced/sip/sip-telnyx.mdx +++ b/fern/advanced/sip/sip-telnyx.mdx @@ -8,13 +8,7 @@ Integrate your Telnyx SIP trunk with Vapi to enable your AI voice assistants to - - - - Log in to your Vapi account - - Navigate to **Organization Settings** - - In the **API Keys** section, copy your **Private Key** - - + Get a [Vapi private API key](/security-and-privacy/api-keys) to authenticate the API requests in this guide. @@ -24,7 +18,7 @@ Integrate your Telnyx SIP trunk with Vapi to enable your AI voice assistants to - Select FQDN - Click "Add FQDN" - Select A record type - - Set FQDN to: `sip.vapi.ai` + - Set FQDN to the SIP host for your Vapi region: `sip.vapi.ai` for US or `sip.eu.vapi.ai` for EU - Port should be 5060 by default @@ -46,7 +40,7 @@ Integrate your Telnyx SIP trunk with Vapi to enable your AI voice assistants to You can get your Vapi SIP URI when you create a new SIP number through the **Phone Numbers** tab in the Vapi dashboard. The URI will look like:
- sip:<your-unique-id>@sip.vapi.ai + sip:<your-unique-id>@sip.vapi.ai for US or sip:<your-unique-id>@sip.eu.vapi.ai for EU
*This setting modifies the SIP Invite so invites are correctly routed to your Vapi SIP URI.*
@@ -85,6 +79,9 @@ Integrate your Telnyx SIP trunk with Vapi to enable your AI voice assistants to Use the Vapi API to create a SIP trunk credential: + + Use IP addresses in `gateways`. FQDNs like `sip.telnyx.com` return a `400 Bad Request`. + ```bash curl -X POST https://api.vapi.ai/credential \ -H "Content-Type: application/json" \ @@ -94,20 +91,26 @@ Integrate your Telnyx SIP trunk with Vapi to enable your AI voice assistants to "name": "Telnyx Trunk", "gateways": [ { - "ip": "sip.telnyx.com", - "inboundEnabled": false + "ip": "192.76.120.10", + "inboundEnabled": true + }, + { + "ip": "64.16.250.10", + "inboundEnabled": true } ], "outboundAuthenticationPlan": { "authUsername": "YOUR_SIP_USERNAME", "authPassword": "YOUR_SIP_PASSWORD", "sipRegisterPlan": { - "realm": "sip.telnyx.com" - } + "realm": "sip.telnyx.com" + } } }' ``` Replace `YOUR_VAPI_PRIVATE_KEY`, `YOUR_SIP_USERNAME`, and `YOUR_SIP_PASSWORD` with your actual credentials. + Replace the gateway IPs with the Telnyx gateway IPs assigned to your trunk. + Set `inboundEnabled` to `false` if you only need outbound calls. If successful, the response will include an `id` for the created credential, which you'll use in the next step. diff --git a/fern/advanced/sip/sip-trunk.mdx b/fern/advanced/sip/sip-trunk.mdx index 0e40db6fb..1cd023ea0 100644 --- a/fern/advanced/sip/sip-trunk.mdx +++ b/fern/advanced/sip/sip-trunk.mdx @@ -8,12 +8,18 @@ SIP trunking replaces traditional phone lines with a virtual connection over the ## Network requirements -To allow SIP signaling and media between Vapi and your SIP provider, you must allowlist the following IP addresses: +To allow SIP signaling and media between Vapi and your SIP provider, allowlist the static IP addresses for the Vapi region where your organization is hosted: -- 44.229.228.186/32 -- 44.238.177.138/32 +| Region | SIP host | Signalling IP addresses | RTP media behavior | +| --- | --- | --- | --- | +| US | `sip.vapi.ai` | `44.229.228.186/32`, `44.238.177.138/32` | Dynamic media IPs; allow UDP ports `40000`-`60000` | +| EU | `sip.eu.vapi.ai` | `63.182.83.170/32` | Static media IP `63.182.83.170`; allow UDP ports `40000`-`60000` | -These IPs are used exclusively for SIP traffic. +For the complete list of ports, TLS options, RTP ranges, and firewall configuration details, see the [networking and firewall](/advanced/sip/sip-networking) reference. + + +If your organization is hosted in the EU, create the SIP trunk credential and BYO phone number through `https://api.eu.vapi.ai`, not `https://api.vapi.ai`. Keep the API region and SIP host in the same region: use `api.vapi.ai` with `sip.vapi.ai`, or `api.eu.vapi.ai` with `sip.eu.vapi.ai`. + We generally don't recommend IP-based authentication for SIP trunks as it can lead to routing issues. Since our servers are shared by many customers, if your telephony provider has multiple customers using IP-based authentication, calls may be routed incorrectly. IP-based authentication works reliably only when your SIP provider offers a unique termination URI or a dedicated SIP server for each customer, as is the case with Plivo and Twilio integrations. @@ -38,9 +44,19 @@ Vapi supports multiple SIP trunk configurations, including: Use the Vapi API to create a new credential (type: byo-sip-trunk) with your provider's details. This informs Vapi how to connect to your SIP network. + Set your API base URL for the region where your organization is hosted: + + ```bash + # US organizations + export VAPI_API_BASE_URL="https://api.vapi.ai" + + # EU organizations + export VAPI_API_BASE_URL="https://api.eu.vapi.ai" + ``` + **Example (using Zadarma):** ```bash - curl -X POST "https://api.vapi.ai/credential" \ + curl -X POST "$VAPI_API_BASE_URL/credential" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_VAPI_PRIVATE_KEY" \ -d '{ @@ -63,9 +79,11 @@ Vapi supports multiple SIP trunk configurations, including: Link your external phone number (DID) to the SIP trunk credential in Vapi by creating a Phone Number resource. + Use the same regional API base URL that you used when creating the SIP trunk credential. + **Example:** ```bash - curl -X POST "https://api.vapi.ai/phone-number" \ + curl -X POST "$VAPI_API_BASE_URL/phone-number" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_VAPI_PRIVATE_KEY" \ -d '{ @@ -85,20 +103,22 @@ Vapi supports multiple SIP trunk configurations, including: Initiate a call through the Vapi dashboard or API to ensure outbound calls are properly routed. **API Example:** - ```json - POST https://api.vapi.ai/call/phone - { - "assistantId": "YOUR_ASSISTANT_ID", - "customer": { - "number": "15557654321", - "numberE164CheckEnabled": false - }, - "phoneNumberId": "YOUR_PHONE_NUMBER_ID" - } + ```bash + curl -X POST "$VAPI_API_BASE_URL/call/phone" \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer YOUR_VAPI_PRIVATE_KEY" \ + -d '{ + "assistantId": "YOUR_ASSISTANT_ID", + "customer": { + "number": "15557654321", + "numberE164CheckEnabled": false + }, + "phoneNumberId": "YOUR_PHONE_NUMBER_ID" + }' ``` - If inbound routing is configured, call your phone number from an external line. Ensure your provider forwards calls to the correct SIP URI (e.g., `{phoneNumber}@.sip.vapi.ai` for Zadarma). + If inbound routing is configured, call your phone number from an external line. Ensure your provider forwards calls to the correct regional SIP URI (for example, `{phoneNumber}@.sip.vapi.ai` for US or `{phoneNumber}@.sip.eu.vapi.ai` for EU). Note: Please ensure that you provide all the signaling IP addresses when creating the SIP trunk. Failure to do so will prevent proper whitelisting, which may result in encountering unauthorized 401 errors for inbound calls. diff --git a/fern/advanced/sip/sip-twilio.mdx b/fern/advanced/sip/sip-twilio.mdx index 0a7136fbe..741afd1d6 100644 --- a/fern/advanced/sip/sip-twilio.mdx +++ b/fern/advanced/sip/sip-twilio.mdx @@ -39,9 +39,12 @@ This guide walks you through setting up both outbound and inbound SIP trunking b ![IP Authentication](../../static/images/sip/sip-twilio-ip-authentication.png) - Whitelist Vapi's SIP server static IPs: - - 44.229.228.186 - - 44.238.177.138 + Whitelist Vapi's SIP server static IPs for the Vapi region where your organization is hosted: + + | Region | SIP host | IP addresses | + | --- | --- | --- | + | US | `sip.vapi.ai` | `44.229.228.186`, `44.238.177.138` | + | EU | `sip.eu.vapi.ai` | `63.182.83.170` | Ensure you whitelist the entire IP range as shown below: @@ -57,13 +60,18 @@ This guide walks you through setting up both outbound and inbound SIP trunking b ### Vapi Configuration -1. **Retrieve Your Vapi API Key** +1. **Get your Vapi API key** - Log in to your Vapi.ai account and retrieve your API key from the Organization Settings. + Get a [Vapi API key](/security-and-privacy/api-keys) to authenticate the API requests in this guide. 2. **Create a SIP Trunk Credential** - Use the following API call to create a SIP trunk credential, replacing the gateway IP with your Twilio Termination SIP URI: + Use the following API call to create a SIP trunk credential. Configure the + Twilio termination hostname as an outbound-only gateway. Configure Twilio's + published signaling networks as separate inbound-only gateways. + + The example below uses a Dublin termination hostname with Twilio's Ireland + and Frankfurt signaling networks: ```bash curl -X POST https://api.vapi.ai/credential \ @@ -74,13 +82,48 @@ This guide walks you through setting up both outbound and inbound SIP trunking b "name": "Twilio Trunk", "gateways": [ { - "ip": "YOUR_TWILIO_GATEWAY_ID", - "inboundEnabled": false + "ip": "YOUR_TRUNK_NAME.pstn.dublin.twilio.com", + "port": 5060, + "inboundEnabled": false, + "outboundEnabled": true + }, + { + "ip": "54.171.127.192", + "netmask": 30, + "port": 5060, + "inboundEnabled": true, + "outboundEnabled": false + }, + { + "ip": "35.156.191.128", + "netmask": 30, + "port": 5060, + "inboundEnabled": true, + "outboundEnabled": false } ], "outboundLeadingPlusEnabled": true }' ``` + + + Replace the example hostname and networks with the values for your Twilio + trunk's selected edges. Add every primary and failover signaling network + that can originate calls. Use Twilio's current [Elastic SIP Trunking IP + address list](https://www.twilio.com/docs/sip-trunking/ip-addresses) as the + source of truth. + + + A termination hostname can be used for outbound routing because Vapi + resolves it when placing a call. It cannot identify inbound traffic: Vapi + must match the source of an incoming SIP request against a numeric IPv4 + network. The `netmask` value represents the CIDR prefix, so a `/30` network + is configured as `"netmask": 30`. + + If you are adding inbound gateways to an existing credential, send a + `PATCH /credential/YOUR_CREDENTIAL_ID` request with the complete `gateways` + array, including the existing outbound gateway and the new inbound + networks. Note the `id` (credentialId) from the response for the next step. @@ -137,7 +180,13 @@ This guide walks you through setting up both outbound and inbound SIP trunking b ![Origination Settings](../../static/images/sip/sip-twilio-origination.png) - Add your Vapi SIP URI in the following format: `sip:YOUR_PHONE_NUMBER@sip.vapi.ai`, where "YOUR_PHONE_NUMBER" is your chosen SIP number that you will attach to this trunk. + Add your Vapi SIP URI using the SIP host for your Vapi region: + + - US: `sip:YOUR_PHONE_NUMBER@.sip.vapi.ai` + - EU: `sip:YOUR_PHONE_NUMBER@.sip.eu.vapi.ai` + - TLS/SIPS: add port `5061` and `;transport=tls`, for example `sip:YOUR_PHONE_NUMBER@.sip.eu.vapi.ai:5061;transport=tls` + + `YOUR_PHONE_NUMBER` is your chosen SIP number that you will attach to this trunk. ![Origination Creation](../../static/images/sip/sip-twilio-origination-creation.png) @@ -149,3 +198,10 @@ This guide walks you through setting up both outbound and inbound SIP trunking b - In the assistant settings, link it to the phone number you created Now when someone calls your Twilio number, the call will be routed to your Vapi assistant. + + + If inbound calls do not reach Vapi, verify that the credential includes the + numeric Twilio signaling networks for every origination edge you configured. + Adding only the Twilio termination hostname enables outbound routing but does + not allowlist inbound SIP traffic. + diff --git a/fern/advanced/sip/sip-zadarma.mdx b/fern/advanced/sip/sip-zadarma.mdx index 21a843c93..481203919 100644 --- a/fern/advanced/sip/sip-zadarma.mdx +++ b/fern/advanced/sip/sip-zadarma.mdx @@ -7,11 +7,9 @@ slug: advanced/sip/zadarma Integrate your Zadarma SIP trunk with Vapi.ai to enable your AI voice assistants to handle calls efficiently. Follow the steps below to set up this integration: -## 1. Retrieve Your Vapi.ai Private Key +## 1. Get your Vapi private API key -- Log in to your Vapi.ai account. -- Navigate to **Organization Settings**. -- In the **API Keys** section, copy your **Private Key**. +Get a [Vapi private API key](/security-and-privacy/api-keys) to authenticate the API requests in this guide. ## 2. Add Your Zadarma SIP Credentials to Vapi.ai @@ -88,7 +86,7 @@ To forward incoming calls from your Zadarma virtual number to Vapi.ai: - Click the ⚙ (gear) icon next to your number. - Open the **External server** tab. - Enable **External server (SIP URI)**. -- Enter the address: `YOUR_VIRTUAL_NUMBER@sip.vapi.ai` (replace `YOUR_VIRTUAL_NUMBER` with your number in international format). +- Enter the address for your Vapi region: `YOUR_VIRTUAL_NUMBER@sip.vapi.ai` for US or `YOUR_VIRTUAL_NUMBER@sip.eu.vapi.ai` for EU. Replace `YOUR_VIRTUAL_NUMBER` with your number in international format. - Click **Save**. By following these steps, your Zadarma SIP trunk will be integrated with Vapi.ai, allowing your AI voice assistants to manage calls effectively. diff --git a/fern/advanced/sip/sip.mdx b/fern/advanced/sip/sip.mdx index 710acf016..9ddd8419a 100644 --- a/fern/advanced/sip/sip.mdx +++ b/fern/advanced/sip/sip.mdx @@ -8,6 +8,35 @@ slug: advanced/sip This guide shows you how to set up and test SIP calls to your Vapi assistant using any SIP client or softphone. You'll create an assistant, assign it a SIP phone number, and make a call using a SIP URI. You can also pass template variables via SIP headers. +## Choose your Vapi region + +Use the API base URL, private key, and SIP host from the same Vapi region. Do not create a SIP phone number in one region with a SIP URI from another region. + +| Region | Dashboard | API base URL | SIP host | +| --- | --- | --- | --- | +| United States | `dashboard.vapi.ai` | `https://api.vapi.ai` | `sip.vapi.ai` | +| European Union | `dashboard.eu.vapi.ai` | `https://api.eu.vapi.ai` | `sip.eu.vapi.ai` | + + +Vapi's EU support and self-serve growth are frozen until 2027. Existing EU customers can continue using their accounts, but Vapi is not offering new add-ons and does not guarantee feature parity with the US region. New self-serve customers should [create an account in the US region](https://dashboard.vapi.ai/register). If you require Vapi-hosted EU data residency, [contact Sales](https://vapi.ai/sales) about selective enterprise onboarding. + + +For existing EU organizations, create the SIP phone number against the EU API with an EU dashboard private key: + +```bash +curl -X POST https://api.eu.vapi.ai/phone-number \ + -H "Authorization: Bearer $VAPI_EU_PRIVATE_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "provider": "vapi", + "name": "EU SIP Assistant", + "sipUri": "sip:your_unique_user_name@sip.eu.vapi.ai", + "assistantId": "your_eu_assistant_id" + }' +``` + +If your SIP provider or firewall requires IP allowlisting, use the signalling IPs for your region from the [SIP networking and firewall configuration](/advanced/sip/sip-networking) reference. + Create an assistant with the `POST /assistant` endpoint. This is the same as creating an assistant for any other transport. @@ -20,7 +49,7 @@ This guide shows you how to set up and test SIP calls to your Vapi assistant usi - Create a SIP phone number with the `POST /phone-number` endpoint. + Create a SIP phone number with the `POST /phone-number` endpoint for your region. ```json { "provider": "vapi", @@ -29,7 +58,7 @@ This guide shows you how to set up and test SIP calls to your Vapi assistant usi } ``` - `sipUri` must be in the format `sip:username@sip.vapi.ai`. You can choose any username you like. + `sipUri` must be in the format `sip:username@`, where `` matches your Vapi region. You can choose any username you like. diff --git a/fern/advanced/sip/troubleshoot-sip-response-codes.mdx b/fern/advanced/sip/troubleshoot-sip-response-codes.mdx new file mode 100644 index 000000000..fe0903736 --- /dev/null +++ b/fern/advanced/sip/troubleshoot-sip-response-codes.mdx @@ -0,0 +1,129 @@ +--- +title: Troubleshoot SIP response codes +subtitle: Identify where a SIP request failed and what to check in Vapi, your provider, and your SIP infrastructure +description: Diagnose SIP response codes by response class, failure point, and call direction, then check the relevant Vapi, provider, network, or destination configuration. +slug: advanced/sip/troubleshoot-sip-response-codes +--- + +Session Initiation Protocol (SIP) response codes describe the result of a SIP request. They are standard protocol responses, not Vapi-specific error codes. + +A response can originate from Vapi, your SIP provider, your PBX or Session Border Controller (SBC), a downstream carrier, or the destination. The code identifies the type of response, but it does not always identify the root cause. Start with the response class, find the system that returned the response, and then check the relevant configuration. + + + Vapi's `endedReason` summarizes why the call ended. For some outbound SIP failures, it includes the response code directly. For example, if Vapi receives `403 Forbidden`, the call can have an `endedReason` of `call.in-progress.error-providerfault-outbound-sip-403-forbidden`. + + Vapi does not have a code-specific `endedReason` for every SIP response. For example, if Vapi receives `404 Not Found`, the call may have a generic SIP failure reason. The original response is still `404`. Only Vapi's summary is generic. Check your provider or PBX/SBC logs when the `endedReason` does not include the response code. + + +## Start in Vapi + + + + Open the [**Vapi Dashboard**](https://dashboard.vapi.ai/), then choose **Observe** > **Logs**. Choose the **Calls** tab, then choose the failed call. + + + + Record the call ID, timestamp, call direction, SIP provider, and `endedReason`. The direction determines which signaling path to inspect first. + + You can also retrieve `endedReason` from the [Call object](/api-reference/calls/get-call). + + - For an outbound call, start with Vapi and your outbound SIP provider. + - For an inbound call, start with the originating provider or PBX and the Vapi phone number or trunk configuration. + + + + If the `endedReason` contains a SIP response code, use that code as your starting point. If the ended reason is generic, check your provider, PBX, or SBC logs for the final response code and reason phrase. + + Record which system returned the response. The same code can have different causes when it comes from a different system. + + + + Use the first digit of the response code to identify the broad failure area, then use the exact code and provider logs to narrow the cause. + + + +## Understand the response class + +| Response class | What it indicates | Where to investigate | +| --- | --- | --- | +| `1xx` | The request was received and call setup is progressing. | Usually no action is needed. Investigate only if setup never reaches a final response. | +| `2xx` | The request succeeded. | Usually no action is needed. | +| `3xx` | The request was redirected. | Check the returned contact, SIP URI, routing rules, and redirect handling. | +| `4xx` | The responding system rejected or could not fulfill this request. | Check authentication, allowlists, addressing, routing, destination state, permissions, and account limits. | +| `5xx` | A server could not fulfill an apparently valid request. | Check provider status, routing availability, capacity, downstream services, and retry behavior. | +| `6xx` | The request cannot be fulfilled at any destination known to the responding system. | Check destination rejection, account policy, and carrier restrictions. | + + + A `4xx` response does not always mean that your application sent an invalid request. A provider can use a `4xx` response for account restrictions, call limits, routing rules, or destination state. Use the provider's reason phrase and call trace to identify the specific cause. + + +## Locate the likely failure point + +Use the response family to decide which part of the call path to inspect first. + +| Likely failure point | Common responses | Start with these checks | +| --- | --- | --- | +| Authentication or authorization | `401`, `403`, `407` | SIP credentials, digest authentication, IP allowlists, account status, caller ID permissions, and geographic permissions | +| Addressing or routing | `404`, `480`, `484` | Destination number or SIP URI, phone number assignment, dial plan, provider route, and endpoint registration | +| Destination state | `480`, `486`, `487`, `600`, `603` | Endpoint availability, busy state, do-not-disturb settings, cancellation source, and destination policy | +| Signaling or network timeout | `408`, `504` | DNS, firewall, signaling ports, transport protocol, provider reachability, and endpoint response | +| Media negotiation | `415`, `488`, `606` | Session Description Protocol (SDP), codecs, public media addresses, TLS, and Secure Real-time Transport Protocol (SRTP) settings | +| Provider or downstream server | `500`, `502`, `503`, `504` | Provider status, routing capacity, calls-per-second limits, concurrent-call limits, downstream carrier errors, and retry headers | + +## Troubleshoot common 4xx responses + +| Response | What it usually means | What to check | +| --- | --- | --- | +| `401 Unauthorized` | The destination server requests authentication. This can be a normal SIP challenge. | If the call fails, check the SIP username, password, authentication realm, and digest authentication. Confirm that a second authenticated request was sent. | +| `403 Forbidden` | The responding system understood the request but refused it. | Check credentials, caller ID and destination permissions, geographic restrictions, and account or trunk limits. For outbound calls, confirm that the provider allows Vapi's [SIP signaling IP addresses](/advanced/sip/sip-networking#sip-signalling). For inbound calls, confirm that the provider's source addresses match the gateways configured in Vapi. Do not retry until you identify the restriction. | +| `404 Not Found` | The responding system could not find the requested user or domain. | Check the number or SIP URI. For inbound calls, confirm that the called number is configured and assigned in Vapi. For outbound calls, confirm that the provider has a route to an active destination. | +| `407 Proxy Authentication Required` | A SIP proxy requests authentication. This can be a normal SIP challenge. | If the call fails, check the trunk username, password, authentication realm, and proxy configuration. Confirm that an authenticated request followed the challenge. | +| `408 Request Timeout` | The responding server could not produce a response in time. | Check DNS, firewall rules, signaling ports, transport protocol, and endpoint availability. Compare Vapi and provider timestamps to find the system that stopped responding. | +| `480 Temporarily Unavailable` | The destination is known but is currently unavailable, offline, unregistered, or set to do not disturb. | Check endpoint registration and routing. Retry later if the destination is expected to become available. | +| `484 Address Incomplete` | The request address is incomplete. | Check the destination number, country code, SIP URI user, and provider dialing format. Use E.164 format when required. | +| `486 Busy Here` | The destination was reached but is busy or cannot accept another call. | This is normally a destination state, not a Vapi configuration error. Retry later or follow your busy-call handling policy. | +| `487 Request Terminated` | The request was canceled before it completed. | Check the timeline or signaling trace to identify who sent the `CANCEL`. This is expected when the caller intentionally abandons the call. | +| `488 Not Acceptable Here` | The endpoint could not accept the proposed session or media configuration. | Check the SDP offer and answer, codecs, public media addresses, TLS, and SRTP. Review the [networking and firewall configuration](/advanced/sip/sip-networking). | + +## Troubleshoot common 5xx responses + +| Response | What it usually means | What to check | +| --- | --- | --- | +| `500 Server Internal Error` | The responding server encountered an unexpected condition. | Check the status and logs for the system that returned the response. If Vapi returned it, check the [Vapi status page](https://status.vapi.ai/). Retry after a short delay if the failure is temporary. | +| `502 Bad Gateway` | A gateway or proxy received an invalid response from a downstream server. | Check the responding system's routing logs and downstream details. Contact the operator of the gateway if you cannot inspect those logs. | +| `503 Service Unavailable` | The responding server is temporarily unavailable. Providers can also use this response for routing failures or call limits. | Check system status, account limits, trunk capacity, and available routes. Follow `Retry-After` when present. Use an alternate route when your provider supports failover. | +| `504 Server Time-out` | A server did not receive a timely response from a downstream server. | Check the responding system's downstream routing and destination reachability. Retry if the failure was temporary. | + +## Troubleshoot common 6xx responses + +| Response | What it usually means | What to check | +| --- | --- | --- | +| `600 Busy Everywhere` | The destination is busy across all endpoints known to the responding system. | Retry later according to your busy-call handling policy. | +| `603 Decline` | The destination or a system acting for it declined the request. | Check destination policy, provider account status, call blocking, and the provider-specific reason before retrying. | + +## If the response is still unclear + +The reason phrase and provider-specific details are important because different providers can use the same response code for different causes. The reason phrase is descriptive text and can vary between implementations, so do not build automated handling from the phrase alone. + +Collect the following information before contacting your SIP provider or [Vapi Support](/support): + +- Vapi call ID and organization ID +- Timestamp with timezone +- Inbound or outbound direction +- SIP provider and PBX or SBC product +- Exact SIP response code and reason phrase +- The system that returned the response, when known +- SIP Call-ID and a redacted signaling trace, when available +- The configuration checks and retries you already performed + +Do not include SIP passwords, API keys, or other secrets in logs or support requests. + +## Related resources + +- [Call end reasons](/calls/call-ended-reason) +- [Troubleshoot call errors](/calls/troubleshoot-call-errors) +- [SIP networking and firewall configuration](/advanced/sip/sip-networking) +- [Troubleshoot SIP trunk credential errors](/advanced/sip/troubleshoot-sip-trunk-credential-errors) +- [IETF RFC 3261](https://www.rfc-editor.org/rfc/rfc3261.html) +- [IANA SIP response code registry](https://www.iana.org/assignments/sip-parameters/sip-parameters.xhtml#sip-parameters-7) +- [Telnyx SIP response code quick reference](https://telnyx.com/resources/sip-response-codes-need-know-2-minutes) diff --git a/fern/advanced/sip/troubleshoot-sip-trunk-credential-errors.mdx b/fern/advanced/sip/troubleshoot-sip-trunk-credential-errors.mdx new file mode 100644 index 000000000..4447932a9 --- /dev/null +++ b/fern/advanced/sip/troubleshoot-sip-trunk-credential-errors.mdx @@ -0,0 +1,218 @@ +--- +title: "Troubleshoot SIP trunk credential errors" +subtitle: "Learn to resolve gateway creation failures when setting up a BYO SIP trunk" +slug: advanced/sip/troubleshoot-sip-trunk-credential-errors +--- + +## Overview + +This guide helps you resolve the `Couldn't validate SIP trunk credential. SIP gateway creation failed.` error when creating a BYO SIP trunk credential in Vapi. + +This error occurs during the gateway creation step of SIP trunk provisioning. Vapi's SBC (Session Border Controller) rejects the gateway configuration you provided. The sections below cover the most common causes and how to fix each one. + +**In this guide, you'll learn to:** + +- Identify the three most common causes of SIP trunk credential validation failures +- Understand when hostnames work (outbound) and when they don't (inbound) +- Resolve hostname-vs-IP, inbound-flag, and IP-allowlist issues +- Verify your gateway configuration against the full parameter reference + + + This guide focuses on the specific `SIP gateway creation failed` error. For + general SIP trunk setup instructions, see the + [SIP trunking](/advanced/sip/sip-trunk) page. + + +## Prerequisites + +Before you start troubleshooting, ensure you have: + +- A Vapi account with API access +- Your SIP provider's server address, username, and password +- Access to your SIP provider's admin panel (to check IP whitelisting) + +## Using a hostname for an inbound gateway + +This is the most common cause of this error. + +### What happens + +The `gateways[].ip` field accepts both hostnames (for example, `sip.example.com`) and IPv4 addresses (for example, `203.0.113.10`). However, the behavior differs depending on the call direction: + +- **Outbound gateways** — Hostnames and IPv4 addresses both work. Vapi resolves the hostname when routing outbound calls to your SIP provider. +- **Inbound gateways** — Only IPv4 addresses work. The SBC needs a numeric IP address to match incoming SIP requests to your trunk. When you provide a hostname with `inboundEnabled: true`, the SBC rejects the gateway configuration. + +### How to check + +Look at your gateway configuration. If `inboundEnabled` is `true` (or omitted, since it defaults to `true`) and the `ip` field contains a hostname (for example, `sip.example.com`), this is the cause of the error. + +### How to fix + +You have two options depending on whether you need inbound calling: + +**If you need inbound calling**, use the source signaling networks published by +your SIP provider. Providers can use different addresses for outbound routing +and inbound signaling, so do not assume that resolving an outbound hostname +returns the addresses that will originate inbound calls. + + + + +Check your provider's SIP trunking documentation for its inbound signaling IP +addresses or CIDR ranges. If your provider explicitly documents a stable +hostname as the source of inbound traffic, you can resolve it with: + +```bash title="Terminal" +dig +short sip.example.com A +``` + +```bash title="Terminal (alternative)" +nslookup sip.example.com +``` + +This returns one or more IPv4 addresses, for example `203.0.113.10`. Include +all primary and failover networks that can originate calls. + + + + + +Represent each provider network as a numeric IPv4 network address and, for a +CIDR range, set `netmask` to its prefix length: + +```json title="Gateway configuration" +{ + "provider": "byo-sip-trunk", + "name": "my sip trunk", + "gateways": [ + { + "ip": "203.0.113.8", + "netmask": 30, + "port": 5060, + "outboundEnabled": false, + "inboundEnabled": true + } + ] +} +``` + + + + + + In this example, `203.0.113.8/30` is written as `"ip": "203.0.113.8"` and + `"netmask": 30`. If your provider changes its signaling networks, update the + gateway configuration to match. + + +**If you only need outbound calling**, you can keep the hostname and disable inbound: + +```json title="Gateway configuration" +{ + "provider": "byo-sip-trunk", + "name": "my sip trunk", + "gateways": [ + { + "ip": "sip.example.com", + "port": 5060, + "outboundEnabled": true, + "inboundEnabled": false + } + ] +} +``` + +## Inbound enabled on an outbound-only trunk + +### What happens + +The `inboundEnabled` gateway option defaults to `true`. If your SIP trunk is outbound-only (you only make calls through it, you do not receive inbound calls through Vapi), having inbound enabled can cause gateway creation to fail with some providers. + +### How to check + +Look at your API request. If you did not set `inboundEnabled` explicitly, it defaulted to `true`. If you only need outbound calling, this is likely the problem. + +### How to fix + +Set `inboundEnabled` to `false` in your gateway configuration: + +```json title="Gateway configuration" +{ + "provider": "byo-sip-trunk", + "name": "my sip trunk", + "gateways": [ + { + "ip": "203.0.113.10", + "port": 5060, + "outboundEnabled": true, + "inboundEnabled": false + } + ] +} +``` + + + If you are using the Vapi dashboard, uncheck the **Inbound** option when + configuring the gateway. + + +## Carrier IP allowlist not configured + +### What happens + +Your SIP provider needs to allow traffic from Vapi's SBC IP addresses. If these IPs are not on the allowlist, the SBC's registration and signaling requests to your provider are blocked, and gateway creation fails. + +### How to check + +Ask your SIP provider whether the Vapi SBC IP addresses for your region are on their allowlist: + +| Region | SIP host | IP addresses | +| --- | --- | --- | +| US | `sip.vapi.ai` | `44.229.228.186/32`, `44.238.177.138/32` | +| EU | `sip.eu.vapi.ai` | `63.182.83.170/32` | + +### How to fix + +Ask your SIP provider to add the Vapi SBC IP addresses for your region to their allowlist: + +| Region | IP address | Netmask | +| --- | --- | --- | +| US | `44.229.228.186` | `/32` | +| US | `44.238.177.138` | `/32` | +| EU | `63.182.83.170` | `/32` | + + + US organizations must allow both US addresses. Vapi may use either one for signaling, so missing one can cause intermittent failures. EU organizations should allow `63.182.83.170`. + + +## Gateway configuration reference + +The table below lists all available options for each entry in the `gateways` array. + +| Option | Type | Default | Description | +| -------------------- | ------- | --------- | ------------------------------------------------------------------------------ | +| `ip` | string | (required)| IPv4 address or hostname of your SIP gateway. Hostnames work for outbound-only gateways. Inbound gateways require a numeric IPv4 address.| +| `port` | number | `5060` | SIP signaling port. | +| `netmask` | number | `32` | Subnet mask for inbound IP matching. Valid range: 24 to 32. | +| `inboundEnabled` | boolean | `true` | Whether this gateway accepts inbound calls. Set to `false` for outbound-only trunks. | +| `outboundEnabled` | boolean | `true` | Whether outbound calls route through this gateway. | +| `outboundProtocol` | string | `"udp"` | Signaling protocol. Options: `udp`, `tcp`, `tls`, `tls/srtp`. | +| `optionsPingEnabled` | boolean | `false` | Whether to send SIP OPTIONS pings to check if the gateway is reachable. | + +## If the error persists + +If none of the above resolves your issue, gather the following information and contact Vapi support: + +- Your organization ID +- The exact error message you received +- The full request payload you sent (redact the password) +- Your SIP provider name and server address +- Whether you are setting up for inbound calls, outbound calls, or both + +## Next steps + +Now that you can troubleshoot SIP trunk credential errors: + +- **Review SIP trunk setup:** Follow the complete [SIP trunking](/advanced/sip/sip-trunk) guide to verify your configuration end-to-end +- **Configure a provider:** Set up your SIP trunk with a specific provider such as [Twilio](/advanced/sip/twilio), [Telnyx](/advanced/sip/telnyx), [Zadarma](/advanced/sip/zadarma), or [Plivo](/advanced/sip/plivo) +- **Learn about SIP telephony:** Explore the [SIP telephony](/advanced/sip) overview for broader SIP integration options diff --git a/fern/apis/api/ai_examples_override.yml b/fern/apis/api/ai_examples_override.yml new file mode 100644 index 000000000..bed285b49 --- /dev/null +++ b/fern/apis/api/ai_examples_override.yml @@ -0,0 +1,899 @@ +paths: + /observability/scorecard/id: + patch: + x-fern-examples: + - path-parameters: + id: id + response: + body: + id: scd_9f8b7c6d5e4a3b2c1d0e + orgId: org_1234567890abcdef + createdAt: '2024-01-15T09:30:00Z' + updatedAt: '2024-01-15T09:30:00Z' + name: Customer Support Quality Scorecard + description: Scorecard to evaluate customer support call quality based on key metrics. + metrics: + - structuredOutputId: metric_001 + conditions: + - {} + assistantIds: + - assistant_abc123xyz + delete: + x-fern-examples: + - path-parameters: + id: id + response: + body: + id: sc-9f8b7c6d5e4a3b2c1d0e + orgId: org-1234567890abcdef + createdAt: '2024-01-15T09:30:00Z' + updatedAt: '2024-01-15T09:30:00Z' + name: Customer Support Quality Scorecard + description: Scorecard to evaluate the quality of customer support calls based on key metrics. + metrics: + - structuredOutputId: metric-00123abc + conditions: + - comparator: '>=' + value: 80 + points: 50 + - comparator: < + value: 80 + points: 20 + assistantIds: + - assistant-9876543210fedcba + get: + x-fern-examples: + - path-parameters: + id: id + response: + body: + id: a3f47b2e-9c4d-4f1a-8b2e-3d7f9a1c5e6b + orgId: org-9f8d7c6b5a4e3d2c1b0a + createdAt: '2024-01-15T09:30:00Z' + updatedAt: '2024-04-20T14:45:00Z' + name: Customer Support Quality Scorecard + description: Scorecard to evaluate the quality of customer support calls based on response accuracy and sentiment analysis. + metrics: + - structuredOutputId: metric-1234abcd-5678-efgh-9012-ijklmnopqrst + conditions: + - comparator: '>=' + value: 85 + points: 50 + description: Score above 85 grants 50 points + - comparator: < + value: 85 + points: 20 + description: Score below 85 grants 20 points + assistantIds: + - assistant-0011223344556677 + /file: + get: + x-fern-examples: + - response: + body: + - object: file + status: processing + name: Meeting Transcript + originalName: meeting_2024_04_20.mp3 + bytes: 5242880 + purpose: transcription + mimetype: audio/mpeg + key: files/2024/04/meeting_2024_04_20.mp3 + path: /files/2024/04/meeting_2024_04_20.mp3 + bucket: vapi-audio-uploads + url: https://vapi-audio-uploads.s3.amazonaws.com/files/2024/04/meeting_2024_04_20.mp3 + parsedTextUrl: https://vapi-text-outputs.s3.amazonaws.com/files/2024/04/meeting_2024_04_20.txt + parsedTextBytes: 102400 + metadata: + durationSeconds: 3600 + language: en-US + id: f47ac10b-58cc-4372-a567-0e02b2c3d479 + orgId: org_9a8b7c6d5e4f3g2h1i0j + createdAt: '2024-01-15T09:30:00Z' + updatedAt: '2024-01-15T09:30:00Z' + post: + x-fern-examples: + - request: + file: base64-encoded-pdf-content + response: + body: + object: file + status: processing + name: ProjectProposal.pdf + originalName: ProjectProposal_2024.pdf + bytes: 245760 + purpose: knowledge_base_upload + mimetype: application/pdf + key: files/2024/04/27/projectproposal_2024.pdf + path: /files/2024/04/27/projectproposal_2024.pdf + bucket: vapi-uploads + url: https://cdn.vapi.ai/files/2024/04/27/projectproposal_2024.pdf + parsedTextUrl: https://cdn.vapi.ai/files/2024/04/27/projectproposal_2024.txt + parsedTextBytes: 10240 + metadata: {} + id: f47ac10b-58cc-4372-a567-0e02b2c3d479 + orgId: a12b34c5-d678-90ef-1234-56789abcdef0 + createdAt: '2024-01-15T09:30:00Z' + updatedAt: '2024-01-15T09:30:00Z' + /file/id: + patch: + x-fern-examples: + - path-parameters: + id: id + response: + body: + object: file + status: processing + name: Meeting_Recording_Jan2024.mp3 + originalName: meeting_recording_2024_01_15.mp3 + bytes: 5242880 + purpose: transcription + mimetype: audio/mpeg + key: files/2024/01/15/meeting_recording_2024_01_15.mp3 + path: /files/2024/01/15/meeting_recording_2024_01_15.mp3 + bucket: vapi-audio-uploads + url: https://vapi-audio-uploads.s3.amazonaws.com/files/2024/01/15/meeting_recording_2024_01_15.mp3 + parsedTextUrl: https://vapi-text-outputs.s3.amazonaws.com/files/2024/01/15/meeting_recording_2024_01_15.txt + parsedTextBytes: 10240 + metadata: {} + id: f47ac10b-58cc-4372-a567-0e02b2c3d479 + orgId: a12b34cd-56ef-78gh-90ij-klmnopqrstuv + createdAt: '2024-01-15T09:30:00Z' + updatedAt: '2024-01-15T09:30:00Z' + get: + x-fern-examples: + - path-parameters: + id: id + response: + body: + object: file + status: processing + name: Meeting_Audio_Recording + originalName: meeting_recording_2024_04_20.mp3 + bytes: 5242880 + purpose: transcription + mimetype: audio/mpeg + key: audio/2024/04/20/meeting_recording_2024_04_20.mp3 + path: /audio/2024/04/20/meeting_recording_2024_04_20.mp3 + bucket: vapi-audio-files + url: https://vapi-audio-files.s3.amazonaws.com/audio/2024/04/20/meeting_recording_2024_04_20.mp3 + parsedTextUrl: https://vapi-audio-files.s3.amazonaws.com/transcripts/2024/04/20/meeting_recording_2024_04_20.txt + parsedTextBytes: 102400 + metadata: + durationSeconds: 3600 + language: en-US + speakerCount: 3 + id: f47ac10b-58cc-4372-a567-0e02b2c3d479 + orgId: org_9a8b7c6d5e4f3g2h1i0j + createdAt: '2024-01-15T09:30:00Z' + updatedAt: '2024-01-15T09:30:00Z' + delete: + x-fern-examples: + - path-parameters: + id: id + response: + body: + object: file + status: done + name: Meeting_Transcript_Jan2024.txt + originalName: transcript_2024_01_15.txt + bytes: 24576 + purpose: transcription + mimetype: text/plain + key: files/2024/01/15/meeting_transcript_12345.txt + path: /2024/01/15/meeting_transcript_12345.txt + bucket: vapi-user-uploads + url: https://cdn.vapi.ai/files/2024/01/15/meeting_transcript_12345.txt + parsedTextUrl: https://cdn.vapi.ai/parsed/2024/01/15/meeting_transcript_12345.txt + parsedTextBytes: 23000 + metadata: + language: en + durationSeconds: 3600 + speakerCount: 3 + id: f47ac10b-58cc-4372-a567-0e02b2c3d479 + orgId: org_9a8b7c6d5e4f3g2h1i0j + createdAt: '2024-01-15T09:30:00Z' + updatedAt: '2024-01-15T10:00:00Z' + /provider/cartesia/pronunciation-dictionary: + post: + x-fern-examples: + - path-parameters: + provider: cartesia + resourceName: pronunciation-dictionary + response: + body: + id: a3f1c9d2-7b4e-4f8a-9c3d-2e5b7f6a1d9e + orgId: org_987654321 + createdAt: '2024-01-15T09:30:00Z' + updatedAt: '2024-01-15T09:30:00Z' + provider: cartesia + resourceName: pronunciation-dictionary + resourceId: dict_123456789 + resource: + entries: + - word: example + pronunciation: ɪɡˈzæmpəl + - word: pronunciation + pronunciation: prəˌnʌnsiˈeɪʃən + language: en-US + version: '1.0' + get: + x-fern-examples: + - path-parameters: + provider: cartesia + resourceName: pronunciation-dictionary + response: + body: + results: + - id: a3f1c9d2-7b4e-4f8a-9d3e-2b5f6c7d8e9f + orgId: org-9876543210 + createdAt: '2024-01-15T09:30:00Z' + updatedAt: '2024-01-15T09:30:00Z' + provider: cartesia + resourceName: pronunciation-dictionary + resourceId: dict-1234567890 + resource: + entries: + - word: quixotic + pronunciation: kwɪkˈsɒtɪk + audioUrl: https://cdn.cartesia.ai/pronunciations/quixotic.mp3 + - word: ephemeral + pronunciation: ɪˈfɛmərəl + audioUrl: https://cdn.cartesia.ai/pronunciations/ephemeral.mp3 + language: en-US + version: 1.2.0 + metadata: + itemsPerPage: 10 + totalItems: 57 + currentPage: 1 + itemsBeyondRetention: false + createdAtLe: '2024-01-15T09:30:00Z' + createdAtGe: '2023-12-01T00:00:00Z' + /reporting/insight: + get: + x-fern-examples: + - response: + body: + results: + - name: Monthly Revenue Overview + type: bar + id: a1b2c3d4-e5f6-7890-abcd-1234567890ef + orgId: org-9876543210 + createdAt: '2024-01-15T09:30:00Z' + updatedAt: '2024-01-15T09:30:00Z' + metadata: + itemsPerPage: 10 + totalItems: 50 + currentPage: 1 + itemsBeyondRetention: false + createdAtLe: '2024-01-15T09:30:00Z' + createdAtGe: '2023-12-01T00:00:00Z' + /provider/cartesia/pronunciation-dictionary/id: + get: + x-fern-examples: + - path-parameters: + provider: cartesia + resourceName: pronunciation-dictionary + id: id + response: + body: + id: 3fa85f64-5717-4562-b3fc-2c963f66afa6 + orgId: a1b2c3d4-e5f6-7890-abcd-ef1234567890 + createdAt: '2024-01-15T09:30:00Z' + updatedAt: '2024-01-15T09:30:00Z' + provider: cartesia + resourceName: pronunciation-dictionary + resourceId: dict-987654321 + resource: + entries: + - word: quixotic + pronunciation: kwɪkˈsɒtɪk + audioUrl: https://cdn.cartesia.ai/pronunciations/quixotic.mp3 + - word: ephemeral + pronunciation: ɪˈfɛmərəl + audioUrl: https://cdn.cartesia.ai/pronunciations/ephemeral.mp3 + language: en-US + version: 1.2.3 + patch: + x-fern-examples: + - path-parameters: + provider: cartesia + resourceName: pronunciation-dictionary + id: id + response: + body: + id: 3fa85f64-5717-4562-b3fc-2c963f66afa6 + orgId: a1b2c3d4-e5f6-7890-abcd-ef1234567890 + createdAt: '2024-01-15T09:30:00Z' + updatedAt: '2024-01-15T09:30:00Z' + provider: cartesia + resourceName: pronunciation-dictionary + resourceId: dict-987654321 + resource: + entries: + - word: example + pronunciation: ɪɡˈzæmpəl + - word: pronunciation + pronunciation: prəˌnʌnsiˈeɪʃən + language: en-US + version: 1.2.3 + delete: + x-fern-examples: + - path-parameters: + provider: cartesia + resourceName: pronunciation-dictionary + id: id + response: + body: + id: d290f1ee-6c54-4b01-90e6-d701748f0851 + orgId: a1b2c3d4-e5f6-7890-abcd-ef1234567890 + createdAt: '2024-01-15T09:30:00Z' + updatedAt: '2024-01-15T09:30:00Z' + provider: cartesia + resourceName: pronunciation-dictionary + resourceId: dict-9876543210 + resource: + entries: + - word: example + pronunciation: ɪɡˈzæmpəl + - word: pronunciation + pronunciation: prəˌnʌnsiˈeɪʃən + language: en-US + version: 1.2.3 + /reporting/insight/id/run: + post: + x-fern-examples: + - path-parameters: + id: id + response: + body: + id: a1b2c3d4-e5f6-7890-ab12-cd34ef567890 + insightId: insight-9876543210 + orgId: org-1234567890 + createdAt: '2024-01-15T09:30:00Z' + updatedAt: '2024-01-15T09:30:00Z' + /structured-output/id: + get: + x-fern-examples: + - path-parameters: + id: id + response: + body: + type: ai + regex: \d{3}-\d{2}-\d{4} + model: + provider: openai + model: gpt-5.4 + temperature: 1.1 + maxTokens: 5030 + compliancePlan: + forceStoreOnHipaaEnabled: false + id: a3f47b9e-8c2d-4f1a-9b7e-2d5f3c6a7b8d + orgId: org-9f8e7d6c5b4a3 + createdAt: '2024-01-15T09:30:00Z' + updatedAt: '2024-01-15T09:30:00Z' + name: Customer Feedback Extraction + description: Extracts customer feedback details including sentiment and key topics from conversation transcripts. + assistantIds: + - assistant-12345 + workflowIds: + - workflow-67890 + schema: + type: object + properties: + customerName: + type: string + description: Name of the customer providing feedback. + feedbackDate: + type: string + format: date-time + description: Date and time when the feedback was given. + rating: + type: integer + description: Customer rating from 1 to 5. + comments: + type: string + description: Additional comments provided by the customer. + topics: + type: array + description: List of key topics mentioned in the feedback. + required: + - customerName + - feedbackDate + - rating + description: Schema defining the structure of extracted customer feedback data. + title: CustomerFeedbackSchema + delete: + x-fern-examples: + - path-parameters: + id: id + response: + body: + type: ai + regex: \d{3}-\d{2}-\d{4} + model: + provider: openai + model: gpt-5.4 + temperature: 1.1 + maxTokens: 5030 + compliancePlan: + forceStoreOnHipaaEnabled: false + id: a3f47b9e-8c2d-4f1a-9b7e-2d5f3c9a1b2e + orgId: org-9f8e7d6c5b4a3 + createdAt: '2024-01-15T09:30:00Z' + updatedAt: '2024-01-15T09:30:00Z' + name: Customer SSN Extractor + description: Extracts Social Security Numbers from call transcripts for verification purposes. + assistantIds: + - assistant-12345 + workflowIds: + - workflow-67890 + schema: + type: string + description: A US Social Security Number in the format XXX-XX-XXXX. + pattern: ^\d{3}-\d{2}-\d{4}$ + format: date-time + required: + - ssn + enum: + - 123-45-6789 + - 987-65-4321 + title: SSN Schema + items: {} + properties: {} + patch: + x-fern-examples: + - path-parameters: + id: id + query-parameters: + schemaOverride: schemaOverride + response: + body: + type: ai + regex: \d{3}-\d{2}-\d{4} + model: + provider: openai + model: gpt-5.4 + temperature: 1.1 + maxTokens: 5030 + compliancePlan: + forceStoreOnHipaaEnabled: false + id: a1b2c3d4-e5f6-7890-abcd-ef1234567890 + orgId: org-9876543210 + createdAt: '2024-01-15T09:30:00Z' + updatedAt: '2024-01-15T09:30:00Z' + name: Customer Data Extractor + description: Extracts customer information such as SSN from conversation transcripts for compliance and analytics. + assistantIds: + - assistant-1234abcd + workflowIds: + - workflow-5678efgh + schema: + type: string + items: {} + properties: {} + description: A string representing a date and time in ISO 8601 format. + pattern: ^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$ + format: date-time + required: + - timestamp + enum: + - '2024-01-15T09:30:00Z' + - '2024-01-16T10:00:00Z' + title: TimestampSchema + /eval/id: + get: + x-fern-examples: + - path-parameters: + id: id + response: + body: + messages: + - role: assistant + content: Welcome to the verified user flow. How can I assist you today? + toolCalls: + - name: verify_user_status + arguments: + userId: '12345' + id: a3f1c9e2-7b4d-4f8a-9c3e-2d5f6b7a8c9d + orgId: org_987654321 + createdAt: '2024-01-15T09:30:00Z' + updatedAt: '2024-01-15T09:30:00Z' + name: Verified User Flow Eval + description: This eval checks if the user flow is verified. + type: chat.mockConversation + delete: + x-fern-examples: + - path-parameters: + id: id + response: + body: + messages: + - role: assistant + content: Welcome to the verified user flow. How can I assist you today? + toolCalls: + - name: verify_user_status + arguments: + userId: '12345' + id: a3f1c9e2-7b4d-4f8a-9c3e-2d5f6b7a8c9d + orgId: org_987654321 + createdAt: '2024-01-15T09:30:00Z' + updatedAt: '2024-01-15T09:30:00Z' + name: Verified User Flow Eval + description: This eval checks if the user flow is verified. + type: chat.mockConversation + patch: + x-fern-examples: + - path-parameters: + id: id + response: + body: + messages: + - role: assistant + id: a1b2c3d4-e5f6-7890-ab12-cd34ef567890 + orgId: org-1234567890abcdef + createdAt: '2024-01-15T09:30:00Z' + updatedAt: '2024-01-15T09:30:00Z' + name: Verified User Flow Eval + description: This eval checks if the user flow is verified. + type: chat.mockConversation + /analytics: + post: + x-fern-examples: + - request: + queries: + - table: call + name: Total Call Duration + operations: + - operation: sum + column: duration + response: + body: + - name: Total Call Duration + timeRange: + step: hour + start: '2024-04-01T00:00:00Z' + end: '2024-04-07T23:59:59Z' + timezone: UTC + result: + - {} + /eval: + post: + x-fern-examples: + - request: + messages: + - role: assistant + type: chat.mockConversation + response: + body: + messages: + - role: assistant + id: a1b2c3d4-e5f6-7890-abcd-ef1234567890 + orgId: org-9876543210 + createdAt: '2024-01-15T09:30:00Z' + updatedAt: '2024-01-15T09:30:00Z' + name: Verified User Flow Eval + description: This eval checks if the user flow is verified. + type: chat.mockConversation + /call/id/customer-recording: + get: + x-fern-examples: + - path-parameters: + id: id + /call/id/pcap: + get: + x-fern-examples: + - path-parameters: + id: id + /call/id/assistant-recording: + get: + x-fern-examples: + - path-parameters: + id: 3fa85f64-5717-4562-b3fc-2c963f66afa6 + /call/id/stereo-recording: + get: + x-fern-examples: + - path-parameters: + id: 3fa85f64-5717-4562-b3fc-2c963f66afa6 + /call/id/video-recording: + get: + x-fern-examples: + - path-parameters: + id: id + /call/id/mono-recording: + get: + x-fern-examples: + - path-parameters: + id: 3fa85f64-5717-4562-b3fc-2c963f66afa6 + /call/id/call-logs: + get: + x-fern-examples: + - path-parameters: + id: id + /reporting/board/id: + delete: + x-fern-examples: + - path-parameters: + id: id + response: + body: + items: + - type: insight + insightId: a3f1c9d2-4b7e-4f8a-9c3d-2e5b7f6a8d9e + systemKey: sys-key-12345 + position: + x: 2 + 'y': 3 + size: + width: 4 + height: 2 + id: d290f1ee-6c54-4b01-90e6-d701748f0851 + orgId: org-7890abcd-1234-5678-efgh-9012ijklmnop + createdAt: '2024-01-15T09:30:00Z' + updatedAt: '2024-04-20T15:45:00Z' + systemKey: system-board-001 + name: Sales Performance Dashboard + layout: + columns: 6 + timeRangeOverride: + step: day + start: '-30d' + end: now + timezone: America/New_York + patch: + x-fern-examples: + - path-parameters: + id: id + response: + body: + items: + - type: insight + insightId: a1b2c3d4-e5f6-7890-ab12-cd34ef567890 + systemKey: sys_insight_001 + position: + x: 2 + 'y': 3 + size: + width: 4 + height: 3 + id: f47ac10b-58cc-4372-a567-0e02b2c3d479 + orgId: 9f8e7d6c-5b4a-3210-9876-54321fedcba0 + createdAt: '2024-01-15T09:30:00Z' + updatedAt: '2024-04-20T14:45:00Z' + systemKey: board_sys_123 + name: Sales Performance Dashboard + layout: + columns: 6 + timeRangeOverride: + step: day + start: '-7d' + end: now + timezone: UTC + get: + x-fern-examples: + - path-parameters: + id: id + response: + body: + items: + - type: insight + insightId: a3f1c9d2-4b7e-4f8a-9c3d-2e5b7f8a1c2d + systemKey: insight_system_key_01 + position: + x: 2 + 'y': 3 + size: + width: 4 + height: 3 + id: d290f1ee-6c54-4b01-90e6-d701748f0851 + orgId: f47ac10b-58cc-4372-a567-0e02b2c3d479 + createdAt: '2024-01-15T09:30:00Z' + updatedAt: '2024-01-15T09:30:00Z' + systemKey: board_system_key_123 + name: Sales Performance Dashboard + layout: + columns: 6 + timeRangeOverride: + step: hour + start: '-7d' + end: now + timezone: America/New_York + /reporting/board: + post: + x-fern-examples: + - request: + name: Sales Performance Dashboard + layout: + columns: 6 + response: + body: + items: + - type: insight + insightId: insight-9f8b7c6d-1234-4a56-b789-0a1b2c3d4e5f + systemKey: syskey-analytics-001 + position: + x: 0 + 'y': 0 + size: + width: 3 + height: 2 + id: board-7a6b5c4d-9876-4321-0fed-cba987654321 + orgId: org-12345678-abcd-efgh-ijkl-9876543210ab + createdAt: '2024-01-15T09:30:00Z' + updatedAt: '2024-01-15T09:30:00Z' + systemKey: syskey-board-001 + name: Sales Performance Dashboard + layout: + columns: 6 + timeRangeOverride: + step: day + start: '-7d' + end: now + timezone: UTC + get: + x-fern-examples: + - response: + body: + results: + - items: + - type: insight + insightId: a1b2c3d4-e5f6-7890-abcd-ef1234567890 + systemKey: sys-board-insight-001 + position: + x: 0 + 'y': 0 + size: + width: 3 + height: 2 + id: board-1234abcd-5678-ef90-gh12-ijklmnopqrst + orgId: org-9876zyxw-5432-vuts-rqpo-nmlkjihgfedc + createdAt: '2024-01-15T09:30:00Z' + updatedAt: '2024-01-15T09:30:00Z' + systemKey: sys-board-001 + name: Executive Summary Dashboard + layout: + columns: 6 + timeRangeOverride: + step: day + start: '-7d' + end: now + timezone: UTC + metadata: + itemsPerPage: 25 + totalItems: 150 + currentPage: 1 + totalPages: 6 + hasNextPage: true + nextCursor: cursor_abcdef123456 + sortOrder: DESC + itemsBeyondRetention: false + createdAtLe: '2024-01-15T09:30:00Z' + createdAtGe: '2023-12-15T09:30:00Z' + /reporting/board/default/metrics-overview: + get: + x-fern-examples: + - response: + body: + items: + - type: insight + insightId: a1b2c3d4-e5f6-7890-ab12-cd34ef567890 + systemKey: sys_insight_001 + position: + x: 2 + 'y': 3 + size: + width: 4 + height: 3 + id: board_9876543210abcdef + orgId: org_1234567890abcdef + createdAt: '2024-01-15T09:30:00Z' + updatedAt: '2024-04-20T15:45:00Z' + systemKey: sys_board_default_metrics + name: Default Metrics Overview + layout: + columns: 6 + timeRangeOverride: + step: day + start: '-7d' + end: now + timezone: UTC + /observability/scorecard: + post: + x-fern-examples: + - request: + metrics: + - conditions: + - type: comparator + comparator: '=' + value: 1 + points: 10 + - type: comparator + comparator: '>' + value: 5 + points: 20 + - type: comparator + comparator: <= + value: 3 + points: 15 + structuredOutputId: call_duration_seconds + - conditions: + - type: comparator + comparator: '=' + value: 1 + points: 30 + structuredOutputId: agent_satisfaction + - conditions: + - type: comparator + comparator: '=' + value: 0 + points: 5 + structuredOutputId: call_dropped + response: + body: + id: a3f47b9e-8c2d-4f1a-9b7e-2d3f5c6a7b8d + orgId: org_9f8e7d6c5b4a3210 + createdAt: '2024-01-15T09:30:00Z' + updatedAt: '2024-01-15T09:30:00Z' + name: Customer Support Quality Scorecard + description: Scorecard to evaluate call metrics and agent performance for customer support calls. + metrics: + - conditions: + - type: comparator + comparator: '=' + value: 1 + points: 10 + - type: comparator + comparator: '>' + value: 5 + points: 20 + - type: comparator + comparator: <= + value: 3 + points: 15 + structuredOutputId: call_duration_seconds + - conditions: + - type: comparator + comparator: '=' + value: 1 + points: 30 + structuredOutputId: agent_satisfaction + - conditions: + - type: comparator + comparator: '=' + value: 0 + points: 5 + structuredOutputId: call_dropped + assistantIds: + - assistant_12345abcde + - assistant_67890fghij + get: + x-fern-examples: + - response: + body: + results: + - id: a3f1c9d2-4b7e-4f8a-9c3d-2e5b7f1a9c8d + orgId: d9f8e7c6-b5a4-4321-9f8e-7d6c5b4a3f2e + createdAt: '2024-01-15T09:30:00Z' + updatedAt: '2024-01-15T09:30:00Z' + name: Customer Support Quality Scorecard + description: Scorecard evaluating key customer support call metrics for Q1 2024. + metrics: + - conditions: + - type: comparator + comparator: '=' + value: 1 + points: 10 + structuredOutputId: metric-voice-quality-001 + assistantIds: + - assistant-1234abcd + metadata: + itemsPerPage: 10 + totalItems: 45 + currentPage: 1 + totalPages: 5 + hasNextPage: true + nextCursor: eyJjdXJzb3IiOiIyMDI0LTAxLTE1VDA5OjMwOjAwWiJ9 + sortOrder: ASC + itemsBeyondRetention: false + createdAtLe: '2024-01-15T09:30:00Z' + createdAtGe: '2023-12-01T00:00:00Z' diff --git a/fern/apis/api/generators.yml b/fern/apis/api/generators.yml index 4a3b5c409..f9bc714a1 100644 --- a/fern/apis/api/generators.yml +++ b/fern/apis/api/generators.yml @@ -1,7 +1,9 @@ + api: specs: - openapi: ./openapi.json overrides: ./openapi-overrides.yml + overlays: ./openapi-parameter-descriptions-overlay.yml origin: https://api.vapi.ai/api-json settings: title-as-schema-name: false @@ -11,33 +13,36 @@ groups: python-sdk: generators: - name: fernapi/fern-python-sdk - version: 4.23.2 + version: 5.3.3 api: settings: - unions: v1 + prefer-undiscriminated-unions-with-literals: true output: location: pypi - package-name: "vapi_server_sdk" + package-name: vapi_server_sdk token: ${PYPI_TOKEN} github: repository: VapiAI/server-sdk-python + mode: pull-request config: pydantic_config: skip_validation: true client_class_name: Vapi + smart-casing: false ts-sdk: generators: - - name: fernapi/fern-typescript-node-sdk - version: 2.1.0 + - name: fernapi/fern-typescript-sdk + version: 3.63.0 api: settings: - unions: v1 + prefer-undiscriminated-unions-with-literals: true output: location: npm - package-name: "@vapi-ai/server-sdk" - token: ${NPM_TOKEN} + package-name: '@vapi-ai/server-sdk' + token: OIDC github: repository: VapiAI/server-sdk-typescript + mode: pull-request config: namespaceExport: Vapi allowCustomFetcher: true @@ -45,57 +50,45 @@ groups: includeApiReference: true noSerdeLayer: true omitUndefined: true + enableInlineTypes: false smart-casing: true - java-sdk: - generators: - - name: fernapi/fern-java-sdk - version: 2.38.6 - disable-examples: true - output: - location: maven - coordinate: dev.vapi:server-sdk - username: ${MAVEN_USERNAME} - password: ${MAVEN_PASSWORD} - signature: - keyId: ${MAVEN_CENTRAL_SECRET_KEY_KEY_ID} - password: ${MAVEN_CENTRAL_SECRET_KEY_PASSWORD} - secretKey: ${MAVEN_CENTRAL_SECRET_KEY} - github: - repository: VapiAI/server-sdk-java - config: - client-class-name: Vapi go-sdk: generators: - name: fernapi/fern-go-sdk - version: 1.4.0 + version: 1.33.5 disable-examples: true api: settings: - unions: v1 + prefer-undiscriminated-unions-with-literals: true github: repository: VapiAI/server-sdk-go + mode: pull-request config: union: v1 + smart-casing: false ruby-sdk: generators: - name: fernapi/fern-ruby-sdk - version: 0.8.2 + version: 1.1.13 disable-examples: true github: repository: VapiAI/server-sdk-ruby + mode: pull-request output: location: rubygems - package-name: vapi-server-sdk - api-key: ${RUBYGEMS_API_KEY} + package-name: vapi_server_sdk config: clientClassName: Vapi + rubocopVariableNumberStyle: disabled + smart-casing: false csharp-sdk: generators: - name: fernapi/fern-csharp-sdk - version: 2.0.2 + version: 2.58.0 disable-examples: true github: repository: VapiAI/server-sdk-csharp + mode: pull-request output: location: nuget package-name: Vapi.Net @@ -109,3 +102,28 @@ groups: inline-path-parameters: false simplify-object-dictionaries: true use-discriminated-unions: false + smart-casing: false + php-sdk: + generators: + - name: fernapi/fern-php-sdk + version: 2.4.0 + github: + repository: VapiAI/server-sdk-php + mode: pull-request + config: + namespace: Vapi + client-class-name: VapiClient + smart-casing: false + swift-sdk: + generators: + - name: fernapi/fern-swift-sdk + version: 0.31.0 + disable-examples: true + github: + repository: VapiAI/server-sdk-swift + mode: pull-request + config: + clientClassName: VapiClient + moduleName: Vapi + environmentEnumName: VapiEnvironment + smart-casing: false diff --git a/fern/apis/api/openapi-overrides.yml b/fern/apis/api/openapi-overrides.yml index 598d91ed1..a2dbd1b50 100644 --- a/fern/apis/api/openapi-overrides.yml +++ b/fern/apis/api/openapi-overrides.yml @@ -1,29 +1,45 @@ x-fern-pagination: offset: $request.page results: $response.results +info: + description: >- + Vapi is a developer platform for building voice AI agents that make and + receive phone calls, run web voice experiences, and integrate with external + systems through tools and webhooks. paths: /enterprise: post: x-fern-ignore: true /call: get: + description: >- + Returns calls for the authenticated organization. Filter results by call + ID, assistant ID, phone number ID, or creation and update timestamps. x-fern-sdk-group-name: - calls x-fern-sdk-method-name: list post: + description: >- + Creates a call using an assistant or squad. The request can reference + saved resources or include transient configurations. x-fern-sdk-group-name: - calls x-fern-sdk-method-name: create /call/{id}: get: + description: >- + Returns the call identified by its ID, including its status, + configuration, and available call data. x-fern-sdk-group-name: - calls x-fern-sdk-method-name: get delete: + description: Deletes the call identified by its ID. x-fern-sdk-group-name: - calls x-fern-sdk-method-name: delete patch: + description: Updates the call identified by its ID. x-fern-sdk-group-name: - calls x-fern-sdk-method-name: update @@ -84,138 +100,327 @@ paths: x-fern-sdk-method-name: update /assistant: get: + description: >- + Returns assistants for the authenticated organization. Filter results + by creation or update timestamps and limit the number returned. x-fern-sdk-group-name: - assistants x-fern-sdk-method-name: list post: + description: >- + Creates a reusable assistant configuration containing the model, voice, + transcriber, tools, prompts, and call behavior. x-fern-sdk-group-name: - assistants x-fern-sdk-method-name: create /assistant/{id}: get: + description: Returns the assistant identified by its ID. x-fern-sdk-group-name: - assistants x-fern-sdk-method-name: get delete: + description: Deletes the assistant identified by its ID. x-fern-sdk-group-name: - assistants x-fern-sdk-method-name: delete patch: + description: >- + Updates the specified fields of the assistant identified by its ID. x-fern-sdk-group-name: - assistants x-fern-sdk-method-name: update /phone-number: get: + description: >- + Returns phone numbers for the authenticated organization. Filter results + by creation or update timestamps and limit the number returned. x-fern-sdk-group-name: - phoneNumbers x-fern-sdk-method-name: list post: + description: >- + Creates a Vapi phone number or imports a phone number from a supported + provider, including Twilio, Vonage, Telnyx, or a bring-your-own provider. x-fern-sdk-group-name: - phoneNumbers x-fern-sdk-method-name: create + /v2/phone-number: + get: + description: >- + Returns a paginated list of phone numbers for the authenticated + organization. Search by name, number, or SIP URI using a partial, + case-insensitive match, and filter by creation or update timestamps. /phone-number/{id}: get: + description: Returns the phone number resource identified by its ID. x-fern-sdk-group-name: - phoneNumbers x-fern-sdk-method-name: get delete: + description: Deletes the phone number resource identified by its ID. x-fern-sdk-group-name: - phoneNumbers x-fern-sdk-method-name: delete patch: + description: >- + Updates the specified fields of the phone number resource identified by + its ID. x-fern-sdk-group-name: - phoneNumbers x-fern-sdk-method-name: update /squad: get: + description: >- + Returns squads for the authenticated organization. Filter results by + creation or update timestamps and limit the number returned. x-fern-sdk-group-name: - squads x-fern-sdk-method-name: list post: + description: >- + Creates a squad that coordinates multiple assistants and their handoffs + during a conversation. x-fern-sdk-group-name: - squads x-fern-sdk-method-name: create /squad/{id}: get: + description: Returns the squad identified by its ID. x-fern-sdk-group-name: - squads x-fern-sdk-method-name: get delete: + description: Deletes the squad identified by its ID. x-fern-sdk-group-name: - squads x-fern-sdk-method-name: delete patch: + description: Updates the specified fields of the squad identified by its ID. x-fern-sdk-group-name: - squads x-fern-sdk-method-name: update /tool: get: + description: >- + Returns reusable tools for the authenticated organization. Filter + results by creation or update timestamps and limit the number returned. x-fern-sdk-group-name: - tools x-fern-sdk-method-name: list post: + description: >- + Creates a reusable tool that assistants can invoke during conversations. x-fern-sdk-group-name: - tools x-fern-sdk-method-name: create /tool/{id}: get: + description: Returns the tool identified by its ID. x-fern-sdk-group-name: - tools x-fern-sdk-method-name: get delete: + description: Deletes the tool identified by its ID. x-fern-sdk-group-name: - tools x-fern-sdk-method-name: delete patch: + description: Updates the specified fields of the tool identified by its ID. x-fern-sdk-group-name: - tools x-fern-sdk-method-name: update /file: get: + description: Returns files uploaded to the authenticated organization. x-fern-sdk-group-name: - files x-fern-sdk-method-name: list post: + description: Uploads a file for use with a Vapi knowledge base. x-fern-sdk-group-name: - files x-fern-sdk-method-name: create /file/{id}: get: + description: Returns the uploaded file identified by its ID. x-fern-sdk-group-name: - files x-fern-sdk-method-name: get delete: + description: Deletes the uploaded file identified by its ID. x-fern-sdk-group-name: - files x-fern-sdk-method-name: delete patch: + description: Updates the name of the uploaded file identified by its ID. x-fern-sdk-group-name: - files x-fern-sdk-method-name: update + /campaign: + get: + description: >- + Returns outbound calling campaigns for the authenticated organization. + Filter results by campaign ID, status, or creation and update timestamps. + post: + description: Creates an outbound calling campaign that calls a set of customers. + /campaign/{id}: + get: + description: Returns the outbound calling campaign identified by its ID. + delete: + description: Deletes the outbound calling campaign identified by its ID. + patch: + description: >- + Updates the outbound calling campaign identified by its ID. Campaigns + can be ended by updating their status to `ended`. + /structured-output: + get: + description: >- + Returns structured-output definitions for the authenticated + organization. Filter results by ID, name, or creation and update + timestamps. + post: + description: >- + Creates a reusable definition for extracting validated data from + conversations using an AI model or regular expression. + /structured-output/{id}: + get: + description: Returns the structured-output definition identified by its ID. + delete: + description: Deletes the structured-output definition identified by its ID. + patch: + description: >- + Updates the structured-output definition identified by its ID. + /structured-output/run: + post: + description: >- + Runs a saved or transient structured-output definition against one or + more calls, optionally returning a preview without updating call + artifacts. + /reporting/insight: + get: + description: >- + Returns saved reporting insights for the authenticated organization. + Filter results by ID or creation and update timestamps. + post: + description: >- + Creates a saved reporting insight that queries call data and presents + the results as a bar chart, pie chart, line chart, or text value. + /reporting/insight/{id}: + get: + description: Returns the reporting insight identified by its ID. + delete: + description: Deletes the reporting insight identified by its ID. + patch: + description: Updates the reporting insight identified by its ID. + /reporting/insight/{id}/run: + post: + description: >- + Runs a saved reporting insight, optionally overriding its time range and + response format. + /reporting/insight/preview: + post: + description: >- + Runs an insight definition without first saving it, returning a preview + of the resulting chart or text value. + /eval: + get: + description: >- + Returns eval definitions for the authenticated organization. Filter + results by ID or creation and update timestamps. + post: + description: >- + Creates a reusable eval that defines a mock conversation and checkpoints + for evaluating assistant responses and tool calls. + /eval/{id}: + get: + description: Returns the eval definition identified by its ID. + delete: + description: Deletes the eval definition identified by its ID. + patch: + description: Updates the eval definition identified by its ID. + /eval/run: + get: + description: >- + Returns eval runs for the authenticated organization. Filter results by + ID or creation and update timestamps. + post: + description: >- + Runs a saved or transient eval against an assistant or squad and creates + an eval-run record containing the results. + /eval/run/{id}: + get: + description: Returns the eval run identified by its ID. + delete: + description: Deletes the eval run identified by its ID. + /observability/scorecard: + get: + description: >- + Returns scorecards for the authenticated organization. Filter results by + ID or creation and update timestamps. + post: + description: >- + Creates a scorecard containing metrics, scoring conditions, and optional + links to assistants whose calls should be evaluated. + /observability/scorecard/{id}: + get: + description: Returns the scorecard identified by its ID. + delete: + description: Deletes the scorecard identified by its ID. + patch: + description: Updates the scorecard identified by its ID. + /provider/{provider}/{resourceName}: + get: + description: >- + Returns a paginated list of provider resources for the authenticated + organization. Filter pronunciation dictionaries by provider, resource + ID, or creation and update timestamps. + post: + description: >- + Creates a pronunciation-dictionary resource for a supported provider, + currently Cartesia or ElevenLabs. + /provider/{provider}/{resourceName}/{id}: + get: + description: >- + Returns the provider resource identified by its Vapi resource ID. + delete: + description: >- + Deletes the provider resource identified by its Vapi resource ID. + patch: + description: >- + Updates the provider resource identified by its Vapi resource ID. /knowledge-base: get: x-fern-sdk-group-name: - knowledgeBases + x-fern-ignore: true x-fern-sdk-method-name: list post: x-fern-sdk-group-name: - knowledgeBases + x-fern-ignore: true x-fern-sdk-method-name: create /knowledge-base/{id}: get: x-fern-sdk-group-name: - knowledgeBases + x-fern-ignore: true x-fern-sdk-method-name: get delete: x-fern-sdk-group-name: - knowledgeBases + x-fern-ignore: true x-fern-sdk-method-name: delete patch: x-fern-sdk-group-name: - knowledgeBases + x-fern-ignore: true x-fern-sdk-method-name: update /analytics: post: + description: >- + Runs one or more metric queries against call or subscription data using + the requested time range, groupings, and aggregate operations. x-fern-sdk-group-name: - analytics x-fern-sdk-method-name: get @@ -224,53 +429,633 @@ paths: /logs: get: x-fern-pagination: true + x-fern-ignore: true x-fern-sdk-group-name: - logs x-fern-sdk-method-name: get + /eval/simulation/personality: + post: + description: Creates a personality, the AI tester's configuration used in simulations. + get: + description: Returns the personalities for the authenticated organization. + /eval/simulation/personality/{id}: + get: + description: Returns the specified personality. + patch: + description: Updates the specified personality. Changes apply to future runs. + delete: + description: Deletes the specified personality. + /eval/simulation/scenario: + post: + description: Creates a scenario, the AI tester's intent plus the success criteria that score a run. + get: + description: Returns the scenarios for the authenticated organization. + /eval/simulation/scenario/generate: + post: + description: Generates scenarios for an assistant or squad by analyzing its configuration with AI. + /eval/simulation/scenario/{id}: + get: + description: Returns the specified scenario. + patch: + description: Updates the specified scenario. + delete: + description: Deletes the specified scenario. + /eval/simulation/run: + post: + description: Starts a simulation run against a target assistant or squad. + get: + description: Returns the simulation runs for the authenticated organization. + /eval/simulation/run/{id}: + get: + description: Returns the specified simulation run, including its status and item counts. + patch: + description: Cancels the specified simulation run. + /eval/simulation/run/{id}/item: + get: + description: Returns the run items for the specified simulation run. + /eval/simulation/run/{id}/item/{itemId}: + get: + description: Returns the specified run item, including its evaluation results and the ID of the call that ran it. + patch: + description: Cancels the specified run item. + /eval/simulation/run/{id}/item/{itemId}/generate: + post: + description: Generates AI suggestions for improving the assistant or squad's system prompt, tools, and scenarios, based on the specified run item. + /eval/simulation/suite: + post: + description: Creates a simulation suite, a group of simulations that run together. + get: + description: Returns the simulation suites for the authenticated organization. + /eval/simulation/suite/{id}: + get: + description: Returns the specified simulation suite. + patch: + description: Updates the specified simulation suite. + delete: + description: Deletes the specified simulation suite. + /eval/simulation: + post: + description: Creates a simulation by pairing a scenario with a personality. + get: + description: Returns the simulations for the authenticated organization. + /eval/simulation/{id}: + get: + description: Returns the specified simulation. + patch: + description: Updates the specified simulation. + delete: + description: Deletes the specified simulation. + /eval/simulation/concurrency: + get: + description: Returns the organization's simulation concurrency limit, the number of active simulations, and how many more can start. + components: schemas: + CreatePersonalityDTO: + properties: + name: + description: The display name of the personality, for example `Impatient customer`. + assistant: + description: >- + The assistant configuration for the AI tester: the model, voice, and system + prompt that determine how the AI tester behaves during the conversation. + CreateScenarioDTO: + properties: + name: + description: The display name of the scenario, for example `Book an appointment`. + instructions: + description: >- + What the AI tester should try to accomplish in the conversation. Write it as the + AI tester's goal, for example `Book an appointment for next week and confirm the time.` + evaluations: + description: >- + The checks that decide whether a run passes. Each evaluation compares a structured + output against an expected value. At least one evaluation is required to run. + toolMocks: + description: >- + Mock results for the assistant or squad's tools during the simulation, so the run + stays deterministic without calling real services. + EvaluationPlanItem: + properties: + structuredOutputId: + description: >- + The ID of an existing structured output to evaluate. Use this to reuse a structured + output across scenarios. Provide either `structuredOutputId` or an inline `structuredOutput`. + structuredOutput: + description: >- + An inline structured output to evaluate, defined by its name and schema. Only + primitive types (string, number, integer, boolean) are allowed. Provide either + this or `structuredOutputId`. + comparator: + description: How the structured output value is compared against `value`. Available operators depend on the output type. Boolean and string support `=` and `!=`; number and integer support `=`, `!=`, `>`, `<`, `>=`, `<=`. + value: + description: The expected value the structured output is compared against. Its type should match the structured output's type, for example `true` for a boolean. + required: + description: Set to `false` to record this evaluation's result without requiring it to pass. Default is `true`. + ScenarioToolMock: + properties: + toolName: + description: The name of the assistant or squad's tool to mock. Must match the tool's name exactly. + result: + description: The result string returned to the assistant or squad in place of calling the real tool. + enabled: + description: Set to `true` to apply this mock during the simulation. Defaults to `true`. + CreateSimulationDTO: + properties: + name: + description: Optional display name for the simulation. + scenarioId: + description: The ID of the scenario to run. + personalityId: + description: The ID of the personality the AI tester uses. + CreateSimulationSuiteDTO: + properties: + name: + description: The display name of the suite. + simulationIds: + description: The IDs of the simulations included in the suite. + slackWebhookUrl: + description: A Slack incoming-webhook URL notified when the suite runs. + targetAssignments: + description: The assistants or squads the suite's simulations run against. + SimulationRun: + properties: + status: + description: The run's current status. One of `queued`, `running`, or `ended`. + endedReason: + description: Why the run ended, when applicable. + itemCounts: + description: Aggregate counts of the run's items by status. + simulations: + description: The simulations and suites included in the run. + target: + description: The assistant or squad the run was tested against. + iterations: + description: The number of times each simulation was run. Defaults to 1. + transport: + description: The transport used for the run, either voice or chat. + SimulationRunItemCounts: + properties: + total: + description: The total number of run items. + passed: + description: The number of run items that passed all required evaluations. + failed: + description: The number of run items that failed at least one required evaluation. + running: + description: The number of run items currently running or evaluating. + queued: + description: The number of run items waiting to start. + canceled: + description: The number of run items that were canceled. + SimulationRunItem: + properties: + status: + description: The run item's current status. + results: + description: The evaluation results for this run item. + improvementSuggestions: + description: AI-generated suggestions for improving the assistant or squad's system prompt, tools, and scenarios after a failed run. + callId: + description: The ID of the call that ran this item. + failureReason: + description: Why the run item failed, when applicable. + iterationNumber: + description: Which iteration of the simulation this item represents. + scenarioId: + description: The ID of the scenario used for this run item. + personalityId: + description: The ID of the personality used for this run item. CreateAssistantDTO: + description: >- + Configuration used to create an assistant, including its model, voice, + transcriber, prompts, tools, messaging, and conversation behavior. properties: + firstMessageInterruptionsEnabled: + description: >- + Set to `true` to allow the user to interrupt the assistant while it + speaks the first message. Default is `false`. + compliancePlan: + description: >- + Compliance settings for the assistant, including HIPAA and PCI + behavior, security filtering, and recording consent. + keypadInputPlan: + description: >- + Configuration for collecting and processing DTMF keypad input + during calls. serverMessages: items: - enum: - - "transcript[transcriptType='final']" x-fern-enum: "transcript[transcriptType='final']": name: FinalTranscript AssistantOverrides: + description: >- + Per-call or handoff overrides for an assistant's providers, messages, + tools, credentials, call behavior, and server configuration. properties: + firstMessageInterruptionsEnabled: + description: >- + Set to `true` to allow the user to interrupt the assistant while it + speaks the first message. Default is `false`. + tools:append: + description: >- + Tools to append to the assistant's existing tool configuration. + compliancePlan: + description: >- + Compliance settings to apply, including HIPAA and PCI behavior, + security filtering, and recording consent. + keypadInputPlan: + description: >- + Configuration for collecting and processing DTMF keypad input. serverMessages: items: - enum: - - "transcript[transcriptType='final']" x-fern-enum: "transcript[transcriptType='final']": name: FinalTranscript Assistant: + description: >- + A saved assistant configuration returned by the Vapi API. It defines + how the assistant listens, reasons, speaks, handles conversations, + sends events, and produces artifacts and analysis. properties: + firstMessageInterruptionsEnabled: + description: >- + Set to `true` to allow the user to interrupt the assistant while it + speaks the first message. Default is `false`. + compliancePlan: + description: >- + Compliance settings for the assistant, including HIPAA and PCI + behavior, security filtering, and recording consent. + keypadInputPlan: + description: >- + Configuration for collecting and processing DTMF keypad input + during calls. serverMessages: items: - enum: - - "transcript[transcriptType='final']" x-fern-enum: "transcript[transcriptType='final']": name: FinalTranscript UpdateAssistantDTO: + description: >- + Fields used to update an existing assistant. Include only the settings + you want to change; omitted fields retain their current values. properties: + firstMessageInterruptionsEnabled: + description: >- + Set to `true` to allow the user to interrupt the assistant while it + speaks the first message. Default is `false`. + compliancePlan: + description: >- + Compliance settings for the assistant, including HIPAA and PCI + behavior, security filtering, and recording consent. + keypadInputPlan: + description: >- + Configuration for collecting and processing DTMF keypad input + during calls. serverMessages: items: - enum: - - "transcript[transcriptType='final']" x-fern-enum: "transcript[transcriptType='final']": name: FinalTranscript + CreateSquadDTO: + description: >- + Configuration used to create a squad. Provide an ordered list of + assistant members and optional overrides that control how the squad + handles a conversation and transfers between assistants. + Squad: + description: >- + A saved squad configuration that coordinates a group of assistants + during a conversation. The first member starts the call, and member + destinations control transfers between assistants. + UpdateSquadDTO: + description: >- + Configuration used to update an existing squad, including its name, + ordered members, and shared assistant overrides. + SquadMemberDTO: + description: >- + An assistant member of a squad. Reference a saved assistant or provide + a transient assistant, then configure member-specific overrides and + destinations for transfers. + properties: + assistantDestinations: + description: >- + Assistants this squad member can route the conversation to through + a transfer or handoff. + CreateFileDTO: + description: >- + A file-upload request containing the file to store and process in Vapi. + File: + description: >- + An uploaded file record, including its processing status, storage + details, extracted-text location, metadata, and lifecycle timestamps. + properties: + object: + description: The object type. This is always `file`. + status: + description: The current processing status of the uploaded file. + originalName: + description: The original name of the uploaded file. + bytes: + description: The size of the uploaded file in bytes. + purpose: + description: The intended use assigned to the uploaded file. + mimetype: + description: The MIME type of the uploaded file. + key: + description: The object-storage key for the uploaded file. + path: + description: The object-storage path for the uploaded file. + bucket: + description: The object-storage bucket containing the uploaded file. + url: + description: The URL used to access the uploaded file. + parsedTextUrl: + description: The URL used to access text extracted from the file. + parsedTextBytes: + description: The size of the extracted text in bytes. + metadata: + description: Additional metadata associated with the uploaded file. + UpdateFileDTO: + description: >- + Fields used to update an uploaded file. Currently, the file name can be + changed. + Campaign: + description: >- + A saved outbound calling campaign, including its calling configuration, + schedule, status, customers, calls, and call-progress counters. + CampaignPaginatedResponse: + description: >- + A paginated collection of outbound calling campaigns and metadata + describing the result set. + properties: + results: + description: The campaigns returned for the current page. + metadata: + description: Pagination metadata for the campaign result set. + CreateCampaignDTO: + description: >- + Configuration used to create an outbound calling campaign. Choose an + assistant, squad, or workflow, then provide customers, phone-number or + dial-plan settings, and an optional schedule. + UpdateCampaignDTO: + description: >- + Fields used to update an outbound calling campaign, including its name, + status, calling resource, phone-number or dial-plan settings, and + schedule. + CreateStructuredOutputDTO: + description: >- + Configuration used to create a structured-output definition that + extracts validated data from calls using an AI model or regular + expression. + StructuredOutput: + description: >- + A saved structured-output definition containing its extraction schema, + execution method, model or regular expression, linked resources, and + lifecycle metadata. + StructuredOutputPaginatedResponse: + description: >- + A paginated collection of structured-output definitions and metadata + describing the result set. + properties: + results: + description: The structured-output definitions returned for the current page. + metadata: + description: Pagination metadata for the structured-output result set. + StructuredOutputRunDTO: + description: >- + A request to run a saved or transient structured-output definition + against one or more calls, either as a preview or as an artifact update. + UpdateStructuredOutputDTO: + description: >- + Fields used to update a structured-output definition, including its + name, extraction schema, execution method, model or regular expression, + compliance settings, and linked resources. + CreateBarInsightFromCallTableDTO: + description: >- + Configuration used to create a bar-chart insight from call data using + metric queries, formulas, grouping, and a stepped time range. + properties: + timeRange: + description: >- + The time range and interval used to aggregate the bar-chart data. + CreateLineInsightFromCallTableDTO: + description: >- + Configuration used to create a line-chart insight from call data using + metric queries, formulas, grouping, and a stepped time range. + properties: + timeRange: + description: >- + The time range and interval used to aggregate the line-chart data. + CreatePieInsightFromCallTableDTO: + description: >- + Configuration used to create a pie-chart insight from call data using + metric queries, formulas, grouping, and a time range. + properties: + timeRange: + description: The time range used to query the pie-chart data. + CreateTextInsightFromCallTableDTO: + description: >- + Configuration used to create a text-value insight from call data using + metric queries, a formula, and a time range. + properties: + timeRange: + description: The time range used to query the text-value data. + BarInsight: + description: >- + A saved bar-chart insight containing its call-data queries, formulas, + grouping, stepped time range, metadata, and lifecycle information. + properties: + timeRange: + description: >- + The time range and interval used to aggregate the bar-chart data. + LineInsight: + description: >- + A saved line-chart insight containing its call-data queries, formulas, + grouping, stepped time range, metadata, and lifecycle information. + properties: + timeRange: + description: >- + The time range and interval used to aggregate the line-chart data. + PieInsight: + description: >- + A saved pie-chart insight containing its call-data queries, formulas, + grouping, time range, and lifecycle information. + properties: + timeRange: + description: The time range used to query the pie-chart data. + TextInsight: + description: >- + A saved text-value insight containing its call-data queries, formula, + time range, and lifecycle information. + properties: + timeRange: + description: The time range used to query the text-value data. + UpdateBarInsightFromCallTableDTO: + description: >- + Fields used to update a bar-chart insight, including its queries, + formulas, grouping, time range, metadata, and name. + properties: + timeRange: + description: >- + The time range and interval used to aggregate the bar-chart data. + UpdateLineInsightFromCallTableDTO: + description: >- + Fields used to update a line-chart insight, including its queries, + formulas, grouping, time range, metadata, and name. + properties: + timeRange: + description: >- + The time range and interval used to aggregate the line-chart data. + UpdatePieInsightFromCallTableDTO: + description: >- + Fields used to update a pie-chart insight, including its queries, + formulas, grouping, time range, and name. + properties: + timeRange: + description: The time range used to query the pie-chart data. + UpdateTextInsightFromCallTableDTO: + description: >- + Fields used to update a text-value insight, including its queries, + formula, time range, and name. + properties: + timeRange: + description: The time range used to query the text-value data. + InsightPaginatedResponse: + description: >- + A paginated collection of saved reporting insights and metadata + describing the result set. + properties: + results: + description: The reporting insights returned for the current page. + metadata: + description: Pagination metadata for the insight result set. + InsightRunDTO: + description: >- + Options for running a saved insight, including optional time-range and + output-format overrides. + properties: + formatPlan: + description: Output-formatting instructions applied to the insight run. + InsightRunResponse: + description: >- + Metadata identifying a saved insight run and its lifecycle timestamps. + properties: + id: + description: The unique identifier for the insight run. + insightId: + description: The unique identifier for the insight that was run. + orgId: + description: The unique identifier for the organization that owns the run. + createdAt: + description: The ISO 8601 timestamp when the insight run was created. + updatedAt: + description: The ISO 8601 timestamp when the insight run was last updated. + AnalyticsQueryDTO: + description: >- + A request containing one or more metric queries to run against call or + subscription data. + AnalyticsQueryResult: + description: >- + The result of a named analytics query, including the evaluated time + range and returned metric data. + CreateEvalDTO: + description: >- + Configuration used to create a reusable eval containing a mock + conversation and checkpoints for assessing assistant responses and tool + calls. + UpdateEvalDTO: + description: >- + Fields used to update an eval, including its name, description, mock + conversation messages, and eval type. + Eval: + description: >- + A saved eval definition containing its mock conversation, checkpoints, + descriptive metadata, type, and lifecycle information. + properties: + id: + description: The unique identifier for the eval. + orgId: + description: The unique identifier for the organization that owns the eval. + createdAt: + description: The ISO 8601 timestamp when the eval was created. + updatedAt: + description: The ISO 8601 timestamp when the eval was last updated. + EvalPaginatedResponse: + description: >- + A paginated collection of saved eval definitions and metadata describing + the result set. + properties: + results: + description: The eval definitions returned for the current page. + metadata: + description: Pagination metadata for the eval result set. + CreateEvalRunDTO: + description: >- + A request to run a saved or transient eval against an assistant or + squad target. + EvalRun: + description: >- + A record of an eval execution, including its target, status, results, + costs, completion details, and lifecycle timestamps. + properties: + id: + description: The unique identifier for the eval run. + orgId: + description: The unique identifier for the organization that owns the run. + createdAt: + description: The ISO 8601 timestamp when the eval run was created. + startedAt: + description: The ISO 8601 timestamp when the eval run started. + endedAt: + description: The ISO 8601 timestamp when the eval run ended. + EvalRunPaginatedResponse: + description: >- + A paginated collection of eval runs and metadata describing the result + set. + properties: + results: + description: The eval runs returned for the current page. + metadata: + description: Pagination metadata for the eval-run result set. + CreateScorecardDTO: + description: >- + Configuration used to create a scorecard containing evaluation metrics, + scoring conditions, and optional assistant associations. + UpdateScorecardDTO: + description: >- + Fields used to update a scorecard, including its name, description, + metrics, scoring conditions, and assistant associations. + Scorecard: + description: >- + A saved scorecard containing its evaluation metrics, scoring conditions, + assistant associations, descriptive metadata, and lifecycle information. + ScorecardPaginatedResponse: + description: >- + A paginated collection of scorecards and metadata describing the result + set. + properties: + results: + description: The scorecards returned for the current page. + metadata: + description: Pagination metadata for the scorecard result set. + ProviderResource: + description: >- + A provider-managed pronunciation-dictionary resource mirrored in Vapi, + including its provider identifiers, resource data, and lifecycle + information. + ProviderResourcePaginatedResponse: + description: >- + A paginated collection of provider resources and metadata describing the + result set. + properties: + results: + description: The provider resources returned for the current page. + metadata: + description: Pagination metadata for the provider-resource result set. ClientMessageTranscript: title: ClientMessageTranscript properties: type: - enum: - - "transcript[transcriptType='final']" x-fern-enum: "transcript[transcriptType='final']": name: FinalTranscript @@ -278,8 +1063,6 @@ components: title: ServerMessageTranscript properties: type: - enum: - - "transcript[transcriptType='final']" x-fern-enum: "transcript[transcriptType='final']": name: FinalTranscript @@ -287,13 +1070,14 @@ components: properties: serverMessages: items: - enum: - - "transcript[transcriptType='final']" x-fern-enum: "transcript[transcriptType='final']": name: FinalTranscript FallbackAzureVoice: title: FallbackAzureVoice + description: >- + Fallback configuration for synthesizing assistant speech with Azure, + including voice selection, speed, chunking, and caching. properties: voiceId: x-fern-type-name: FallbackAzureVoiceId @@ -301,6 +1085,10 @@ components: - x-fern-type-name: FallbackAzureVoiceIdEnum FallbackDeepgramVoice: title: FallbackDeepgramVoice + description: >- + Fallback configuration for synthesizing assistant speech with Deepgram, + including voice and model selection, model-improvement preferences, + chunking, and caching. properties: voiceId: x-fern-type-name: FallbackDeepgramVoiceId @@ -308,6 +1096,11 @@ components: - x-fern-type-name: FallbackDeepgramVoiceIdEnum FallbackElevenLabsVoice: title: FallbackElevenLabsVoice + description: >- + Fallback configuration for synthesizing assistant speech with + ElevenLabs, including voice and model selection, language, voice tuning, + streaming, Speech Synthesis Markup Language parsing, pronunciation + dictionaries, chunking, and caching. properties: voiceId: x-fern-type-name: FallbackElevenLabsVoiceId @@ -317,6 +1110,10 @@ components: x-fern-type: literal<"11labs"> FallbackOpenAIVoice: title: FallbackOpenAIVoice + description: >- + Fallback configuration for synthesizing assistant speech with OpenAI, + including voice and model selection, delivery instructions, speed, + chunking, and caching. properties: voiceId: x-fern-type-name: FallbackOpenAIVoiceId @@ -324,6 +1121,10 @@ components: - x-fern-type-name: FallbackOpenAIVoiceIdEnum FallbackRimeAIVoice: title: FallbackRimeAIVoice + description: >- + Fallback configuration for synthesizing assistant speech with Rime AI, + including voice and model selection, language, speed, pauses, + phonemization, latency, chunking, and caching. properties: voiceId: x-fern-type-name: FallbackRimeAIVoiceId @@ -331,6 +1132,10 @@ components: - x-fern-type-name: FallbackRimeAIVoiceIdEnum FallbackPlayHTVoice: title: FallbackPlayHTVoice + description: >- + Fallback configuration for synthesizing assistant speech with PlayHT, + including voice and model selection, language, emotion and style + guidance, chunking, and caching. properties: voiceId: x-fern-type-name: FallbackPlayHTVoiceId @@ -338,6 +1143,9 @@ components: - x-fern-type-name: FallbackPlayHTVoiceIdEnum FallbackLMNTVoice: title: FallbackLMNTVoice + description: >- + Fallback configuration for synthesizing assistant speech with LMNT, + including voice selection, language, speed, chunking, and caching. properties: voiceId: x-fern-type-name: FallbackLMNTVoiceId @@ -352,6 +1160,9 @@ components: - x-fern-type-name: FallbackNeetsVoiceIdEnum FallbackSmallestAIVoice: title: FallbackSmallestAIVoice + description: >- + Fallback configuration for synthesizing assistant speech with Smallest + AI, including voice and model selection, speed, chunking, and caching. properties: voiceId: x-fern-type-name: FallbackSmallestAIVoiceId @@ -359,6 +1170,9 @@ components: - x-fern-type-name: FallbackSmallestAIVoiceIdEnum AzureVoice: title: AzureVoice + description: >- + Configuration for synthesizing assistant speech with Azure, including + voice selection, speed, chunking, caching, and fallback settings. properties: voiceId: x-fern-type-name: AzureVoiceId @@ -366,6 +1180,10 @@ components: - x-fern-type-name: AzureVoiceIdEnum DeepgramVoice: title: DeepgramVoice + description: >- + Configuration for synthesizing assistant speech with Deepgram, including + voice and model selection, model-improvement preferences, chunking, + caching, and fallback settings. properties: voiceId: x-fern-type-name: DeepgramVoiceId @@ -373,6 +1191,11 @@ components: - x-fern-type-name: DeepgramVoiceIdEnum ElevenLabsVoice: title: ElevenLabsVoice + description: >- + Configuration for synthesizing assistant speech with ElevenLabs, + including voice and model selection, language, voice tuning, streaming, + Speech Synthesis Markup Language parsing, pronunciation dictionaries, + chunking, caching, and fallback settings. properties: voiceId: x-fern-type-name: ElevenLabsVoiceId @@ -382,6 +1205,10 @@ components: x-fern-type: literal<"11labs"> SmallestAIVoice: title: SmallestAIVoice + description: >- + Configuration for synthesizing assistant speech with Smallest AI, + including voice and model selection, speed, chunking, caching, and + fallback settings. properties: voiceId: x-fern-type-name: SmallestAIVoiceId @@ -393,9 +1220,13 @@ components: x-fern-type: literal<"11labs"> CreateElevenLabsCredentialDTO: title: CreateElevenLabsCredentialDTO + description: >- + Credentials for authenticating speech recognition and voice synthesis + requests with ElevenLabs. properties: provider: x-fern-type: literal<"11labs"> + description: Selects ElevenLabs as the credential provider. UpdateElevenLabsCredentialDTO: properties: provider: @@ -417,6 +1248,9 @@ components: "11labs": name: ElevenLabs KeypadInputPlan: + description: >- + Controls collection of dual-tone multi-frequency (DTMF) keypad input, + including enablement, processing timeout, and delimiters. properties: delimiters: x-fern-enum: @@ -426,18 +1260,38 @@ components: name: Asterisk "#": name: Hash + items: + x-fern-enum: + "": + name: Empty + "*": + name: Asterisk + "#": + name: Hash NeuphonicVoice: title: NeuphonicVoice + description: >- + Configuration for synthesizing assistant speech with Neuphonic, + including voice and model selection, language, speed, chunking, caching, + and fallback settings. properties: voiceId: x-fern-type: string FallbackNeuphonicVoice: title: FallbackNeuphonicVoice + description: >- + Fallback configuration for synthesizing assistant speech with Neuphonic, + including voice and model selection, language, speed, chunking, and + caching. properties: voiceId: x-fern-type: string LMNTVoice: title: LMNTVoice + description: >- + Configuration for synthesizing assistant speech with LMNT, including + voice selection, language, speed, chunking, caching, and fallback + settings. properties: voiceId: x-fern-type-name: LMNTVoiceId @@ -452,6 +1306,10 @@ components: - x-fern-type-name: NeetsVoiceIdEnum OpenAIVoice: title: OpenAIVoice + description: >- + Configuration for synthesizing assistant speech with OpenAI, including + voice and model selection, delivery instructions, speed, chunking, + caching, and fallback settings. properties: voiceId: x-fern-type-name: OpenAIVoiceId @@ -459,6 +1317,10 @@ components: - x-fern-type-name: OpenAIVoiceIdEnum RimeAIVoice: title: RimeAIVoice + description: >- + Configuration for synthesizing assistant speech with Rime AI, including + voice and model selection, language, speed, pauses, phonemization, + latency, chunking, caching, and fallback settings. properties: voiceId: x-fern-type-name: RimeAIVoiceId @@ -466,6 +1328,10 @@ components: - x-fern-type-name: RimeAIVoiceIdEnum PlayHTVoice: title: PlayHTVoice + description: >- + Configuration for synthesizing assistant speech with PlayHT, including + voice and model selection, language, emotion and style guidance, + chunking, caching, and fallback settings. properties: voiceId: x-fern-type-name: PlayHTVoiceId @@ -473,6 +1339,10 @@ components: - x-fern-type-name: PlayHTVoiceIdEnum DeepgramTranscriber: title: DeepgramTranscriber + description: >- + Configuration for transcribing speech during assistant conversations + with Deepgram, including model, language, formatting, endpointing, + vocabulary, and fallback settings. properties: model: $ref: "#/components/schemas/DeepgramTranscriberModel" @@ -581,6 +1451,7 @@ components: DeepgramTranscriberModel: type: string enum: + - "flux-general-en" - "nova-3" - "nova-3-general" - "nova-3-medical" @@ -612,7 +1483,10 @@ components: - "base-conversationalai" - "base-voicemail" - "base-video" + - "whisper" x-fern-enum: + "flux-general-en": + name: fluxGeneralEn "nova-3": name: nova3 "nova-3-general": @@ -675,8 +1549,13 @@ components: name: baseVoicemail "base-video": name: baseVideo + "whisper": + name: whisper FallbackDeepgramTranscriber: title: FallbackDeepgramTranscriber + description: >- + Fallback configuration for transcribing speech with Deepgram, including + model, language, formatting, endpointing, and vocabulary. properties: model: $ref: "#/components/schemas/DeepgramTranscriberModel" @@ -785,6 +1664,7 @@ components: FallbackDeepgramTranscriberModel: type: string enum: + - "flux-general-en" - "nova-3" - "nova-3-general" - "nova-3-medical" @@ -816,7 +1696,10 @@ components: - "base-conversationalai" - "base-voicemail" - "base-video" + - "whisper" x-fern-enum: + "flux-general-en": + name: fluxGeneralEn "nova-3": name: nova3 "nova-3-general": @@ -879,9 +1762,16 @@ components: name: baseVoicemail "base-video": name: baseVideo + "whisper": + name: whisper TransferDestinationAssistant: title: TransferDestinationAssistant + description: >- + Transfers a call to another assistant by name, with an optional message + and assistant-transfer mode. properties: + type: + description: Selects another assistant as the transfer destination. transferMode: $ref: "#/components/schemas/TransferMode" TransferMode: @@ -894,6 +1784,9 @@ components: "swap-system-message-in-history": name: swapSystemMessageInHistory ChunkPlan: + description: >- + Controls how model output is split into chunks before voice synthesis, + including minimum length, punctuation boundaries, and formatting. properties: punctuationBoundaries: items: @@ -962,151 +1855,967 @@ components: name: COLON description: ":" CartesiaExperimentalControls: + description: Cartesia voice controls for speed and emotion. properties: speed: + description: >- + Speaking-speed control expressed as a preset or a value from -1 to + 1. x-fern-type-name: CartesiaSpeedControl + emotion: + description: Emotion and intensity applied to the Cartesia voice. + + AWSIAMCredentialsAuthenticationPlan: + description: Direct AWS IAM credentials used to authenticate requests. + properties: + type: + description: Selects direct AWS IAM credential authentication. + AWSStsAuthenticationPlan: + description: >- + AWS Security Token Service role-assumption configuration used to + authenticate requests. + AnthropicThinkingConfig: + description: >- + Enables Anthropic extended thinking with a maximum thinking-token + budget. + properties: + type: + description: Enables Anthropic extended thinking. + AzureBlobStorageBucketPlan: + description: >- + Azure Blob Storage container configuration for call artifacts, + including its connection string, container name, and storage path. + CartesiaGenerationConfig: + description: >- + Generation controls for Cartesia Sonic 3 voices, including speed, + volume, and accent localization. + CartesiaGenerationConfigExperimental: + description: >- + Cartesia Sonic 3 generation controls, including accent localization. + ElevenLabsPronunciationDictionaryLocator: + description: >- + Identifies a specific version of an ElevenLabs pronunciation + dictionary. + FormatPlan: + description: >- + Controls text normalization before voice synthesis, including built-in + formatters, number handling, and custom replacements. + GeminiMultimodalLivePrebuiltVoiceConfig: + description: >- + Selects a prebuilt voice for Gemini Multimodal Live audio output. + properties: + voiceName: + description: Prebuilt Gemini voice used for audio output. + GeminiMultimodalLiveSpeechConfig: + description: Speech-output configuration for Gemini Multimodal Live. + properties: + voiceConfig: + description: >- + Voice configuration used for Gemini Multimodal Live speech output. + GeminiMultimodalLiveVoiceConfig: + description: Voice selection configuration for Gemini Multimodal Live. + properties: + prebuiltVoiceConfig: + description: >- + Prebuilt voice used for Gemini Multimodal Live speech output. + GhlToolMetadata: + description: GHL workflow and location identifiers attached to a tool. + properties: + workflowId: + description: GHL workflow identifier associated with the tool. + locationId: + description: GHL location identifier associated with the tool. + GladiaCustomVocabularyConfigDTO: + description: >- + Custom vocabulary configuration for Gladia transcription, including + vocabulary items and default recognition intensity. + GladiaVocabularyItemDTO: + description: >- + A Gladia custom vocabulary word or phrase with optional pronunciations, + intensity, and language. + GoogleRealtimeConfig: + description: >- + Realtime Gemini generation and speech-output settings, including + sampling, repetition penalties, and voice configuration. + RegexOption: + description: >- + Enables or disables one regular-expression matching option for a text + replacement. + TavusConversationProperties: + description: >- + Tavus conversation behavior and media settings, including duration, + participant timeouts, recording, transcription, background, language, + and recording storage. + VapiPronunciationDictionaryLocator: + description: >- + Identifies a pronunciation dictionary and optional version used for + voice synthesis. + AssistantMessageEvaluationContinuePlan: + description: >- + Controls how an evaluation proceeds after judging an assistant message, + including failure handling and optional message overrides. + AssistantMessageJudgePlanAI: + description: >- + Evaluates an assistant message with an LLM judge and a configured + evaluation model. + AssistantMessageJudgePlanExact: + description: >- + Evaluates an assistant message using case-insensitive exact content + matching and expected tool calls. + AssistantMessageJudgePlanRegex: + description: >- + Evaluates assistant-message content and tool-call arguments using + regular-expression patterns. + ChatEvalAssistantMessageEvaluation: + description: >- + An expected assistant turn in an evaluation, including the judge plan + and how the evaluation should continue afterward. + ChatEvalAssistantMessageMock: + description: >- + A simulated assistant turn in an evaluation conversation, with optional + message content and tool calls. + ChatEvalAssistantMessageMockToolCall: + description: >- + A simulated assistant tool call with the tool name and optional + arguments. + ChatEvalSystemMessageMock: + description: A simulated system message in an evaluation conversation. + ChatEvalToolResponseMessageEvaluation: + description: >- + An expected tool-response turn evaluated by a configured LLM judge. + ChatEvalToolResponseMessageMock: + description: A simulated tool response in an evaluation conversation. + ChatEvalUserMessageMock: + description: A simulated user message in an evaluation conversation. + EvalAnthropicModel: + description: >- + Anthropic model configuration for an LLM judge, including its messages, + generation settings, and optional extended thinking. + EvalCustomModel: + description: >- + OpenAI-compatible custom model configuration for an LLM judge, + including its endpoint, headers, messages, and generation settings. + EvalGoogleModel: + description: >- + Google model configuration for an LLM judge, including its messages and + generation settings. + EvalOpenAIModel: + description: >- + OpenAI model configuration for an LLM judge, including its messages and + generation settings. + EvalRunResult: + description: >- + The pass or fail result of an evaluation run, including its conversation + messages and timing. + EvalRunTargetAssistant: + description: >- + An assistant evaluation target provided as a saved assistant ID or a + transient assistant, with optional assistant overrides. + EvalRunTargetSquad: + description: >- + A squad evaluation target provided as a saved squad ID or a transient + squad, with optional assistant overrides. + ScorecardMetric: + description: >- + A scorecard metric that awards points when a structured output meets its + configured conditions. UserMessage: title: UserMessage + description: >- + A user-authored entry in the call message history, including content, + timing, security-filter results, and optional speaker metadata. SystemMessage: title: SystemMessage + description: >- + A system-authored entry in the call message history, including its + content and timing. BotMessage: title: BotMessage + description: >- + An assistant-authored entry in the call message history, including + content, timing, source, and duration. ToolCallMessage: title: ToolCallMessage + description: >- + An entry in the call message history that records one or more tool calls + requested during the conversation. ToolCallResultMessage: title: ToolCallResultMessage + description: >- + An entry in the call message history that records the result and + metadata for a completed tool call. FallbackAssemblyAITranscriber: title: FallbackAssemblyAITranscriber + description: >- + Fallback configuration for transcribing speech with AssemblyAI, + including language, streaming model, endpointing, and vocabulary. FallbackAzureSpeechTranscriber: title: FallbackAzureSpeechTranscriber + description: >- + Fallback configuration for transcribing speech with Azure Speech, + including language and segmentation. FallbackCustomTranscriber: title: FallbackCustomTranscriber + description: >- + Fallback configuration for sending conversation audio to a custom + WebSocket transcription server. FallbackElevenLabsTranscriber: title: FallbackElevenLabsTranscriber + description: >- + Fallback configuration for transcribing speech with ElevenLabs, + including model, language, and speech thresholds. FallbackGladiaTranscriber: title: FallbackGladiaTranscriber + description: >- + Fallback configuration for transcribing speech with Gladia, including + language behavior, audio processing, endpointing, vocabulary, and + region. FallbackGoogleTranscriber: title: FallbackGoogleTranscriber + description: >- + Fallback configuration for transcribing speech with Google, including + model and language. FallbackTalkscriberTranscriber: title: FallbackTalkscriberTranscriber + description: >- + Fallback configuration for transcribing speech with Talkscriber, + including model and language. FallbackSpeechmaticsTranscriber: title: FallbackSpeechmaticsTranscriber + description: >- + Fallback configuration for transcribing speech with Speechmatics, + including language, region, diarization, vocabulary, endpointing, and + formatting. + properties: + language: + description: >- + Language used for transcription. Set to `auto` to detect the + language automatically. + customVocabulary: + description: >- + Words and phrases that Speechmatics should recognize more + accurately, with optional phonetic alternatives. FallbackOpenAITranscriber: title: FallbackOpenAITranscriber + description: >- + Fallback configuration for transcribing speech with OpenAI, including + model and language. TextContent: title: TextContent + description: >- + Localized text content used as a language-specific message variant. + properties: + type: + description: Selects text as the content type. + text: + description: Text spoken or displayed for this content variant. + language: + description: Language code associated with this text variant. ToolMessageStart: title: ToolMessageStart + description: >- + Message spoken when a tool call starts, with optional language variants, + argument conditions, and blocking behavior. ToolMessageComplete: title: ToolMessageComplete + description: >- + Message spoken when a tool call completes, with optional language + variants, argument conditions, role, and end-call behavior. ToolMessageFailed: title: ToolMessageFailed + description: >- + Message spoken when a tool call fails, with optional language variants, + argument conditions, and end-call behavior. ToolMessageDelayed: title: ToolMessageDelayed + description: >- + Message spoken when a tool call exceeds a configured response delay, + with optional language variants and argument conditions. CustomMessage: title: CustomMessage + description: >- + A message spoken by the assistant with optional language-specific + content variants. TransferDestinationNumber: title: TransferDestinationNumber + description: >- + Transfers a call to a phone number, with optional extension, caller ID, + message, transfer plan, and number validation. + properties: + type: + description: Selects a phone number as the transfer destination. TransferDestinationSip: title: TransferDestinationSip + description: >- + Transfers a call to a SIP URI, with optional caller ID, headers, message, + and transfer plan. + properties: + type: + description: Selects a SIP URI as the transfer destination. CreateApiRequestToolDTO: title: CreateApiRequestToolDTO + description: >- + Configuration used to create a reusable tool that sends HTTP requests + to a configured API and can authenticate, retry failures, and extract + variables from responses. + properties: + method: + description: The HTTP method used for the API request. + CreateCodeToolDTO: + description: >- + Configuration used to create a reusable tool that executes TypeScript + code with configured credentials, environment variables, and timeout. CreateBashToolDTO: title: CreateBashToolDTO + description: >- + Configuration used to create a tool that executes shell commands in a + configured environment. CreateComputerToolDTO: title: CreateComputerToolDTO + description: >- + Configuration used to create a tool that lets the model interact with a + computer display through screen, pointer, and keyboard actions. CreateDtmfToolDTO: title: CreateDtmfToolDTO + description: >- + Configuration used to create a tool that lets an assistant send DTMF + keypad tones during a call. CreateEndCallToolDTO: title: CreateEndCallToolDTO + description: >- + Configuration used to create a tool that lets an assistant end the + active call. CreateFunctionToolDTO: title: CreateFunctionToolDTO + description: >- + Configuration used to create a custom function tool that sends + model-generated arguments to a server and returns the result to the + assistant. + CreateHandoffToolDTO: + description: >- + Configuration used to create a tool that hands a conversation to + another assistant, squad, or dynamically selected destination. CreateGoHighLevelCalendarAvailabilityToolDTO: title: CreateGoHighLevelCalendarAvailabilityToolDTO + description: >- + Configuration used to create a tool that checks calendar availability + in a connected GoHighLevel account. CreateGoHighLevelCalendarEventCreateToolDTO: title: CreateGoHighLevelCalendarEventCreateToolDTO + description: >- + Configuration used to create a tool that adds calendar events to a + connected GoHighLevel account. CreateGoHighLevelContactCreateToolDTO: title: CreateGoHighLevelContactCreateToolDTO + description: >- + Configuration used to create a tool that adds contacts to a connected + GoHighLevel account. CreateGoHighLevelContactGetToolDTO: title: CreateGoHighLevelContactGetToolDTO + description: >- + Configuration used to create a tool that retrieves contacts from a + connected GoHighLevel account. CreateGoogleCalendarCheckAvailabilityToolDTO: title: CreateGoogleCalendarCheckAvailabilityToolDTO + description: >- + Configuration used to create a tool that checks availability in a + connected Google Calendar. CreateGoogleCalendarCreateEventToolDTO: title: CreateGoogleCalendarCreateEventToolDTO + description: >- + Configuration used to create a tool that adds events to a connected + Google Calendar. CreateGoogleSheetsRowAppendToolDTO: title: CreateGoogleSheetsRowAppendToolDTO + description: >- + Configuration used to create a tool that appends rows to a connected + Google Sheet. CreateMcpToolDTO: title: CreateMcpToolDTO + description: >- + Configuration used to create a tool that connects an assistant to a + Model Context Protocol server and exposes its available tools. + properties: + metadata: + description: >- + Connection metadata for the MCP server, including its communication + protocol. CreateQueryToolDTO: title: CreateQueryToolDTO + description: >- + Configuration used to create a tool that searches configured knowledge + bases and returns relevant content to the assistant. CreateSlackSendMessageToolDTO: title: CreateSlackSendMessageToolDTO + description: >- + Configuration used to create a tool that lets an assistant send a + message to Slack. CreateSmsToolDTO: title: CreateSmsToolDTO + description: >- + Configuration used to create a tool that lets an assistant send an SMS + message during a call. CreateTextEditorToolDTO: title: CreateTextEditorToolDTO + description: >- + Configuration used to create a tool that reads and edits text files in + a configured environment. CreateTransferCallToolDTO: title: CreateTransferCallToolDTO + description: >- + Configuration used to create a tool that transfers the active call to + one of its configured destinations. + properties: + type: + description: >- + The tool type. Use `transferCall` for a call-transfer tool. + CreateSipRequestToolDTO: + description: >- + Configuration used to create a tool that sends SIP `INFO`, `MESSAGE`, + or `NOTIFY` requests with configured headers and body. + CreateVoicemailToolDTO: + description: >- + Configuration used to create a voicemail-detection tool with optional + beep detection for supported calls. CreateCustomKnowledgeBaseDTO: title: CreateCustomKnowledgeBaseDTO + description: >- + Configuration for connecting a custom knowledge-base implementation + through a customer-hosted server. + KnowledgeBase: + description: >- + A knowledge-base configuration, including its provider, model, + description, and associated files. + CodeToolEnvironmentVariable: + description: >- + An environment variable supplied to code-tool execution, with support + for Liquid templates in its value. + McpToolMessages: + description: >- + Per-tool message overrides for a tool discovered through an MCP server. + McpToolMetadata: + description: >- + Protocol metadata used to communicate with an MCP server. + OpenAIFunction: + description: >- + Function definition exposed to a language model, including its name, + purpose, parameter schema, and strict-schema behavior. + OpenAIFunctionParameters: + description: >- + JSON object schema defining the properties accepted by a function and + which properties are required. + ToolParameter: + description: >- + Static key-value parameter added to a tool request, with Liquid template + support for string values. + ToolRejectionPlan: + description: >- + Conditions evaluated to determine whether a requested tool call should + be rejected. + TransferFallbackPlan: + description: >- + Controls the message and end-call behavior used when a call transfer + fails. + TransferPlan: + description: >- + Controls how a call transfer is executed, including blind and warm + transfer modes, dialing and SIP behavior, hold audio, context, summary, + and failure handling. WorkflowOpenAIModel: title: WorkflowOpenAIModel + description: >- + Workflow model configuration for OpenAI, including model selection, + temperature, and maximum output tokens. WorkflowAnthropicModel: title: WorkflowAnthropicModel + description: >- + Workflow model configuration for Anthropic, including model selection, + thinking, temperature, and maximum output tokens. + WorkflowAnthropicBedrockModel: + description: >- + Workflow model configuration for Anthropic through Amazon Bedrock, + including model selection, thinking, temperature, and maximum output + tokens. + WorkflowGoogleModel: + description: >- + Workflow model configuration for Google, including model selection, + temperature, and maximum output tokens. + WorkflowCustomModel: + description: >- + Workflow model configuration for a custom language model endpoint, + including URL, headers, metadata delivery, timeout, model, temperature, + and maximum output tokens. + WorkflowOverrides: + description: >- + Per-call overrides for values used in workflow template variables. + CreateWorkflowDTO: + description: >- + Configuration for creating a graph-based workflow, including + conversation and tool nodes, directed edges, global prompts, shared + providers, hooks, credentials, and call behavior. + properties: + nodes: + description: >- + Nodes that make up the workflow graph. Conversation nodes interact + with the customer, while tool nodes invoke configured tools. + name: + description: Name used to identify the workflow. + edges: + description: Directed connections that determine transitions between nodes. + globalPrompt: + description: Prompt applied across the workflow's conversation nodes. + GlobalNodePlan: + description: >- + Controls whether a conversation node can be entered globally and the + condition evaluated before that node runs. + Edge: + description: >- + A directed connection between two workflow nodes, with an optional + AI-evaluated transition condition. + properties: + condition: + description: Condition that must evaluate to true to follow this edge. + from: + description: Name of the source workflow node. + to: + description: Name of the destination workflow node. + Condition: + description: >- + Compares a named parameter with a value using the selected comparison + operator. + RegexCondition: + description: >- + Evaluates whether targeted conversation-message content matches a + regular expression. + LiquidCondition: + description: >- + Evaluates a Liquid template that must return `true` or `false`. + GroupCondition: + description: >- + Combines nested regular-expression, Liquid, or grouped conditions with + an `AND` or `OR` operator. + MessageTarget: + description: >- + Selects a conversation message by participant role and position for + condition evaluation. + ContextEngineeringPlanAll: + description: >- + Includes all available messages when constructing context for a handoff. + properties: + type: + description: Selects inclusion of all available messages. + ContextEngineeringPlanLastNMessages: + description: >- + Includes a configured number of the most recent messages when + constructing context for a handoff. + properties: + type: + description: Selects inclusion of the most recent messages. + ContextEngineeringPlanNone: + description: >- + Excludes prior conversation messages when constructing context for a + handoff. + properties: + type: + description: Selects exclusion of prior conversation messages. + ContextEngineeringPlanUserAndAssistantMessages: + description: >- + Includes only user and assistant messages when constructing context for + a handoff. + properties: + type: + description: Selects inclusion of user and assistant messages only. + HandoffDestinationAssistant: + description: >- + Routes a handoff to a saved or transient assistant, with optional + context engineering, variable extraction, and assistant overrides. + properties: + type: + description: Selects an assistant as the handoff destination. + HandoffDestinationDynamic: + description: >- + Uses a webhook response to select the handoff destination at runtime. + properties: + type: + description: Selects a dynamically resolved handoff destination. + HandoffDestinationSquad: + description: >- + Routes a handoff to a saved or transient squad, with optional entry + assistant, context engineering, variable extraction, and overrides. + properties: + type: + description: Selects a squad as the handoff destination. + CallHookModelResponseTimeout: + description: >- + Runs configured actions when the language model does not respond before + its timeout. + VariableExtractionPlan: + description: >- + Defines structured variables to extract and optional aliases made + available during and after a call. + VariableExtractionAlias: + description: >- + Defines an additional Liquid-based variable from values extracted + during a call. + JsonSchema: + description: >- + JSON Schema definition used to describe structured data for extraction, + validation, or model output. + AnalyticsOperation: + description: >- + An aggregation or history operation applied to an analytics column, with + an optional response alias. + AnalyticsQuery: + description: >- + A named analytics query against call or subscription data, including + grouping, time range, and aggregation operations. + BarInsightMetadata: + description: >- + Display settings for a bar insight, including chart name, axis labels, + and optional y-axis bounds. + properties: + xAxisLabel: + description: Label displayed on the chart's x-axis. + yAxisLabel: + description: Label displayed on the chart's y-axis. + yAxisMin: + description: Minimum value displayed on the chart's y-axis. + yAxisMax: + description: Maximum value displayed on the chart's y-axis. + name: + description: Display name for the insight chart. + LineInsightMetadata: + description: >- + Display settings for a line insight, including chart name, axis labels, + and optional y-axis bounds. + properties: + xAxisLabel: + description: Label displayed on the chart's x-axis. + yAxisLabel: + description: Label displayed on the chart's y-axis. + yAxisMin: + description: Minimum value displayed on the chart's y-axis. + yAxisMax: + description: Maximum value displayed on the chart's y-axis. + name: + description: Display name for the insight chart. + EventsTableBooleanCondition: + description: >- + Filters event data by comparing a boolean field with an expected value. + EventsTableNumberCondition: + description: >- + Filters event data by comparing a numeric field with a value. + EventsTableStringCondition: + description: >- + Filters event data by comparing or searching a string field. + FilterDateTypeColumnOnCallTable: + description: >- + Filters call records by comparing a start or end timestamp with a date. + FilterNumberArrayTypeColumnOnCallTable: + description: >- + Filters numeric call fields using a list of values or an emptiness test. + FilterNumberTypeColumnOnCallTable: + description: >- + Filters call records by comparing a numeric field with a value. + FilterStringArrayTypeColumnOnCallTable: + description: >- + Filters string-valued call fields using a list of values or an emptiness + test. + FilterStringTypeColumnOnCallTable: + description: >- + Filters call records by comparing or searching a string-valued field. + FilterStructuredOutputColumnOnCallTable: + description: >- + Filters a structured-output value stored on a call using comparison, + membership, containment, or emptiness operators. + Insight: + description: >- + A saved insight returned by the API, including its visualization type, + identity, organization, and lifecycle timestamps. + InsightFormula: + description: >- + A formula used to calculate an insight from its query results, with an + optional display name. + InsightRunFormatPlan: + description: >- + Selects whether an insight run returns raw data or Recharts-formatted + data. + InsightTimeRange: + description: >- + Start, end, and timezone used to limit an insight query by time. + InsightTimeRangeWithStep: + description: >- + Start, end, timezone, and aggregation step used for a time-series insight + query. + JSONQueryOnCallTableWithNumberTypeColumn: + description: >- + VapiQL JSON query that aggregates a numeric call-table column with + optional call filters. + JSONQueryOnCallTableWithStringTypeColumn: + description: >- + VapiQL JSON query that counts values from a string-valued call-table + column with optional call filters. + JSONQueryOnCallTableWithStructuredOutputColumn: + description: >- + VapiQL JSON query that aggregates or counts a structured-output value + stored on call records. + JSONQueryOnEventsTable: + description: >- + VapiQL JSON query that counts or calculates the percentage of matching + events using optional typed event-data filters. + TimeRange: + description: >- + Start, end, timezone, and time step used for analytics aggregation. + VariableValueGroupBy: + description: >- + Groups analytics results by a selected assistant variable-value key. AssemblyAITranscriber: title: AssemblyAITranscriber + description: >- + Configuration for transcribing speech during assistant conversations + with AssemblyAI, including language, streaming model, endpointing, + vocabulary, and fallback settings. AzureSpeechTranscriber: title: AzureSpeechTranscriber + description: >- + Configuration for transcribing speech during assistant conversations + with Azure Speech, including language, segmentation, and fallback + settings. CustomTranscriber: title: CustomTranscriber + description: >- + Configuration for sending conversation audio to a custom WebSocket + transcription server. ElevenLabsTranscriber: title: ElevenLabsTranscriber + description: >- + Configuration for transcribing speech during assistant conversations + with ElevenLabs, including model, language, speech thresholds, and + fallback settings. GladiaTranscriber: title: GladiaTranscriber + description: >- + Configuration for transcribing speech during assistant conversations + with Gladia, including language behavior, audio processing, endpointing, + vocabulary, region, and fallback settings. GoogleTranscriber: title: GoogleTranscriber + description: >- + Configuration for transcribing speech during assistant conversations + with Google, including model, language, and fallback settings. SpeechmaticsTranscriber: title: SpeechmaticsTranscriber + description: >- + Configuration for transcribing speech during assistant conversations + with Speechmatics, including language, region, diarization, vocabulary, + endpointing, formatting, and fallback settings. + properties: + language: + description: >- + Language used for transcription. Set to `auto` to detect the + language automatically. + customVocabulary: + description: >- + Words and phrases that Speechmatics should recognize more + accurately, with optional phonetic alternatives. + SpeechmaticsCustomVocabularyItem: + description: >- + A word or phrase to prioritize during Speechmatics transcription, with + optional phonetic alternatives. TalkscriberTranscriber: title: TalkscriberTranscriber + description: >- + Configuration for transcribing speech during assistant conversations + with Talkscriber, including model, language, and fallback settings. OpenAITranscriber: title: OpenAITranscriber + description: >- + Configuration for transcribing speech during assistant conversations + with OpenAI, including model, language, and fallback settings. + CartesiaTranscriber: + description: >- + Configuration for transcribing speech during assistant conversations + with Cartesia, including model, language, and fallback settings. + properties: + provider: + description: Selects Cartesia for speech-to-text transcription. + model: + description: The Cartesia speech-to-text model used for transcription. + language: + description: The language code used for transcription. + SonioxTranscriber: + description: >- + Configuration for transcribing speech during assistant conversations + with Soniox, including model, language detection, endpointing, + vocabulary, and fallback settings. + properties: + provider: + description: Selects Soniox for speech-to-text transcription. CartesiaVoice: title: CartesiaVoice + description: >- + Configuration for synthesizing assistant speech with Cartesia, including + voice and model selection, language, generation controls, pronunciation + dictionaries, chunking, caching, and fallback settings. CustomVoice: title: CustomVoice + description: >- + Configuration for synthesizing assistant speech through a custom server, + including voice selection, server connection, chunking, caching, and + fallback settings. HumeVoice: title: HumeVoice + description: >- + Configuration for synthesizing assistant speech with Hume, including + model and voice selection, custom voice metadata, chunking, caching, and + fallback settings. TavusVoice: title: TavusVoice + description: >- + Configuration for using Tavus as the assistant's voice provider, + including persona, callback, context, greeting, conversation properties, + chunking, caching, and fallback settings. VapiVoice: title: VapiVoice + description: >- + Configuration for synthesizing assistant speech with Vapi, including + voice selection, speed, pronunciation dictionary, chunking, caching, and + fallback settings. + WellSaidVoice: + description: >- + Configuration for synthesizing assistant speech with WellSaid, including + voice and model selection, Speech Synthesis Markup Language support, + voice libraries, chunking, caching, and fallback settings. + SesameVoice: + description: >- + Configuration for synthesizing assistant speech with Sesame, including + voice and model selection, chunking, caching, and fallback settings. + InworldVoice: + description: >- + Configuration for synthesizing assistant speech with Inworld, including + voice and model selection, language, temperature, speaking rate, + chunking, caching, and fallback settings. + MinimaxVoice: + description: >- + Configuration for synthesizing assistant speech with MiniMax, including + voice and model selection, emotion, pitch, speed, volume, region, + language, text normalization, chunking, caching, and fallback settings. AIEdgeCondition: title: AIEdgeCondition + description: >- + An AI-evaluated boolean condition that determines whether a workflow + follows an edge. + properties: + type: + description: Selects an AI-evaluated workflow edge condition. LogicEdgeCondition: title: LogicEdgeCondition FailedEdgeCondition: title: FailedEdgeCondition ConversationNode: title: ConversationNode + description: >- + A workflow node where the assistant conducts a conversation using + optional node-specific providers, tools, prompt, and variable extraction. + properties: + prompt: + description: Prompt that guides the assistant while this node is active. + name: + description: Unique name used to identify this workflow node. ToolNode: title: ToolNode + description: >- + A workflow node that invokes an inline tool or an existing saved tool. + properties: + name: + description: Unique name used to identify this workflow node. ExactReplacement: title: ExactReplacement + description: >- + Replaces an exact word or phrase before text is sent to a voice + provider. RegexReplacement: title: RegexReplacement + description: >- + Replaces text matching a regular expression before it is sent to a + voice provider. FallbackCartesiaVoice: title: FallbackCartesiaVoice + description: >- + Fallback configuration for synthesizing assistant speech with Cartesia, + including voice and model selection, language, generation controls, + pronunciation dictionaries, chunking, and caching. FallbackHumeVoice: title: FallbackHumeVoice + description: >- + Fallback configuration for synthesizing assistant speech with Hume, + including model and voice selection, custom voice metadata, chunking, + and caching. FallbackCustomVoice: title: FallbackCustomVoice + description: >- + Fallback configuration for synthesizing assistant speech through a + custom server, including voice selection, server connection, chunking, + and caching. FallbackVapiVoice: title: FallbackVapiVoice + description: >- + Fallback configuration for synthesizing assistant speech with Vapi, + including voice selection, speed, pronunciation dictionary, chunking, + and caching. FallbackTavusVoice: title: FallbackTavusVoice + description: >- + Fallback configuration for using Tavus as the assistant's voice + provider, including persona, callback, context, greeting, conversation + properties, chunking, and caching. + FallbackCartesiaTranscriber: + description: >- + Fallback configuration for transcribing speech with Cartesia, including + model and language. + properties: + provider: + description: Selects Cartesia for speech-to-text transcription. + model: + description: The Cartesia speech-to-text model used for transcription. + language: + description: The language code used for transcription. + FallbackSonioxTranscriber: + description: >- + Fallback configuration for transcribing speech with Soniox, including + model, language detection, endpointing, and vocabulary. + properties: + provider: + description: Selects Soniox for speech-to-text transcription. + FallbackInworldVoice: + description: >- + Fallback configuration for synthesizing assistant speech with Inworld, + including voice and model selection, language, temperature, speaking + rate, chunking, and caching. + FallbackSesameVoice: + description: >- + Fallback configuration for synthesizing assistant speech with Sesame, + including voice and model selection, chunking, and caching. + FallbackWellSaidVoice: + description: >- + Fallback configuration for synthesizing assistant speech with WellSaid, + including voice and model selection, Speech Synthesis Markup Language + support, voice libraries, chunking, and caching. + FallbackPlan: + description: >- + Lists backup voice configurations that can be used if the primary voice + provider fails. + FallbackTranscriberPlan: + description: >- + Lists backup transcriber configurations that can be used if the primary + transcriber fails. + properties: + transcribers: + description: >- + Transcriber configurations available when the primary transcriber + fails. TransferAssistantHookAction: title: TransferAssistantHookAction FunctionCallAssistantHookAction: @@ -1115,148 +2824,885 @@ components: title: SayAssistantHookAction VapiSmartEndpointingPlan: title: VapiSmartEndpointingPlan + description: >- + Selects Vapi smart endpointing to determine when customer speech is + complete. LivekitSmartEndpointingPlan: title: LivekitSmartEndpointingPlan + description: >- + Configuration for using LiveKit smart endpointing, including provider + selection and wait-function behavior. + CustomEndpointingModelSmartEndpointingPlan: + description: >- + Configuration for using a custom endpointing model, including its + provider identifier and server connection. AssistantCustomEndpointingRule: title: AssistantCustomEndpointingRule + description: >- + A custom endpointing rule that matches the assistant's last message and + applies a configured timeout. CustomerCustomEndpointingRule: title: CustomerCustomEndpointingRule + description: >- + A custom endpointing rule that matches the customer's current speech + and applies a configured timeout. BothCustomEndpointingRule: title: BothCustomEndpointingRule + description: >- + A custom endpointing rule that matches both the assistant's last + message and the customer's current speech before applying a configured + timeout. + properties: + customerRegex: + description: >- + The regular expression pattern matched against the customer's + speech. + StartSpeakingPlan: + description: >- + Controls when the assistant begins speaking after customer speech, + including the minimum wait, endpointing strategy, and custom endpointing + rules. + StopSpeakingPlan: + description: >- + Controls when the assistant stops speaking after a customer + interruption, including word and voice thresholds, restart delay, and + phrase exceptions. + BackgroundSpeechDenoisingPlan: + description: >- + Controls smart and Fourier denoising applied to customer audio before + transcription. + TranscriptionEndpointingPlan: + description: >- + Controls endpointing delays based on whether customer speech ends with + punctuation, without punctuation, or with a number. + SmartDenoisingPlan: + description: >- + Controls whether Krisp smart denoising filters background speech and + noise. + FourierDenoisingPlan: + description: >- + Configuration for Fourier denoising, including media detection, + thresholds, baseline calculation, and analysis window. + VoicemailDetectionBackoffPlan: + description: >- + Controls voicemail-detection retry timing, including when retries start, + retry frequency, and maximum attempts. + AnalysisPlan: + description: >- + Configuration for post-call analysis of summaries, structured-data + extraction, success evaluation, and outcomes. + SummaryPlan: + description: >- + Controls generation of a post-call summary, including prompt messages, + enablement, and request timeout. + StructuredDataPlan: + description: >- + Controls extraction of post-call structured data, including prompt + messages, JSON schema, enablement, and request timeout. + StructuredDataMultiPlan: + description: >- + Associates a catalog key with a structured data extraction plan. + SuccessEvaluationPlan: + description: >- + Controls post-call success evaluation, including the rubric, prompt + messages, enablement, and request timeout. + ArtifactPlan: + description: >- + Controls artifacts generated and stored for calls, including recordings, + packet captures, logs, transcripts, structured outputs, scorecards, and + custom storage paths. + TranscriptPlan: + description: >- + Controls whether the call transcript is stored and the speaker names + used in the transcript. + MonitorPlan: + description: >- + Controls real-time listening and control for assistant calls, + authentication requirements for monitor URLs, and attached monitors. + properties: + monitorIds: + description: >- + IDs of the monitors attached to the assistant. Use this field for + transient assistants or to update the monitors attached to an + existing assistant. Defaults to an empty array. + CompliancePlan: + description: >- + Controls HIPAA and PCI requirements, transcript security filtering, and + recording-consent handling for assistant calls. + properties: + recordingConsentPlan: + description: >- + Controls how recording consent is requested before the assistant + joins the call. + RecordingConsentPlanStayOnLine: + description: >- + Configuration for requesting recording consent by treating continued + presence on the call as consent, including the announcement voice and + wait time. + properties: + type: + description: >- + Identifies a stay-on-line recording-consent plan, which treats + remaining on the call as consent. + RecordingConsentPlanVerbal: + description: >- + Configuration for requesting explicit verbal recording consent, + including the announcement voice and action to take when the customer + declines. + properties: + type: + description: >- + Identifies a verbal recording-consent plan that requires the + customer to explicitly consent or decline. + SecurityFilterBase: + description: >- + Base configuration for a security filter applied to transcripts before + model processing. + SecurityFilterPlan: + description: >- + Controls filtering of transcripts for security threats before content + is sent to the assistant's language model, including filter selection, + handling mode, and replacement text. + SQLInjectionSecurityFilter: + description: Filters potential SQL injection patterns from transcripts. + XSSSecurityFilter: + description: >- + Filters potential cross-site scripting (XSS) patterns from transcripts. + SSRFSecurityFilter: + description: >- + Filters potential server-side request forgery (SSRF) patterns from + transcripts. + RCESecurityFilter: + description: >- + Filters potential remote code execution (RCE) patterns from transcripts. + PromptInjectionSecurityFilter: + description: Filters potential prompt-injection patterns from transcripts. + RegexSecurityFilter: + description: >- + Filters transcript content that matches a custom regular expression. + BackoffPlan: + description: >- + Controls retry behavior for failed server requests, including strategy, + maximum retries, base delay, and status codes excluded from retries. + properties: + baseDelaySeconds: + description: >- + Base delay in seconds. For fixed backoff, this is the delay between + retries. For exponential backoff, this is the initial delay. + excludedStatusCodes: + description: >- + HTTP status codes that should not trigger a retry. By default, any + non-2xx status code not listed here can be retried. + Server: + description: >- + Configuration for requests Vapi sends to a customer server, including + URL, authentication, headers, timeout, encryption, static IP addresses, + and retry behavior. + CallHookCallEnding: + description: >- + Runs configured actions when a call is ending, optionally only when its + filters match. + CallHookAssistantSpeechInterrupted: + description: >- + Runs configured actions when the customer's speech interrupts the + assistant. + CallHookCustomerSpeechInterrupted: + description: >- + Runs configured actions when the assistant interrupts the customer's + speech. + CallHookCustomerSpeechTimeout: + description: >- + Runs configured actions when the customer does not speak before the + configured timeout, with support for trigger limits and named instances. + properties: + options: + description: >- + Controls the speech timeout, maximum trigger count, and counter + reset behavior for this hook. + ToolCallHookAction: + description: >- + A hook action that invokes an inline tool or an existing tool when the + hook triggers. + MessageAddHookAction: + description: >- + A hook action that adds an OpenAI-format message to the conversation and + can trigger an assistant response. + CallHookFilter: + description: >- + Matches a call field against one or more allowed values to determine + whether a hook runs. + SayHookAction: + description: >- + A hook action that makes the assistant speak exact text or generate a + response from a prompt. + CustomerSpeechTimeoutOptions: + description: >- + Controls how long a hook waits for customer speech, how often it can + trigger, and when its trigger counter resets. + properties: + triggerResetMode: + description: >- + Controls whether the hook's trigger counter resets after the + customer speaks. Defaults to `never`. AnthropicModel: title: AnthropicModel + description: >- + Configuration for generating assistant responses with Anthropic, + including model, prompts, tools, knowledge-base access, reasoning, and + generation settings. + AnthropicBedrockModel: + description: >- + Configuration for generating assistant responses with Anthropic models + through Amazon Bedrock, including model, prompts, tools, knowledge-base + access, reasoning, and generation settings. AnyscaleModel: title: AnyscaleModel + description: >- + Configuration for generating assistant responses with Anyscale, + including model, prompts, tools, knowledge-base access, and generation + settings. + properties: + provider: + description: Routes assistant response generation through Anyscale. CerebrasModel: title: CerebrasModel + description: >- + Configuration for generating assistant responses with Cerebras, + including model, prompts, tools, knowledge-base access, and generation + settings. + properties: + provider: + description: Routes assistant response generation through Cerebras. CustomLLMModel: title: CustomLLMModel + description: >- + Configuration for generating assistant responses through a custom + language model endpoint, including server URL, headers, metadata, + prompts, tools, and generation settings. DeepInfraModel: title: DeepInfraModel + description: >- + Configuration for generating assistant responses with DeepInfra, + including model, prompts, tools, knowledge-base access, and generation + settings. + properties: + provider: + description: Routes assistant response generation through DeepInfra. DeepSeekModel: title: DeepSeekModel + description: >- + Configuration for generating assistant responses with DeepSeek, + including model, prompts, tools, knowledge-base access, and generation + settings. + properties: + provider: + description: Routes assistant response generation through DeepSeek. GoogleModel: title: GoogleModel + description: >- + Configuration for generating assistant responses with Google, including + model, prompts, tools, knowledge-base access, realtime settings, and + generation settings. + properties: + provider: + description: Routes assistant response generation through Google. GroqModel: title: GroqModel + description: >- + Configuration for generating assistant responses with Groq, including + model, prompts, tools, knowledge-base access, and generation settings. + properties: + provider: + description: Routes assistant response generation through Groq. InflectionAIModel: title: InflectionAIModel + description: >- + Configuration for generating assistant responses with Inflection AI, + including model, prompts, tools, knowledge-base access, and generation + settings. + properties: + provider: + description: Routes assistant response generation through Inflection AI. + MinimaxLLMModel: + description: >- + Configuration for generating assistant responses with MiniMax, including + model, prompts, tools, knowledge-base access, and generation settings. + properties: + provider: + description: Routes assistant response generation through MiniMax. OpenAIModel: title: OpenAIModel + description: >- + Configuration for generating assistant responses with OpenAI, including + model selection, fallback models, prompts, tools, prompt caching, and + generation settings. OpenRouterModel: title: OpenRouterModel + description: >- + Configuration for generating assistant responses through OpenRouter, + including routed model selection, prompts, tools, knowledge-base access, + and generation settings. + properties: + provider: + description: Routes assistant response generation through OpenRouter. PerplexityAIModel: title: PerplexityAIModel + description: >- + Configuration for generating assistant responses with Perplexity AI, + including model, prompts, tools, knowledge-base access, and generation + settings. + properties: + provider: + description: Routes assistant response generation through Perplexity AI. TogetherAIModel: title: TogetherAIModel + description: >- + Configuration for generating assistant responses with Together AI, + including model, prompts, tools, knowledge-base access, and generation + settings. + properties: + provider: + description: Routes assistant response generation through Together AI. XaiModel: title: XaiModel + description: >- + Configuration for generating assistant responses with xAI, including + model, prompts, tools, knowledge-base access, and generation settings. + properties: + provider: + description: Routes assistant response generation through xAI. GoogleVoicemailDetectionPlan: title: GoogleVoicemailDetectionPlan + description: >- + Configuration for detecting voicemail with Google, including detection + type, maximum beep wait, and retry backoff. OpenAIVoicemailDetectionPlan: title: OpenAIVoicemailDetectionPlan + description: >- + Configuration for detecting voicemail with OpenAI, including detection + type, maximum beep wait, and retry backoff. TwilioVoicemailDetectionPlan: title: TwilioVoicemailDetectionPlan + description: >- + Configuration for Twilio answering-machine detection, including + recognized outcomes, enablement, timeout, speech thresholds, and silence + timeout. VapiVoicemailDetectionPlan: title: VapiVoicemailDetectionPlan + description: >- + Configuration for detecting voicemail with Vapi, including detection + type, maximum beep wait, and retry backoff. TransportConfigurationTwilio: title: TransportConfigurationTwilio + description: >- + Configuration passed to Twilio for assistant calls, including ring + timeout and Twilio recording behavior. + properties: + provider: + description: Selects Twilio as the call transport provider. LangfuseObservabilityPlan: title: LangfuseObservabilityPlan + description: >- + Configuration for sending assistant call traces to Langfuse, including + prompt version linkage, trace naming, tags, and metadata. + properties: + provider: + description: Routes assistant call observability data to Langfuse. CreateAnthropicCredentialDTO: title: CreateAnthropicCredentialDTO + description: >- + Credentials for authenticating assistant model requests with Anthropic. + properties: + provider: + description: Selects Anthropic as the credential provider. + CreateAnthropicBedrockCredentialDTO: + description: >- + Credentials for authenticating Anthropic model requests through Amazon + Bedrock, including AWS region and authentication method. + properties: + provider: + description: Selects Anthropic through Amazon Bedrock as the credential provider. CreateAnyscaleCredentialDTO: title: CreateAnyscaleCredentialDTO + description: >- + Credentials for authenticating assistant model requests with Anyscale. + properties: + provider: + description: Selects Anyscale as the credential provider. CreateAssemblyAICredentialDTO: title: CreateAssemblyAICredentialDTO + description: >- + Credentials for authenticating transcription requests with AssemblyAI. + properties: + provider: + description: Selects AssemblyAI as the credential provider. CreateAzureCredentialDTO: title: CreateAzureCredentialDTO + description: >- + Credentials for Azure Speech or Blob Storage, including service, region, + and optional storage bucket settings. + properties: + provider: + description: Selects Azure as the credential provider. CreateAzureOpenAICredentialDTO: title: CreateAzureOpenAICredentialDTO + description: >- + Credentials for authenticating assistant model requests with Azure + OpenAI, including region, endpoint, and available models. + properties: + provider: + description: Selects Azure OpenAI as the credential provider. + region: + description: Azure region that hosts the OpenAI resource. + models: + description: Azure OpenAI models available through this credential. + openAIEndpoint: + description: Endpoint URL for the Azure OpenAI resource. CreateByoSipTrunkCredentialDTO: title: CreateByoSipTrunkCredentialDTO + description: >- + Configuration for connecting Vapi to a bring-your-own SIP trunk or + carrier, including gateways, outbound authentication, number handling, + and optional session border controller routing. + properties: + provider: + description: Selects a bring-your-own SIP trunk as the credential provider. CreateCartesiaCredentialDTO: title: CreateCartesiaCredentialDTO + description: >- + Credentials for authenticating speech recognition and voice synthesis + requests with Cartesia. + properties: + provider: + description: Selects Cartesia as the credential provider. CreateCerebrasCredentialDTO: title: CreateCerebrasCredentialDTO + description: >- + Credentials for authenticating assistant model requests with Cerebras. + properties: + provider: + description: Selects Cerebras as the credential provider. CreateCloudflareCredentialDTO: title: CreateCloudflareCredentialDTO + description: >- + Credentials for storing call artifacts in Cloudflare R2, including + account details, bucket configuration, and upload fallback order. + properties: + provider: + description: Selects Cloudflare R2 as the credential provider. CreateCustomLLMCredentialDTO: title: CreateCustomLLMCredentialDTO + description: >- + Credentials for authenticating requests to a custom language model with + an API key or OAuth 2.0 authentication plan. + properties: + provider: + description: Selects a custom language model as the credential provider. CreateDeepgramCredentialDTO: title: CreateDeepgramCredentialDTO + description: >- + Credentials for authenticating speech recognition and voice synthesis + requests with Deepgram, with an optional API URL for an on-premises + instance. + properties: + provider: + description: Selects Deepgram as the credential provider. CreateDeepInfraCredentialDTO: title: CreateDeepInfraCredentialDTO + description: >- + Credentials for authenticating assistant model requests with DeepInfra. + properties: + provider: + description: Selects DeepInfra as the credential provider. CreateDeepSeekCredentialDTO: title: CreateDeepSeekCredentialDTO + description: >- + Credentials for authenticating assistant model requests with DeepSeek. + properties: + provider: + description: Selects DeepSeek as the credential provider. CreateGcpCredentialDTO: title: CreateGcpCredentialDTO + description: >- + Service-account credentials for Google Cloud resources and optional + call-artifact storage, including region, bucket configuration, and + upload fallback order. + properties: + provider: + description: Selects Google Cloud as the credential provider. + bucketPlan: + description: >- + Bucket configuration used to store call artifacts in Google Cloud + Storage. CreateGladiaCredentialDTO: title: CreateGladiaCredentialDTO + description: >- + Credentials for authenticating transcription requests with Gladia. + properties: + provider: + description: Selects Gladia as the credential provider. CreateGoHighLevelCredentialDTO: title: CreateGoHighLevelCredentialDTO + description: >- + Credentials for authenticating Vapi integrations with GoHighLevel. + properties: + provider: + description: Selects GoHighLevel as the credential provider. CreateGoogleCredentialDTO: title: CreateGoogleCredentialDTO + description: >- + Credentials for authenticating assistant model requests with Google AI. + properties: + provider: + description: Selects Google AI as the credential provider. CreateGroqCredentialDTO: title: CreateGroqCredentialDTO + description: >- + Credentials for authenticating assistant model requests with Groq. + properties: + provider: + description: Selects Groq as the credential provider. CreateHumeCredentialDTO: title: CreateHumeCredentialDTO + description: >- + Credentials for authenticating voice synthesis requests with Hume. + properties: + provider: + description: Selects Hume as the credential provider. CreateInflectionAICredentialDTO: title: CreateInflectionAICredentialDTO + description: >- + Credentials for authenticating assistant model requests with Inflection + AI. + properties: + provider: + description: Selects Inflection AI as the credential provider. CreateLangfuseCredentialDTO: title: CreateLangfuseCredentialDTO + description: >- + Credentials for sending assistant call traces to a Langfuse project, + including its public key, secret key, and host URL. + properties: + provider: + description: Selects Langfuse as the credential provider. CreateLmntCredentialDTO: title: CreateLmntCredentialDTO + description: >- + Credentials for authenticating voice synthesis requests with LMNT. + properties: + provider: + description: Selects LMNT as the credential provider. CreateMakeCredentialDTO: title: CreateMakeCredentialDTO + description: >- + Credentials for authenticating Vapi integrations with Make, including + team, region, and API key. + properties: + provider: + description: Selects Make as the credential provider. CreateMistralCredentialDTO: title: CreateMistralCredentialDTO + description: >- + Credentials for authenticating assistant model requests with Mistral. + properties: + provider: + description: Selects Mistral as the credential provider. + CreateMinimaxCredentialDTO: + description: >- + Credentials for authenticating assistant model and voice synthesis + requests with MiniMax, including the MiniMax group identifier. + properties: + provider: + description: Selects MiniMax as the credential provider. CreateNeuphonicCredentialDTO: title: CreateNeuphonicCredentialDTO + description: >- + Credentials for authenticating voice synthesis requests with Neuphonic. + properties: + provider: + description: Selects Neuphonic as the credential provider. CreateOpenAICredentialDTO: title: CreateOpenAICredentialDTO + description: >- + Credentials for authenticating assistant model, transcription, and + voice synthesis requests with OpenAI. + properties: + provider: + description: Selects OpenAI as the credential provider. CreateOpenRouterCredentialDTO: title: CreateOpenRouterCredentialDTO + description: >- + Credentials for authenticating assistant model requests with OpenRouter. + properties: + provider: + description: Selects OpenRouter as the credential provider. CreatePerplexityAICredentialDTO: title: CreatePerplexityAICredentialDTO + description: >- + Credentials for authenticating assistant model requests with Perplexity + AI. + properties: + provider: + description: Selects Perplexity AI as the credential provider. CreatePlayHTCredentialDTO: title: CreatePlayHTCredentialDTO + description: >- + Credentials for authenticating voice synthesis requests with PlayHT, + including the PlayHT user identifier. + properties: + provider: + description: Selects PlayHT as the credential provider. + userId: + description: PlayHT user identifier associated with the API key. CreateRimeAICredentialDTO: title: CreateRimeAICredentialDTO + description: >- + Credentials for authenticating voice synthesis requests with Rime AI. + properties: + provider: + description: Selects Rime AI as the credential provider. CreateRunpodCredentialDTO: title: CreateRunpodCredentialDTO + description: >- + Credentials for authenticating assistant model requests through Runpod. + properties: + provider: + description: Selects Runpod as the credential provider. CreateS3CredentialDTO: title: CreateS3CredentialDTO + description: >- + Credentials for storing call artifacts in Amazon S3, including access + keys, region, bucket, path prefix, and upload fallback order. + properties: + provider: + description: Selects Amazon S3 as the credential provider. CreateSmallestAICredentialDTO: title: CreateSmallestAICredentialDTO + description: >- + Credentials for authenticating voice synthesis requests with Smallest + AI. + properties: + provider: + description: Selects Smallest AI as the credential provider. CreateSpeechmaticsCredentialDTO: title: CreateSpeechmaticsCredentialDTO + description: >- + Credentials for authenticating transcription requests with Speechmatics. + properties: + provider: + description: Selects Speechmatics as the credential provider. + CreateSonioxCredentialDTO: + description: >- + Credentials for authenticating transcription requests with Soniox. + properties: + provider: + description: Selects Soniox as the credential provider. CreateSupabaseCredentialDTO: title: CreateSupabaseCredentialDTO + description: >- + Credentials for storing call artifacts in Supabase's S3-compatible + storage, including bucket configuration and upload fallback order. + properties: + provider: + description: Selects Supabase Storage as the credential provider. + bucketPlan: + description: >- + Supabase S3-compatible bucket configuration used to store call + artifacts. CreateTavusCredentialDTO: title: CreateTavusCredentialDTO + description: >- + Credentials for authenticating voice synthesis requests with Tavus. + properties: + provider: + description: Selects Tavus as the credential provider. CreateTogetherAICredentialDTO: title: CreateTogetherAICredentialDTO + description: >- + Credentials for authenticating assistant model requests with Together + AI. + properties: + provider: + description: Selects Together AI as the credential provider. CreateTrieveCredentialDTO: title: CreateTrieveCredentialDTO + description: >- + Credentials for authenticating knowledge-base requests with Trieve. + properties: + provider: + description: Selects Trieve as the credential provider. CreateTwilioCredentialDTO: title: CreateTwilioCredentialDTO + description: >- + Credentials for authenticating telephony requests with Twilio using an + account SID and either an auth token or API key credentials. + properties: + provider: + description: Selects Twilio as the credential provider. + accountSid: + description: Twilio Account SID associated with the credential. CreateVonageCredentialDTO: title: CreateVonageCredentialDTO + description: >- + Credentials for authenticating telephony requests with Vonage. + properties: + provider: + description: Selects Vonage as the credential provider. + apiKey: + description: Vonage API key associated with the credential. CreateWebhookCredentialDTO: title: CreateWebhookCredentialDTO + properties: + provider: + description: Selects webhook authentication as the credential provider. CreateXAiCredentialDTO: title: CreateXAiCredentialDTO + description: >- + Credentials for authenticating assistant model requests with xAI. + properties: + provider: + description: Selects xAI as the credential provider. + CreateInworldCredentialDTO: + description: >- + Credentials for authenticating voice synthesis requests with Inworld. + properties: + provider: + description: Selects Inworld as the credential provider. + CreateWellSaidCredentialDTO: + description: >- + Credentials for authenticating voice synthesis requests with WellSaid. + properties: + provider: + description: Selects WellSaid as the credential provider. CreateGoogleCalendarOAuth2ClientCredentialDTO: title: CreateGoogleCalendarOAuth2ClientCredentialDTO + description: >- + OAuth 2.0 client credential for Google Calendar integrations. + properties: + provider: + description: Selects a Google Calendar OAuth 2.0 client credential. CreateGoogleCalendarOAuth2AuthorizationCredentialDTO: title: CreateGoogleCalendarOAuth2AuthorizationCredentialDTO + description: >- + Stored OAuth 2.0 authorization for Google Calendar operations. + properties: + provider: + description: Selects a Google Calendar OAuth 2.0 authorization credential. CreateGoogleSheetsOAuth2AuthorizationCredentialDTO: title: CreateGoogleSheetsOAuth2AuthorizationCredentialDTO + description: >- + Stored OAuth 2.0 authorization for Google Sheets operations. + properties: + provider: + description: Selects a Google Sheets OAuth 2.0 authorization credential. CreateSlackOAuth2AuthorizationCredentialDTO: title: CreateSlackOAuth2AuthorizationCredentialDTO + description: >- + Stored OAuth 2.0 authorization for Slack operations. + properties: + provider: + description: Selects a Slack OAuth 2.0 authorization credential. CreateGoHighLevelMCPCredentialDTO: title: CreateGoHighLevelMCPCredentialDTO + description: >- + OAuth 2.0 session credentials for authenticating GoHighLevel MCP + requests. + properties: + provider: + description: Selects GoHighLevel OAuth 2.0 authorization for MCP. + CreateCustomCredentialDTO: + description: >- + Reusable custom credentials for authenticating outbound requests, with + optional public-key encryption for sensitive request data. + properties: + provider: + description: Selects a custom credential configuration. + CreateEmailCredentialDTO: + description: >- + Destination configuration for sending Vapi alerts to an email address. + properties: + provider: + description: Selects email as the alert destination provider. + CreateSlackWebhookCredentialDTO: + description: >- + Credentials for sending Vapi alerts through a Slack incoming webhook. + properties: + provider: + description: Selects a Slack incoming webhook as the credential provider. + SipTrunkGateway: + description: >- + Network and routing settings for a SIP trunk gateway, including address, + port, netmask, inbound and outbound use, signaling protocol, and OPTIONS + health checks. + SipTrunkOutboundAuthenticationPlan: + description: >- + Credentials and optional SIP REGISTER settings used to authenticate + outbound calls with a SIP trunk. + properties: + authUsername: + description: Username used to authenticate outbound SIP requests. + SipTrunkOutboundSipRegisterPlan: + description: >- + Registration settings used when the SIP trunk requires SIP REGISTER. + properties: + domain: + description: SIP registrar domain used for registration. + username: + description: Username sent with the SIP REGISTER request. + realm: + description: Authentication realm used for SIP registration. + SbcConfiguration: + description: >- + Routes bring-your-own SIP traffic through an on-premises session border + controller instead of Vapi's managed controller. + CloudflareR2BucketPlan: + description: >- + Cloudflare R2 bucket configuration for call-artifact storage, including + access keys, base URL, bucket name, and path. + GcpKey: + description: >- + Google Cloud service-account key used to authenticate access to Google + Cloud resources. + BucketPlan: + description: >- + Google Cloud Storage bucket configuration for call artifacts, including + bucket name, region, path, and optional HMAC credentials. + SupabaseBucketPlan: + description: >- + Supabase S3-compatible bucket configuration for call artifacts, + including region, endpoint, access keys, bucket name, and path. + OAuth2AuthenticationPlan: + description: >- + Client-credentials configuration for obtaining an OAuth 2.0 access token + used to authenticate outbound requests. + properties: + type: + description: Selects OAuth 2.0 authentication. + HMACAuthenticationPlan: + description: >- + Configuration for signing outbound requests with an HMAC secret, + including algorithm, headers, payload format, and signature encoding. + properties: + type: + description: Selects HMAC request authentication. + BearerAuthenticationPlan: + description: >- + Configuration for authenticating outbound requests with a bearer token, + including header name and optional `Bearer` prefix. + properties: + type: + description: Selects bearer-token authentication. + PublicKeyEncryptionPlan: + description: >- + Configuration for encrypting sensitive outbound request data with a + public key. + SpkiPemPublicKeyConfig: + description: >- + An SPKI public key in PEM format used to encrypt sensitive request data. + Oauth2AuthenticationSession: + description: >- + OAuth 2.0 session tokens and expiration used to authenticate integration + requests. AssistantHookCallEnding: title: AssistantHookCallEnding AssistantHookAssistantSpeechInterrupted: @@ -1265,42 +3711,250 @@ components: title: AssistantHookCustomerSpeechInterrupted TransferPhoneNumberHookAction: title: TransferPhoneNumberHookAction + description: >- + A phone-number hook action that transfers the call to a phone number or + SIP destination. SayPhoneNumberHookAction: title: SayPhoneNumberHookAction + description: >- + A phone-number hook action that speaks an exact message to the caller. PhoneNumberHookCallRinging: title: PhoneNumberHookCallRinging + description: >- + Runs configured transfer or message actions when an incoming call rings + and its caller-number prefix filters match. + PhoneNumberHookCallEnding: + description: >- + Runs configured transfer or message actions when a call ends with a + matching assistant-request failure reason. + PhoneNumberCallRingingHookFilter: + description: >- + Matches an incoming caller's phone number against one or more prefixes + before a ringing hook runs. + PhoneNumberCallEndingHookFilter: + description: >- + Matches the call's ended reason against configured assistant-request + failure reasons before an ending hook runs. + CreateCustomerDTO: + description: >- + Customer details used for call delivery and assistant personalization, + including phone or SIP destination, contact identifiers, extension, and + assistant overrides. + SchedulePlan: + description: >- + Time window that controls the earliest and latest time a call may begin. + DialPlanEntry: + description: >- + Associates a phone number with the customers to dial through that number + in a batch call plan. + SipAuthentication: + description: >- + Realm, username, and password used to authenticate SIP requests. + ImportTwilioPhoneNumberDTO: + description: >- + Configuration for importing a Twilio phone number into Vapi, including + Twilio credentials, routing target, fallback destination, hooks, SMS, + and server settings. + Analysis: + description: >- + Post-call analysis results, including summary, structured data, and + success evaluation outputs. + Artifact: + description: >- + Artifacts generated during a call, including messages, recordings, + transcript, logs, packet capture, workflow-node data, variables, + performance metrics, structured outputs, scorecards, and transfers. + NodeArtifact: + description: >- + Messages and variable values captured while a workflow node was active. + AssistantActivation: + description: >- + Identifies an assistant that became active during a call. + Recording: + description: >- + Call recording locations, including stereo, video, and separated mono + recording URLs. + Mono: + description: >- + Mono recording URLs for the combined call and isolated assistant and + customer audio. + RecordingConsent: + description: >- + Result of the recording-consent flow, including consent type and the + time consent was granted. + Compliance: + description: >- + Compliance information captured for a call, including recording consent. + ComplianceOverride: + description: >- + Overrides storage behavior for an output when HIPAA compliance is + enabled. + PerformanceMetrics: + description: >- + Call performance measurements, including per-turn and average provider, + endpointing, transport, and interruption metrics. + TurnLatency: + description: >- + Model, voice, transcription, endpointing, and total latency measurements + for a conversation turn. + Monitor: + description: >- + Live monitoring data for a call, including attached monitor results and + listening and control URLs. + properties: + monitors: + description: Results produced by monitors attached to the call. + MonitorResult: + description: >- + Result of evaluating an attached monitor's filter for a call. + properties: + monitorId: + description: Unique identifier of the monitor that produced this result. + filterPassed: + description: Whether the monitor's filter matched the call. + CallBatchError: + description: >- + Error returned for one customer entry in a batch call request. + properties: + customer: + description: Customer configuration associated with the failed call. + error: + description: Error message explaining why the call could not be created. + CostBreakdown: + description: >- + Aggregated call costs and usage, including transport, transcription, + model, voice, Vapi, analysis, token, and character totals. + AnalysisCostBreakdown: + description: >- + Analysis costs and token usage grouped by summary, structured data, + success evaluation, and structured-output generation. + SubscriptionLimits: + description: >- + Organization concurrency limits and remaining concurrent call capacity. TransportCost: title: TransportCost + description: >- + Telephony transport cost for a call, including provider, billable + minutes, and amount. + properties: + provider: + description: Telephony or transport provider that generated the cost. TranscriberCost: title: TranscriberCost + description: >- + Speech-to-text cost for a call, including transcriber, billable minutes, + and amount. ModelCost: title: ModelCost + description: >- + Language-model cost for a call, including model, token usage, and amount. VoiceCost: title: VoiceCost + description: >- + Voice-synthesis cost for a call, including voice, character usage, and + amount. VapiCost: title: VapiCost + description: >- + Vapi platform cost for a call, including cost subtype, billable minutes, + and amount. VoicemailDetectionCost: title: VoicemailDetectionCost + description: >- + Voicemail-detection model cost, including provider, model, multimodal + token usage, and amount. AnalysisCost: title: AnalysisCost + description: >- + Cost for an individual analysis request, including analysis type, model, + token usage, and amount. KnowledgeBaseCost: title: KnowledgeBaseCost + description: >- + Knowledge-base model cost, including model, token usage, and amount. AssistantMessage: title: AssistantMessage + description: >- + An assistant-authored message, including content, refusal text, tool + calls, participant name, and metadata. ToolMessage: title: ToolMessage + description: >- + A tool-result message associated with a specific tool call. DeveloperMessage: title: DeveloperMessage + description: >- + A developer-authored instruction message supplied to the language + model. + OpenAIMessage: + description: >- + A conversation message represented in OpenAI chat format. + properties: + content: + description: Content of the conversation message. + role: + description: Role associated with the conversation message. + ToolCall: + description: >- + A tool invocation requested by the assistant, including its identifier, + type, and function details. + ToolCallFunction: + description: >- + The function name and serialized arguments associated with a tool call. ByoPhoneNumber: title: ByoPhoneNumber + description: >- + A phone number connected to Vapi through a bring-your-own telephony + provider, including its credential, routing, hooks, server settings, + and lifecycle metadata. TwilioPhoneNumber: title: TwilioPhoneNumber + description: >- + A Twilio phone number connected to Vapi, including its Twilio account + details, SMS configuration, routing, hooks, server settings, and + lifecycle metadata. VonagePhoneNumber: title: VonagePhoneNumber + description: >- + A Vonage phone number connected to Vapi, including its credential, + routing, hooks, server settings, and lifecycle metadata. VapiPhoneNumber: title: VapiPhoneNumber + description: >- + A Vapi-managed phone number or SIP URI, including its authentication, + routing, hooks, server settings, and lifecycle metadata. TelnyxPhoneNumber: title: TelnyxPhoneNumber + description: >- + A Telnyx phone number connected to Vapi, including its credential, + routing, hooks, server settings, and lifecycle metadata. + PhoneNumberPaginatedResponse: + description: >- + A paginated collection of phone numbers and metadata describing the + result set. + PaginationMeta: + description: >- + Pagination and retention metadata returned with a paginated list of + phone numbers. + properties: + itemsPerPage: + description: The number of phone numbers returned per page. + totalItems: + description: The total number of phone numbers matching the request. + currentPage: + description: The current page number. + itemsBeyondRetention: + description: >- + Whether additional matching phone numbers exist beyond the + organization's data-retention window. + createdAtLe: + description: >- + The inclusive upper creation-time boundary applied to the result + set. + createdAtGe: + description: >- + The inclusive lower creation-time boundary applied to the result + set. TrieveKnowledgeBaseImport: title: TrieveKnowledgeBaseImport TestSuiteTestScorerAI: @@ -1331,14 +3985,29 @@ components: title: GoHighLevelContactGetToolProviderDetails CreateByoPhoneNumberDTO: title: CreateByoPhoneNumberDTO + description: >- + Configuration used to connect a bring-your-own phone number to Vapi + with a stored telephony credential and routing settings. CreateTwilioPhoneNumberDTO: title: CreateTwilioPhoneNumberDTO + description: >- + Configuration used to import a Twilio phone number into Vapi with its + account credentials and routing settings. CreateVonagePhoneNumberDTO: title: CreateVonagePhoneNumberDTO + description: >- + Configuration used to import a Vonage phone number into Vapi with a + stored credential and routing settings. CreateVapiPhoneNumberDTO: title: CreateVapiPhoneNumberDTO + description: >- + Configuration used to provision a Vapi-managed phone number or connect + a SIP URI, with optional routing and authentication settings. CreateTelnyxPhoneNumberDTO: title: CreateTelnyxPhoneNumberDTO + description: >- + Configuration used to import a Telnyx phone number into Vapi with a + stored credential and routing settings. FunctionToolWithToolCall: title: FunctionToolWithToolCall GhlToolWithToolCall: @@ -1431,8 +4100,35 @@ components: title: ClientInboundMessageTransfer Call: title: Call + description: >- + A call record returned by Vapi. It contains the configuration and + resources used for the call, its lifecycle status and timestamps, + conversation messages, artifacts, analysis, and costs. + properties: + messages: + description: >- + Messages exchanged during the call, including user, assistant, + system, tool-call, and tool-result messages. CallBatchResponse: title: CallBatchResponse + description: >- + The result of a batch call creation request, containing successfully + created calls, per-call failures, and subscription limits recorded at + the end of the batch. + CreateCallDTO: + description: >- + Configuration used to create a single call or a batch of outbound + calls. Choose a saved or transient assistant, squad, or workflow, then + provide the customer, phone-number, scheduling, and transport settings + that apply. + UpdateCallDTO: + description: >- + Fields used to update an existing call. Currently, the call name can be + changed. + DeleteCallDTO: + description: >- + Configuration for deleting stored call data, including optional call + IDs for asynchronous bulk deletion. Chat: title: Chat CreateChatStreamResponse: @@ -1449,104 +4145,278 @@ components: title: ResponseErrorEvent UpdateByoPhoneNumberDTO: title: UpdateByoPhoneNumberDTO + description: >- + Fields used to update a bring-your-own phone number, including its + credential, number, routing, hooks, and server settings. UpdateTwilioPhoneNumberDTO: title: UpdateTwilioPhoneNumberDTO + description: >- + Fields used to update a Twilio phone number, including its account + credentials, SMS configuration, routing, hooks, and server settings. UpdateVonagePhoneNumberDTO: title: UpdateVonagePhoneNumberDTO + description: >- + Fields used to update a Vonage phone number, including its credential, + number, routing, hooks, and server settings. UpdateVapiPhoneNumberDTO: title: UpdateVapiPhoneNumberDTO + description: >- + Fields used to update a Vapi-managed phone number or SIP URI, including + its authentication, routing, hooks, and server settings. UpdateTelnyxPhoneNumberDTO: title: UpdateTelnyxPhoneNumberDTO + description: >- + Fields used to update a Telnyx phone number, including its credential, + number, routing, hooks, and server settings. CreateGhlToolDTO: title: CreateGhlToolDTO CreateMakeToolDTO: title: CreateMakeToolDTO CreateOutputToolDTO: title: CreateOutputToolDTO + ApiRequestTool: + description: >- + A reusable tool that sends HTTP requests to a configured API and can + authenticate, retry failures, and extract variables from responses. + properties: + method: + description: The HTTP method used for the API request. + CodeTool: + description: >- + A reusable tool that executes TypeScript code with configured + credentials, environment variables, and timeout. DtmfTool: title: DtmfTool + description: >- + A reusable tool that lets an assistant send DTMF keypad tones during a + call. EndCallTool: title: EndCallTool + description: >- + A reusable tool that lets an assistant end the active call. FunctionTool: title: FunctionTool + description: >- + A reusable custom function tool that sends model-generated arguments to + a configured server and returns the result to the assistant. GhlTool: title: GhlTool MakeTool: title: MakeTool TransferCallTool: title: TransferCallTool + description: >- + A reusable tool that transfers the active call to one of its configured + destinations. + properties: + type: + description: >- + The tool type. Use `transferCall` for a call-transfer tool. + HandoffTool: + description: >- + A reusable tool that hands a conversation to another assistant, squad, + or dynamically selected destination. + SipRequestTool: + description: >- + A reusable tool that sends SIP `INFO`, `MESSAGE`, or `NOTIFY` requests + with configured headers and body. + VoicemailTool: + description: >- + A reusable voicemail-detection tool with optional beep detection for + supported calls. OutputTool: title: OutputTool BashTool: title: BashTool + description: >- + A reusable tool that executes shell commands in a configured + environment. ComputerTool: title: ComputerTool + description: >- + A reusable tool that lets the model interact with a computer display + through screen, pointer, and keyboard actions. TextEditorTool: title: TextEditorTool + description: >- + A reusable tool that reads and edits text files in a configured + environment. QueryTool: title: QueryTool + description: >- + A reusable tool that searches configured knowledge bases and returns + relevant content to the assistant. GoogleCalendarCreateEventTool: title: GoogleCalendarCreateEventTool + description: >- + A reusable tool that adds events to a connected Google Calendar. GoogleSheetsRowAppendTool: title: GoogleSheetsRowAppendTool + description: >- + A reusable tool that appends rows to a connected Google Sheet. GoogleCalendarCheckAvailabilityTool: title: GoogleCalendarCheckAvailabilityTool + description: >- + A reusable tool that checks availability in a connected Google + Calendar. SlackSendMessageTool: title: SlackSendMessageTool + description: >- + A reusable tool that lets an assistant send a message to Slack. SmsTool: title: SmsTool + description: >- + A reusable tool that lets an assistant send an SMS message during a + call. McpTool: title: McpTool + description: >- + A reusable tool that connects an assistant to a Model Context Protocol + server and exposes its available tools. + properties: + metadata: + description: >- + Connection metadata for the MCP server, including its communication + protocol. GoHighLevelCalendarAvailabilityTool: title: GoHighLevelCalendarAvailabilityTool + description: >- + A reusable tool that checks calendar availability in a connected + GoHighLevel account. GoHighLevelCalendarEventCreateTool: title: GoHighLevelCalendarEventCreateTool + description: >- + A reusable tool that adds calendar events to a connected GoHighLevel + account. GoHighLevelContactCreateTool: title: GoHighLevelContactCreateTool + description: >- + A reusable tool that adds contacts to a connected GoHighLevel account. GoHighLevelContactGetTool: title: GoHighLevelContactGetTool + description: >- + A reusable tool that retrieves contacts from a connected GoHighLevel + account. + UpdateApiRequestToolDTO: + description: >- + Fields used to update an API-request tool, including its URL, HTTP + method, authentication, request data, retries, and response handling. + properties: + method: + description: The HTTP method used for the API request. UpdateDtmfToolDTO: title: UpdateDtmfToolDTO + description: >- + Fields used to update a DTMF tool, including its spoken messages, + rejection plan, and SIP INFO behavior. UpdateEndCallToolDTO: title: UpdateEndCallToolDTO + description: >- + Fields used to update an end-call tool, including its spoken messages + and rejection plan. UpdateFunctionToolDTO: title: UpdateFunctionToolDTO + description: >- + Fields used to update a custom function tool, including its function + definition, server, parameters, messages, and execution behavior. + UpdateHandoffToolDTO: + description: >- + Fields used to update a handoff tool, including its destinations, + function definition, default result, messages, and rejection plan. UpdateGhlToolDTO: title: UpdateGhlToolDTO UpdateMakeToolDTO: title: UpdateMakeToolDTO UpdateTransferCallToolDTO: title: UpdateTransferCallToolDTO + description: >- + Fields used to update a call-transfer tool, including its destinations, + spoken messages, and rejection plan. + UpdateSipRequestToolDTO: + description: >- + Fields used to update a SIP-request tool, including its method, headers, + body, spoken messages, and rejection plan. + UpdateVoicemailToolDTO: + description: >- + Fields used to update a voicemail-detection tool, including beep + detection, spoken messages, and rejection plan. UpdateOutputToolDTO: title: UpdateOutputToolDTO UpdateBashToolDTO: title: UpdateBashToolDTO + description: >- + Fields used to update a Bash tool, including its name, environment + subtype, server, messages, and rejection plan. UpdateComputerToolDTO: title: UpdateComputerToolDTO + description: >- + Fields used to update a computer tool, including its display settings, + environment subtype, server, messages, and rejection plan. UpdateTextEditorToolDTO: title: UpdateTextEditorToolDTO + description: >- + Fields used to update a text-editor tool, including its name, + environment subtype, server, messages, and rejection plan. UpdateQueryToolDTO: title: UpdateQueryToolDTO + description: >- + Fields used to update a query tool, including its knowledge bases, + spoken messages, and rejection plan. UpdateGoogleCalendarCreateEventToolDTO: title: UpdateGoogleCalendarCreateEventToolDTO + description: >- + Fields used to update a Google Calendar event-creation tool, including + its spoken messages and rejection plan. UpdateGoogleSheetsRowAppendToolDTO: title: UpdateGoogleSheetsRowAppendToolDTO + description: >- + Fields used to update a Google Sheets row-append tool, including its + spoken messages and rejection plan. UpdateGoogleCalendarCheckAvailabilityToolDTO: title: UpdateGoogleCalendarCheckAvailabilityToolDTO + description: >- + Fields used to update a Google Calendar availability tool, including + its spoken messages and rejection plan. UpdateSlackSendMessageToolDTO: title: UpdateSlackSendMessageToolDTO + description: >- + Fields used to update a Slack message tool, including its spoken + messages and rejection plan. UpdateSmsToolDTO: title: UpdateSmsToolDTO + description: >- + Fields used to update an SMS tool, including its spoken messages and + rejection plan. UpdateMcpToolDTO: title: UpdateMcpToolDTO + description: >- + Fields used to update an MCP tool, including its server, connection + metadata, exposed tool messages, and rejection plan. + properties: + metadata: + description: >- + Connection metadata for the MCP server, including its communication + protocol. UpdateGoHighLevelCalendarAvailabilityToolDTO: title: UpdateGoHighLevelCalendarAvailabilityToolDTO + description: >- + Fields used to update a GoHighLevel calendar-availability tool, + including its spoken messages and rejection plan. UpdateGoHighLevelCalendarEventCreateToolDTO: title: UpdateGoHighLevelCalendarEventCreateToolDTO + description: >- + Fields used to update a GoHighLevel calendar-event tool, including its + spoken messages and rejection plan. UpdateGoHighLevelContactCreateToolDTO: title: UpdateGoHighLevelContactCreateToolDTO + description: >- + Fields used to update a GoHighLevel contact-creation tool, including its + spoken messages and rejection plan. UpdateGoHighLevelContactGetToolDTO: title: UpdateGoHighLevelContactGetToolDTO + description: >- + Fields used to update a GoHighLevel contact-retrieval tool, including + its spoken messages and rejection plan. CreateTrieveKnowledgeBaseDTO: title: CreateTrieveKnowledgeBaseDTO TrieveKnowledgeBase: @@ -1566,6 +4436,12 @@ components: UpdateTestSuiteTestChatDto: title: UpdateTestSuiteTestChatDto securitySchemes: + bearer: + description: >- + Authenticate server-side requests with a private Vapi API key. Create or + copy a key from the [Vapi Dashboard](https://dashboard.vapi.ai) and send + it in the `Authorization` header as `Bearer `. Keep private API + keys out of client-side code and public repositories. BearerAuth: type: http scheme: bearer diff --git a/fern/apis/api/openapi-parameter-descriptions-overlay.yml b/fern/apis/api/openapi-parameter-descriptions-overlay.yml new file mode 100644 index 000000000..cfdad8bf1 --- /dev/null +++ b/fern/apis/api/openapi-parameter-descriptions-overlay.yml @@ -0,0 +1,123 @@ +overlay: 1.0.0 +info: + title: Document API parameters + version: 1.0.0 +actions: + # Path parameters + - target: $.paths['/assistant/{id}'].*.parameters[?(@.name == 'id' && @.in == 'path')] + update: + description: The unique identifier of the assistant. + - target: $.paths['/squad/{id}'].*.parameters[?(@.name == 'id' && @.in == 'path')] + update: + description: The unique identifier of the squad. + - target: $.paths['/call/{id}'].*.parameters[?(@.name == 'id' && @.in == 'path')] + update: + description: The unique identifier of the call. + - target: $.paths['/campaign/{id}'].*.parameters[?(@.name == 'id' && @.in == 'path')] + update: + description: The unique identifier of the campaign. + - target: $.paths['/phone-number/{id}'].*.parameters[?(@.name == 'id' && @.in == 'path')] + update: + description: The unique identifier of the phone number. + - target: $.paths['/tool/{id}'].*.parameters[?(@.name == 'id' && @.in == 'path')] + update: + description: The unique identifier of the tool. + - target: $.paths['/file/{id}'].*.parameters[?(@.name == 'id' && @.in == 'path')] + update: + description: The unique identifier of the file. + - target: $.paths['/structured-output/{id}'].*.parameters[?(@.name == 'id' && @.in == 'path')] + update: + description: The unique identifier of the structured output. + - target: $.paths['/reporting/insight/{id}'].*.parameters[?(@.name == 'id' && @.in == 'path')] + update: + description: The unique identifier of the reporting insight. + - target: $.paths['/reporting/insight/{id}/run'].post.parameters[?(@.name == 'id' && @.in == 'path')] + update: + description: The unique identifier of the reporting insight. + - target: $.paths['/eval/{id}'].*.parameters[?(@.name == 'id' && @.in == 'path')] + update: + description: The unique identifier of the eval definition. + - target: $.paths['/eval/run/{id}'].*.parameters[?(@.name == 'id' && @.in == 'path')] + update: + description: The unique identifier of the eval run. + - target: $.paths['/observability/scorecard/{id}'].*.parameters[?(@.name == 'id' && @.in == 'path')] + update: + description: The unique identifier of the scorecard. + - target: $.paths['/provider/{provider}/{resourceName}/{id}'].*.parameters[?(@.name == 'id' && @.in == 'path')] + update: + description: The unique identifier of the provider resource. + + # Query parameters + - target: $.paths['/campaign'].get.parameters[?(@.name == 'id' && @.in == 'query')] + update: + description: Filters campaigns by ID. + - target: $.paths['/campaign'].get.parameters[?(@.name == 'status' && @.in == 'query')] + update: + description: Filters campaigns by status. + - target: $.paths['/structured-output/{id}'].patch.parameters[?(@.name == 'schemaOverride' && @.in == 'query')] + update: + description: Set to the string `true` to allow changing the schema's top-level type. Other values do not enable schema type changes. + - target: $.paths['/reporting/insight'].get.parameters[?(@.name == 'id' && @.in == 'query')] + update: + description: Filters reporting insights by ID. + - target: $.paths['/eval'].get.parameters[?(@.name == 'id' && @.in == 'query')] + update: + description: Filters eval definitions by ID. + - target: $.paths['/eval/run'].get.parameters[?(@.name == 'id' && @.in == 'query')] + update: + description: Filters eval runs by ID. + - target: $.paths['/observability/scorecard'].get.parameters[?(@.name == 'id' && @.in == 'query')] + update: + description: Filters scorecards by ID. + - target: $.paths['/provider/{provider}/{resourceName}'].get.parameters[?(@.name == 'id' && @.in == 'query')] + update: + description: Filters provider resources by their resource ID. + - target: $.paths['/provider/{provider}/{resourceName}'].get.parameters[?(@.name == 'resourceId' && @.in == 'query')] + update: + description: Filters provider resources by their provider-specific resource ID. + + # Simulations (staged — /eval/simulation/* not yet in openapi.json; these targets no-op until synced) + # Path parameters + - target: $.paths['/eval/simulation/personality/{id}'].*.parameters[?(@.name == 'id' && @.in == 'path')] + update: + description: The unique identifier of the personality. + - target: $.paths['/eval/simulation/scenario/{id}'].*.parameters[?(@.name == 'id' && @.in == 'path')] + update: + description: The unique identifier of the scenario. + - target: $.paths['/eval/simulation/{id}'].*.parameters[?(@.name == 'id' && @.in == 'path')] + update: + description: The unique identifier of the simulation. + - target: $.paths['/eval/simulation/suite/{id}'].*.parameters[?(@.name == 'id' && @.in == 'path')] + update: + description: The unique identifier of the simulation suite. + - target: $.paths['/eval/simulation/run/{id}'].*.parameters[?(@.name == 'id' && @.in == 'path')] + update: + description: The unique identifier of the simulation run. + - target: $.paths['/eval/simulation/run/{id}/item'].*.parameters[?(@.name == 'id' && @.in == 'path')] + update: + description: The unique identifier of the simulation run. + - target: $.paths['/eval/simulation/run/{id}/item/{itemId}'].*.parameters[?(@.name == 'id' && @.in == 'path')] + update: + description: The unique identifier of the simulation run. + - target: $.paths['/eval/simulation/run/{id}/item/{itemId}'].*.parameters[?(@.name == 'itemId' && @.in == 'path')] + update: + description: The unique identifier of the run item. + - target: $.paths['/eval/simulation/run/{id}/item/{itemId}/generate'].*.parameters[?(@.name == 'id' && @.in == 'path')] + update: + description: The unique identifier of the simulation run. + - target: $.paths['/eval/simulation/run/{id}/item/{itemId}/generate'].*.parameters[?(@.name == 'itemId' && @.in == 'path')] + update: + description: The unique identifier of the run item. + # Query parameters + - target: $.paths['/eval/simulation/run/{id}/item'].get.parameters[?(@.name == 'simulationId' && @.in == 'query')] + update: + description: Filters run items to a specific simulation. + - target: $.paths['/eval/simulation/run/{id}/item'].get.parameters[?(@.name == 'runId' && @.in == 'query')] + update: + description: Filters run items to a specific run. + - target: $.paths['/eval/simulation/run/{id}/item'].get.parameters[?(@.name == 'status' && @.in == 'query')] + update: + description: Filters run items by status. + - target: $.paths['/eval/simulation/run/{id}/item/{itemId}/generate'].post.parameters[?(@.name == 'force' && @.in == 'query')] + update: + description: Set to the string `true` to regenerate improvement suggestions even if they already exist. diff --git a/fern/apis/api/openapi.json b/fern/apis/api/openapi.json index 0ac803577..99dcf506e 100644 --- a/fern/apis/api/openapi.json +++ b/fern/apis/api/openapi.json @@ -1,17 +1,17 @@ { "openapi": "3.0.0", "paths": { - "/call": { + "/assistant": { "post": { - "operationId": "CallController_create", - "summary": "Create Call", + "operationId": "AssistantController_create", + "summary": "Create Assistant", "parameters": [], "requestBody": { "required": true, "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateCallDTO" + "$ref": "#/components/schemas/CreateAssistantDTO" } } } @@ -22,21 +22,14 @@ "content": { "application/json": { "schema": { - "oneOf": [ - { - "$ref": "#/components/schemas/Call" - }, - { - "$ref": "#/components/schemas/CallBatchResponse" - } - ] + "$ref": "#/components/schemas/Assistant" } } } } }, "tags": [ - "Calls" + "Assistants" ], "security": [ { @@ -45,36 +38,9 @@ ] }, "get": { - "operationId": "CallController_findAll", - "summary": "List Calls", + "operationId": "AssistantController_findAll", + "summary": "List Assistants", "parameters": [ - { - "name": "id", - "required": false, - "in": "query", - "description": "This is the unique identifier for the call.", - "schema": { - "type": "string" - } - }, - { - "name": "assistantId", - "required": false, - "in": "query", - "description": "This will return calls with the specified assistantId.", - "schema": { - "type": "string" - } - }, - { - "name": "phoneNumberId", - "required": false, - "in": "query", - "description": "This is the phone number that will be used for the call. To use a transient number, use `phoneNumber` instead.\n\nOnly relevant for `outboundPhoneCall` and `inboundPhoneCall` type.", - "schema": { - "type": "string" - } - }, { "name": "limit", "required": false, @@ -175,7 +141,7 @@ "schema": { "type": "array", "items": { - "$ref": "#/components/schemas/Call" + "$ref": "#/components/schemas/Assistant" } } } @@ -183,7 +149,7 @@ } }, "tags": [ - "Calls" + "Assistants" ], "security": [ { @@ -192,16 +158,18 @@ ] } }, - "/call/{id}": { + "/assistant/{id}": { "get": { - "operationId": "CallController_findOne", - "summary": "Get Call", + "operationId": "AssistantController_findOne", + "summary": "Get Assistant", "parameters": [ { "name": "id", "required": true, "in": "path", + "description": "The unique identifier for the resource.", "schema": { + "format": "uuid", "type": "string" } } @@ -212,14 +180,14 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Call" + "$ref": "#/components/schemas/Assistant" } } } } }, "tags": [ - "Calls" + "Assistants" ], "security": [ { @@ -228,14 +196,16 @@ ] }, "patch": { - "operationId": "CallController_update", - "summary": "Update Call", + "operationId": "AssistantController_update", + "summary": "Update Assistant", "parameters": [ { "name": "id", "required": true, "in": "path", + "description": "The unique identifier for the resource.", "schema": { + "format": "uuid", "type": "string" } } @@ -245,7 +215,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpdateCallDTO" + "$ref": "#/components/schemas/UpdateAssistantDTO" } } } @@ -256,14 +226,14 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Call" + "$ref": "#/components/schemas/Assistant" } } } } }, "tags": [ - "Calls" + "Assistants" ], "security": [ { @@ -272,14 +242,16 @@ ] }, "delete": { - "operationId": "CallController_deleteCallData", - "summary": "Delete Call Data", + "operationId": "AssistantController_remove", + "summary": "Delete Assistant", "parameters": [ { "name": "id", "required": true, "in": "path", + "description": "The unique identifier for the resource.", "schema": { + "format": "uuid", "type": "string" } } @@ -290,14 +262,24 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Call" + "$ref": "#/components/schemas/Assistant" + } + } + } + }, + "409": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AssistantPinnedConflictResponseDTO" } } } } }, "tags": [ - "Calls" + "Assistants" ], "security": [ { @@ -306,59 +288,57 @@ ] } }, - "/chat": { - "get": { - "operationId": "ChatController_listChats", - "summary": "List Chats", - "parameters": [ - { - "name": "assistantId", - "required": false, - "in": "query", - "description": "This is the unique identifier for the assistant that will be used for the chat.", - "schema": { - "type": "string" - } - }, - { - "name": "workflowId", - "required": false, - "in": "query", - "description": "This is the unique identifier for the workflow that will be used for the chat.", - "schema": { - "type": "string" + "/squad": { + "post": { + "operationId": "SquadController_create", + "summary": "Create Squad", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateSquadDTO" + } } - }, - { - "name": "sessionId", - "required": false, - "in": "query", - "description": "This is the unique identifier for the session that will be used for the chat.", - "schema": { - "type": "string" + } + }, + "responses": { + "201": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Squad" + } + } } - }, + } + }, + "tags": [ + "Squads" + ], + "security": [ { - "name": "page", - "required": false, - "in": "query", - "description": "This is the page number to return. Defaults to 1.", - "schema": { - "minimum": 1, - "type": "number" - } - }, + "bearer": [] + } + ] + }, + "get": { + "operationId": "SquadController_findAll", + "summary": "List Squads", + "parameters": [ { - "name": "sortOrder", + "name": "idAny", "required": false, "in": "query", - "description": "This is the sort order for pagination. Defaults to 'DESC'.", + "description": "Return only squads matching the provided ids", "schema": { - "enum": [ - "ASC", - "DESC" - ], - "type": "string" + "format": "uuid", + "type": "array", + "items": { + "type": "string" + } } }, { @@ -459,103 +439,101 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ChatPaginatedResponse" + "type": "array", + "items": { + "$ref": "#/components/schemas/Squad" + } } } } } }, "tags": [ - "Chats" + "Squads" ], "security": [ { "bearer": [] } ] - }, - "post": { - "operationId": "ChatController_createChat", - "summary": "Create Chat", - "description": "Creates a new chat. Requires at least one of: assistantId/assistant, sessionId, or previousChatId. Note: sessionId and previousChatId are mutually exclusive.", - "parameters": [], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateChatDTO" - } + } + }, + "/squad/{id}": { + "get": { + "operationId": "SquadController_findOne", + "summary": "Get Squad", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "description": "The unique identifier for the resource.", + "schema": { + "format": "uuid", + "type": "string" } } - }, + ], "responses": { "200": { - "description": "Chat response - either non-streaming chat or streaming", - "content": { - "application/json": { - "schema": { - "oneOf": [ - { - "$ref": "#/components/schemas/Chat" - }, - { - "$ref": "#/components/schemas/CreateChatStreamResponse" - } - ] - } - } - } - }, - "201": { "description": "", "content": { "application/json": { "schema": { - "type": "object" + "$ref": "#/components/schemas/Squad" } } } } }, "tags": [ - "Chats" + "Squads" ], "security": [ { "bearer": [] } ] - } - }, - "/chat/{id}": { - "get": { - "operationId": "ChatController_getChat", - "summary": "Get Chat", + }, + "patch": { + "operationId": "SquadController_update", + "summary": "Update Squad", "parameters": [ { "name": "id", "required": true, "in": "path", + "description": "The unique identifier for the resource.", "schema": { + "format": "uuid", "type": "string" } } ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateSquadDTO" + } + } + } + }, "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Chat" + "$ref": "#/components/schemas/Squad" } } } } }, "tags": [ - "Chats" + "Squads" ], "security": [ { @@ -564,14 +542,16 @@ ] }, "delete": { - "operationId": "ChatController_deleteChat", - "summary": "Delete Chat", + "operationId": "SquadController_remove", + "summary": "Delete Squad", "parameters": [ { "name": "id", "required": true, "in": "path", + "description": "The unique identifier for the resource.", "schema": { + "format": "uuid", "type": "string" } } @@ -582,14 +562,14 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Chat" + "$ref": "#/components/schemas/Squad" } } } } }, "tags": [ - "Chats" + "Squads" ], "security": [ { @@ -598,98 +578,48 @@ ] } }, - "/chat/responses": { + "/call": { "post": { - "operationId": "ChatController_createOpenAIChat", - "summary": "Create Chat (OpenAI Compatible)", + "operationId": "CallController_create", + "summary": "Create Call", "parameters": [], "requestBody": { "required": true, "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/OpenAIResponsesRequest" + "$ref": "#/components/schemas/CreateCallDTO" } } } }, "responses": { - "200": { - "description": "OpenAI Responses API format - either non-streaming or streaming", + "201": { + "description": "", "content": { "application/json": { "schema": { "oneOf": [ { - "$ref": "#/components/schemas/ResponseObject" - }, - { - "$ref": "#/components/schemas/ResponseTextDeltaEvent" - }, - { - "$ref": "#/components/schemas/ResponseTextDoneEvent" - }, - { - "$ref": "#/components/schemas/ResponseCompletedEvent" + "$ref": "#/components/schemas/Call" }, { - "$ref": "#/components/schemas/ResponseErrorEvent" + "$ref": "#/components/schemas/CallBatchResponse" } ] } } } }, - "201": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "object" - } - } - } - } - }, - "tags": [ - "Chats" - ], - "security": [ - { - "bearer": [] - } - ] - } - }, - "/campaign": { - "post": { - "operationId": "CampaignController_create", - "summary": "Create Campaign", - "parameters": [], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateCampaignDTO" - } - } - } - }, - "responses": { - "201": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Campaign" - } - } - } + "400": { + "description": "Client/policy failure (limits, validation, missing resources)" + }, + "500": { + "description": "System failure (database, queue, or internal infra)" } }, "tags": [ - "Campaigns" + "Calls" ], "security": [ { @@ -698,50 +628,33 @@ ] }, "get": { - "operationId": "CampaignController_findAll", - "summary": "List Campaigns", + "operationId": "CallController_findAll", + "summary": "List Calls", "parameters": [ { "name": "id", "required": false, "in": "query", + "description": "This is the unique identifier for the call.", "schema": { "type": "string" } }, { - "name": "status", + "name": "assistantId", "required": false, "in": "query", + "description": "This will return calls with the specified assistantId.", "schema": { - "enum": [ - "scheduled", - "in-progress", - "ended" - ], "type": "string" } }, { - "name": "page", - "required": false, - "in": "query", - "description": "This is the page number to return. Defaults to 1.", - "schema": { - "minimum": 1, - "type": "number" - } - }, - { - "name": "sortOrder", + "name": "phoneNumberId", "required": false, "in": "query", - "description": "This is the sort order for pagination. Defaults to 'DESC'.", + "description": "This is the phone number that will be used for the call. To use a transient number, use `phoneNumber` instead.\n\nOnly relevant for `outboundPhoneCall` and `inboundPhoneCall` type.", "schema": { - "enum": [ - "ASC", - "DESC" - ], "type": "string" } }, @@ -843,14 +756,17 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CampaignPaginatedResponse" + "type": "array", + "items": { + "$ref": "#/components/schemas/Call" + } } } } } }, "tags": [ - "Campaigns" + "Calls" ], "security": [ { @@ -859,16 +775,18 @@ ] } }, - "/campaign/{id}": { + "/call/{id}": { "get": { - "operationId": "CampaignController_findOne", - "summary": "Get Campaign", + "operationId": "CallController_findOne", + "summary": "Get Call", "parameters": [ { "name": "id", "required": true, "in": "path", + "description": "The unique identifier for the resource.", "schema": { + "format": "uuid", "type": "string" } } @@ -879,14 +797,14 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Campaign" + "$ref": "#/components/schemas/Call" } } } } }, "tags": [ - "Campaigns" + "Calls" ], "security": [ { @@ -895,14 +813,16 @@ ] }, "patch": { - "operationId": "CampaignController_update", - "summary": "Update Campaign", + "operationId": "CallController_update", + "summary": "Update Call", "parameters": [ { "name": "id", "required": true, "in": "path", + "description": "The unique identifier for the resource.", "schema": { + "format": "uuid", "type": "string" } } @@ -912,7 +832,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpdateCampaignDTO" + "$ref": "#/components/schemas/UpdateCallDTO" } } } @@ -923,14 +843,14 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Campaign" + "$ref": "#/components/schemas/Call" } } } } }, "tags": [ - "Campaigns" + "Calls" ], "security": [ { @@ -939,32 +859,36 @@ ] }, "delete": { - "operationId": "CampaignController_remove", - "summary": "Delete Campaign", - "parameters": [ - { - "name": "id", - "required": true, - "in": "path", - "schema": { - "type": "string" + "operationId": "CallController_deleteCallData", + "summary": "Delete Call", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeleteCallDTO" + } } } - ], + }, "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Campaign" + "$ref": "#/components/schemas/Call" } } } + }, + "503": { + "description": "Failed to erase call recordings; the call was not deleted. Retry the request." } }, "tags": [ - "Campaigns" + "Calls" ], "security": [ { @@ -973,69 +897,351 @@ ] } }, - "/session": { - "post": { - "operationId": "SessionController_create", - "summary": "Create Session", - "parameters": [], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateSessionDTO" - } + "/call/{id}/mono-recording": { + "get": { + "operationId": "CallArtifactController_monoRecordingDownload", + "summary": "Download Call Mono Recording", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "description": "Call ID", + "schema": { + "format": "uuid", + "type": "string" } } - }, + ], "responses": { - "201": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Session" - } - } - } + "200": { + "description": "" + }, + "302": { + "description": "Redirect to a short-lived presigned URL for the recording." + }, + "401": { + "description": "Unauthorized — missing or invalid API token." + }, + "404": { + "description": "Artifact not found." } }, "tags": [ - "Sessions" + "Calls" ], "security": [ { "bearer": [] } ] - }, + } + }, + "/call/{id}/stereo-recording": { "get": { - "operationId": "SessionController_findAllPaginated", - "summary": "List Sessions", + "operationId": "CallArtifactController_stereoRecordingDownload", + "summary": "Download Call Stereo Recording", "parameters": [ { - "name": "name", - "required": false, - "in": "query", - "description": "This is the name of the session to filter by.", + "name": "id", + "required": true, + "in": "path", + "description": "Call ID", "schema": { + "format": "uuid", "type": "string" } + } + ], + "responses": { + "200": { + "description": "" }, + "302": { + "description": "Redirect to a short-lived presigned URL for the recording." + }, + "401": { + "description": "Unauthorized — missing or invalid API token." + }, + "404": { + "description": "Artifact not found." + } + }, + "tags": [ + "Calls" + ], + "security": [ { - "name": "assistantId", - "required": false, - "in": "query", - "description": "This is the ID of the assistant to filter sessions by.", + "bearer": [] + } + ] + } + }, + "/call/{id}/video-recording": { + "get": { + "operationId": "CallArtifactController_videoRecordingDownload", + "summary": "Download Call Video Recording", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "description": "Call ID", "schema": { + "format": "uuid", "type": "string" } - }, - { - "name": "workflowId", + } + ], + "responses": { + "200": { + "description": "" + }, + "302": { + "description": "Redirect to a short-lived presigned URL for the video." + }, + "401": { + "description": "Unauthorized — missing or invalid API token." + }, + "404": { + "description": "Artifact not found." + } + }, + "tags": [ + "Calls" + ], + "security": [ + { + "bearer": [] + } + ] + } + }, + "/call/{id}/customer-recording": { + "get": { + "operationId": "CallArtifactController_customerRecordingDownload", + "summary": "Download Call Customer Recording", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "description": "Call ID", + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "" + }, + "302": { + "description": "Redirect to a short-lived presigned URL for the recording." + }, + "401": { + "description": "Unauthorized — missing or invalid API token." + }, + "404": { + "description": "Artifact not found." + } + }, + "tags": [ + "Calls" + ], + "security": [ + { + "bearer": [] + } + ] + } + }, + "/call/{id}/assistant-recording": { + "get": { + "operationId": "CallArtifactController_assistantRecordingDownload", + "summary": "Download Call Assistant Recording", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "description": "Call ID", + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "" + }, + "302": { + "description": "Redirect to a short-lived presigned URL for the recording." + }, + "401": { + "description": "Unauthorized — missing or invalid API token." + }, + "404": { + "description": "Artifact not found." + } + }, + "tags": [ + "Calls" + ], + "security": [ + { + "bearer": [] + } + ] + } + }, + "/call/{id}/pcap": { + "get": { + "operationId": "CallArtifactController_pcapDownload", + "summary": "Download Call Packet Capture (pcap)", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "description": "Call ID", + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "" + }, + "302": { + "description": "Redirect to a short-lived presigned URL for the pcap file." + }, + "401": { + "description": "Unauthorized — missing or invalid API token." + }, + "404": { + "description": "Artifact not found." + } + }, + "tags": [ + "Calls" + ], + "security": [ + { + "bearer": [] + } + ] + } + }, + "/call/{id}/call-logs": { + "get": { + "operationId": "CallArtifactController_callLogsDownload", + "summary": "Download Call Logs", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "description": "Call ID", + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "" + }, + "302": { + "description": "Redirect to a short-lived presigned URL for the log file." + }, + "401": { + "description": "Unauthorized — missing or invalid API token." + }, + "404": { + "description": "Artifact not found." + } + }, + "tags": [ + "Calls" + ], + "security": [ + { + "bearer": [] + } + ] + } + }, + "/chat": { + "get": { + "operationId": "ChatController_listChats", + "summary": "List Chats", + "parameters": [ + { + "name": "id", "required": false, "in": "query", - "description": "This is the ID of the workflow to filter sessions by.", + "description": "This is the unique identifier for the chat to filter by.", + "schema": { + "type": "string" + } + }, + { + "name": "assistantId", + "required": false, + "in": "query", + "description": "This is the unique identifier for the assistant that will be used for the chat.", + "schema": { + "type": "string" + } + }, + { + "name": "assistantIdAny", + "required": false, + "in": "query", + "description": "Filter by multiple assistant IDs. Provide as comma-separated values.", + "schema": { + "example": "assistant-1,assistant-2,assistant-3", + "type": "string" + } + }, + { + "name": "squadId", + "required": false, + "in": "query", + "description": "This is the unique identifier for the squad that will be used for the chat.", + "schema": { + "type": "string" + } + }, + { + "name": "sessionId", + "required": false, + "in": "query", + "description": "This is the unique identifier for the session that will be used for the chat.", + "schema": { + "type": "string" + } + }, + { + "name": "previousChatId", + "required": false, + "in": "query", + "description": "This is the unique identifier for the previous chat to filter by.", + "schema": { + "type": "string" + } + }, + { + "name": "idAny", + "required": false, + "in": "query", + "description": "Filter by multiple chat IDs. Provide as comma-separated values.", "schema": { "type": "string" } @@ -1063,6 +1269,20 @@ "type": "string" } }, + { + "name": "sortBy", + "required": false, + "in": "query", + "description": "This is the column to sort by. Defaults to 'createdAt'.", + "schema": { + "enum": [ + "createdAt", + "duration", + "cost" + ], + "type": "string" + } + }, { "name": "limit", "required": false, @@ -1161,14 +1381,67 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/SessionPaginatedResponse" + "$ref": "#/components/schemas/ChatPaginatedResponse" } } } } }, "tags": [ - "Sessions" + "Chats" + ], + "security": [ + { + "bearer": [] + } + ] + }, + "post": { + "operationId": "ChatController_createChat", + "summary": "Create Chat", + "description": "Creates a new chat with optional SMS delivery via transport field. Requires at least one of: assistantId/assistant, sessionId, or previousChatId. Note: sessionId and previousChatId are mutually exclusive. Transport field enables SMS delivery with two modes: (1) New conversation - provide transport.phoneNumberId and transport.customer to create a new session, (2) Existing conversation - provide sessionId to use existing session data. Cannot specify both sessionId and transport fields together. The transport.useLLMGeneratedMessageForOutbound flag controls whether input is processed by LLM (true, default) or forwarded directly as SMS (false).", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateChatDTO" + } + } + } + }, + "responses": { + "200": { + "description": "Chat response - either non-streaming chat or streaming", + "content": { + "application/json": { + "schema": { + "oneOf": [ + { + "$ref": "#/components/schemas/Chat" + }, + { + "$ref": "#/components/schemas/CreateChatStreamResponse" + } + ] + } + } + } + }, + "201": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object" + } + } + } + } + }, + "tags": [ + "Chats" ], "security": [ { @@ -1177,10 +1450,10 @@ ] } }, - "/session/{id}": { + "/chat/{id}": { "get": { - "operationId": "SessionController_findOne", - "summary": "Get Session", + "operationId": "ChatController_getChat", + "summary": "Get Chat", "parameters": [ { "name": "id", @@ -1197,14 +1470,14 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Session" + "$ref": "#/components/schemas/Chat" } } } } }, "tags": [ - "Sessions" + "Chats" ], "security": [ { @@ -1212,9 +1485,9 @@ } ] }, - "patch": { - "operationId": "SessionController_update", - "summary": "Update Session", + "delete": { + "operationId": "ChatController_deleteChat", + "summary": "Delete Chat", "parameters": [ { "name": "id", @@ -1225,64 +1498,83 @@ } } ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateSessionDTO" - } - } - } - }, "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Session" + "$ref": "#/components/schemas/Chat" } } } } }, "tags": [ - "Sessions" + "Chats" ], "security": [ { "bearer": [] } ] - }, - "delete": { - "operationId": "SessionController_remove", - "summary": "Delete Session", - "parameters": [ - { - "name": "id", - "required": true, - "in": "path", - "schema": { - "type": "string" + } + }, + "/chat/responses": { + "post": { + "operationId": "ChatController_createOpenAIChat", + "summary": "Create Chat (OpenAI Compatible)", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OpenAIResponsesRequest" + } } } - ], + }, "responses": { "200": { + "description": "OpenAI Responses API format - either non-streaming or streaming", + "content": { + "application/json": { + "schema": { + "oneOf": [ + { + "$ref": "#/components/schemas/ResponseObject" + }, + { + "$ref": "#/components/schemas/ResponseTextDeltaEvent" + }, + { + "$ref": "#/components/schemas/ResponseTextDoneEvent" + }, + { + "$ref": "#/components/schemas/ResponseCompletedEvent" + }, + { + "$ref": "#/components/schemas/ResponseErrorEvent" + } + ] + } + } + } + }, + "201": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Session" + "type": "object" } } } } }, "tags": [ - "Sessions" + "Chats" ], "security": [ { @@ -1291,17 +1583,17 @@ ] } }, - "/assistant": { + "/campaign": { "post": { - "operationId": "AssistantController_create", - "summary": "Create Assistant", + "operationId": "CampaignController_create", + "summary": "Create Campaign", "parameters": [], "requestBody": { "required": true, "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateAssistantDTO" + "$ref": "#/components/schemas/CreateCampaignDTO" } } } @@ -1312,14 +1604,14 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Assistant" + "$ref": "#/components/schemas/Campaign" } } } } }, "tags": [ - "Assistants" + "Campaigns" ], "security": [ { @@ -1328,9 +1620,69 @@ ] }, "get": { - "operationId": "AssistantController_findAll", - "summary": "List Assistants", + "operationId": "CampaignController_findAll", + "summary": "List Campaigns", "parameters": [ + { + "name": "id", + "required": false, + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "status", + "required": false, + "in": "query", + "schema": { + "enum": [ + "scheduled", + "in-progress", + "ended", + "cancelled", + "archived" + ], + "type": "string" + } + }, + { + "name": "page", + "required": false, + "in": "query", + "description": "This is the page number to return. Defaults to 1.", + "schema": { + "minimum": 1, + "type": "number" + } + }, + { + "name": "sortOrder", + "required": false, + "in": "query", + "description": "This is the sort order for pagination. Defaults to 'DESC'.", + "schema": { + "enum": [ + "ASC", + "DESC" + ], + "type": "string" + } + }, + { + "name": "sortBy", + "required": false, + "in": "query", + "description": "This is the column to sort by. Defaults to 'createdAt'.", + "schema": { + "enum": [ + "createdAt", + "duration", + "cost" + ], + "type": "string" + } + }, { "name": "limit", "required": false, @@ -1429,17 +1781,14 @@ "content": { "application/json": { "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Assistant" - } + "$ref": "#/components/schemas/CampaignPaginatedResponse" } } } } }, "tags": [ - "Assistants" + "Campaigns" ], "security": [ { @@ -1448,78 +1797,35 @@ ] } }, - "/assistant/{id}": { - "get": { - "operationId": "AssistantController_findOne", - "summary": "Get Assistant", - "parameters": [ - { - "name": "id", - "required": true, - "in": "path", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Assistant" - } - } - } - } - }, - "tags": [ - "Assistants" - ], - "security": [ - { - "bearer": [] - } - ] - }, - "patch": { - "operationId": "AssistantController_update", - "summary": "Update Assistant", - "parameters": [ - { - "name": "id", - "required": true, - "in": "path", - "schema": { - "type": "string" - } - } - ], + "/v2/campaign": { + "post": { + "operationId": "CampaignController_createV2", + "summary": "Create Campaign V2", + "parameters": [], "requestBody": { "required": true, "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpdateAssistantDTO" + "$ref": "#/components/schemas/CreateCampaignDTO" } } } }, "responses": { - "200": { + "201": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Assistant" + "$ref": "#/components/schemas/Campaign" } } } } }, "tags": [ - "Assistants" + "Campaigns" ], "security": [ { @@ -1527,144 +1833,79 @@ } ] }, - "delete": { - "operationId": "AssistantController_remove", - "summary": "Delete Assistant", + "get": { + "operationId": "CampaignController_findAllV2", + "summary": "List Campaigns V2", "parameters": [ { "name": "id", - "required": true, - "in": "path", + "required": false, + "in": "query", "schema": { "type": "string" } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Assistant" - } - } - } - } - }, - "tags": [ - "Assistants" - ], - "security": [ + }, { - "bearer": [] - } - ] - } - }, - "/phone-number": { - "post": { - "operationId": "PhoneNumberController_create", - "summary": "Create Phone Number", - "parameters": [], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "oneOf": [ - { - "$ref": "#/components/schemas/CreateByoPhoneNumberDTO", - "title": "ByoPhoneNumber" - }, - { - "$ref": "#/components/schemas/CreateTwilioPhoneNumberDTO", - "title": "TwilioPhoneNumber" - }, - { - "$ref": "#/components/schemas/CreateVonagePhoneNumberDTO", - "title": "VonagePhoneNumber" - }, - { - "$ref": "#/components/schemas/CreateVapiPhoneNumberDTO", - "title": "VapiPhoneNumber" - }, - { - "$ref": "#/components/schemas/CreateTelnyxPhoneNumberDTO", - "title": "TelnyxPhoneNumber" - } - ], - "discriminator": { - "propertyName": "provider", - "mapping": { - "byo-phone-number": "#/components/schemas/CreateByoPhoneNumberDTO", - "twilio": "#/components/schemas/CreateTwilioPhoneNumberDTO", - "vonage": "#/components/schemas/CreateVonagePhoneNumberDTO", - "vapi": "#/components/schemas/CreateVapiPhoneNumberDTO", - "telnyx": "#/components/schemas/CreateTelnyxPhoneNumberDTO" - } - } - } + "name": "status", + "required": false, + "in": "query", + "schema": { + "enum": [ + "scheduled", + "in-progress", + "ended", + "cancelled", + "archived" + ], + "type": "string" } - } - }, - "responses": { - "201": { - "description": "", - "content": { - "application/json": { - "schema": { - "title": "PhoneNumber", - "oneOf": [ - { - "$ref": "#/components/schemas/ByoPhoneNumber", - "title": "ByoPhoneNumber" - }, - { - "$ref": "#/components/schemas/TwilioPhoneNumber", - "title": "TwilioPhoneNumber" - }, - { - "$ref": "#/components/schemas/VonagePhoneNumber", - "title": "VonagePhoneNumber" - }, - { - "$ref": "#/components/schemas/VapiPhoneNumber", - "title": "VapiPhoneNumber" - }, - { - "$ref": "#/components/schemas/TelnyxPhoneNumber", - "title": "TelnyxPhoneNumber" - } - ], - "discriminator": { - "propertyName": "provider", - "mapping": { - "byo-phone-number": "#/components/schemas/ByoPhoneNumber", - "twilio": "#/components/schemas/TwilioPhoneNumber", - "vonage": "#/components/schemas/VonagePhoneNumber", - "vapi": "#/components/schemas/VapiPhoneNumber", - "telnyx": "#/components/schemas/TelnyxPhoneNumber" - } - } - } - } + }, + { + "name": "includeCounters", + "required": false, + "in": "query", + "description": "When true, every campaign in the response includes `contactCounters` and\n`callMetrics`. These are aggregate queries over contacts and events —\nbatched across the page, so the cost is three queries per request rather\nthan three per campaign, but still opt-in rather than paid for on every\nread. Defaults to false.", + "schema": { + "type": "boolean" } - } - }, - "tags": [ - "Phone Numbers" - ], - "security": [ + }, { - "bearer": [] - } - ] - }, - "get": { - "operationId": "PhoneNumberController_findAll", - "summary": "List Phone Numbers", - "parameters": [ + "name": "page", + "required": false, + "in": "query", + "description": "This is the page number to return. Defaults to 1.", + "schema": { + "minimum": 1, + "type": "number" + } + }, + { + "name": "sortOrder", + "required": false, + "in": "query", + "description": "This is the sort order for pagination. Defaults to 'DESC'.", + "schema": { + "enum": [ + "ASC", + "DESC" + ], + "type": "string" + } + }, + { + "name": "sortBy", + "required": false, + "in": "query", + "description": "This is the column to sort by. Defaults to 'createdAt'.", + "schema": { + "enum": [ + "createdAt", + "duration", + "cost" + ], + "type": "string" + } + }, { "name": "limit", "required": false, @@ -1763,49 +2004,14 @@ "content": { "application/json": { "schema": { - "type": "array", - "items": { - "title": "PhoneNumber", - "oneOf": [ - { - "$ref": "#/components/schemas/ByoPhoneNumber", - "title": "ByoPhoneNumber" - }, - { - "$ref": "#/components/schemas/TwilioPhoneNumber", - "title": "TwilioPhoneNumber" - }, - { - "$ref": "#/components/schemas/VonagePhoneNumber", - "title": "VonagePhoneNumber" - }, - { - "$ref": "#/components/schemas/VapiPhoneNumber", - "title": "VapiPhoneNumber" - }, - { - "$ref": "#/components/schemas/TelnyxPhoneNumber", - "title": "TelnyxPhoneNumber" - } - ], - "discriminator": { - "propertyName": "provider", - "mapping": { - "byo-phone-number": "#/components/schemas/ByoPhoneNumber", - "twilio": "#/components/schemas/TwilioPhoneNumber", - "vonage": "#/components/schemas/VonagePhoneNumber", - "vapi": "#/components/schemas/VapiPhoneNumber", - "telnyx": "#/components/schemas/TelnyxPhoneNumber" - } - } - } + "$ref": "#/components/schemas/CampaignSummaryPaginatedResponse" } } } } }, "tags": [ - "Phone Numbers" + "Campaigns" ], "security": [ { @@ -1814,18 +2020,29 @@ ] } }, - "/phone-number/{id}": { + "/v2/campaign/{id}": { "get": { - "operationId": "PhoneNumberController_findOne", - "summary": "Get Phone Number", + "operationId": "CampaignController_findOneV2", + "summary": "Get Campaign V2", "parameters": [ { "name": "id", "required": true, "in": "path", + "description": "The unique identifier for the resource.", "schema": { + "format": "uuid", "type": "string" } + }, + { + "name": "includeCounters", + "required": false, + "in": "query", + "description": "When true, the response includes `contactCounters` and `callMetrics`.\nThese are aggregate queries over the campaign's contacts and events, so\nthey are opt-in rather than paid for on every read. Defaults to false.", + "schema": { + "type": "boolean" + } } ], "responses": { @@ -1834,46 +2051,14 @@ "content": { "application/json": { "schema": { - "title": "PhoneNumber", - "oneOf": [ - { - "$ref": "#/components/schemas/ByoPhoneNumber", - "title": "ByoPhoneNumber" - }, - { - "$ref": "#/components/schemas/TwilioPhoneNumber", - "title": "TwilioPhoneNumber" - }, - { - "$ref": "#/components/schemas/VonagePhoneNumber", - "title": "VonagePhoneNumber" - }, - { - "$ref": "#/components/schemas/VapiPhoneNumber", - "title": "VapiPhoneNumber" - }, - { - "$ref": "#/components/schemas/TelnyxPhoneNumber", - "title": "TelnyxPhoneNumber" - } - ], - "discriminator": { - "propertyName": "provider", - "mapping": { - "byo-phone-number": "#/components/schemas/ByoPhoneNumber", - "twilio": "#/components/schemas/TwilioPhoneNumber", - "vonage": "#/components/schemas/VonagePhoneNumber", - "vapi": "#/components/schemas/VapiPhoneNumber", - "telnyx": "#/components/schemas/TelnyxPhoneNumber" - } - } + "$ref": "#/components/schemas/CampaignSummary" } } } } }, "tags": [ - "Phone Numbers" + "Campaigns" ], "security": [ { @@ -1882,14 +2067,16 @@ ] }, "patch": { - "operationId": "PhoneNumberController_update", - "summary": "Update Phone Number", + "operationId": "CampaignController_updateV2", + "summary": "Update Campaign", "parameters": [ { "name": "id", "required": true, "in": "path", + "description": "The unique identifier for the resource.", "schema": { + "format": "uuid", "type": "string" } } @@ -1899,38 +2086,7 @@ "content": { "application/json": { "schema": { - "oneOf": [ - { - "$ref": "#/components/schemas/UpdateByoPhoneNumberDTO", - "title": "ByoPhoneNumber" - }, - { - "$ref": "#/components/schemas/UpdateTwilioPhoneNumberDTO", - "title": "TwilioPhoneNumber" - }, - { - "$ref": "#/components/schemas/UpdateVonagePhoneNumberDTO", - "title": "VonagePhoneNumber" - }, - { - "$ref": "#/components/schemas/UpdateVapiPhoneNumberDTO", - "title": "VapiPhoneNumber" - }, - { - "$ref": "#/components/schemas/UpdateTelnyxPhoneNumberDTO", - "title": "TelnyxPhoneNumber" - } - ], - "discriminator": { - "propertyName": "provider", - "mapping": { - "byo-phone-number": "#/components/schemas/UpdateByoPhoneNumberDTO", - "twilio": "#/components/schemas/UpdateTwilioPhoneNumberDTO", - "vonage": "#/components/schemas/UpdateVonagePhoneNumberDTO", - "vapi": "#/components/schemas/UpdateVapiPhoneNumberDTO", - "telnyx": "#/components/schemas/UpdateTelnyxPhoneNumberDTO" - } - } + "$ref": "#/components/schemas/UpdateCampaignDTO" } } } @@ -1941,46 +2097,14 @@ "content": { "application/json": { "schema": { - "title": "PhoneNumber", - "oneOf": [ - { - "$ref": "#/components/schemas/ByoPhoneNumber", - "title": "ByoPhoneNumber" - }, - { - "$ref": "#/components/schemas/TwilioPhoneNumber", - "title": "TwilioPhoneNumber" - }, - { - "$ref": "#/components/schemas/VonagePhoneNumber", - "title": "VonagePhoneNumber" - }, - { - "$ref": "#/components/schemas/VapiPhoneNumber", - "title": "VapiPhoneNumber" - }, - { - "$ref": "#/components/schemas/TelnyxPhoneNumber", - "title": "TelnyxPhoneNumber" - } - ], - "discriminator": { - "propertyName": "provider", - "mapping": { - "byo-phone-number": "#/components/schemas/ByoPhoneNumber", - "twilio": "#/components/schemas/TwilioPhoneNumber", - "vonage": "#/components/schemas/VonagePhoneNumber", - "vapi": "#/components/schemas/VapiPhoneNumber", - "telnyx": "#/components/schemas/TelnyxPhoneNumber" - } - } + "$ref": "#/components/schemas/Campaign" } } } } }, "tags": [ - "Phone Numbers" + "Campaigns" ], "security": [ { @@ -1989,14 +2113,16 @@ ] }, "delete": { - "operationId": "PhoneNumberController_remove", - "summary": "Delete Phone Number", + "operationId": "CampaignController_removeV2", + "summary": "Delete Campaign", "parameters": [ { "name": "id", "required": true, "in": "path", + "description": "The unique identifier for the resource.", "schema": { + "format": "uuid", "type": "string" } } @@ -2007,46 +2133,14 @@ "content": { "application/json": { "schema": { - "title": "PhoneNumber", - "oneOf": [ - { - "$ref": "#/components/schemas/ByoPhoneNumber", - "title": "ByoPhoneNumber" - }, - { - "$ref": "#/components/schemas/TwilioPhoneNumber", - "title": "TwilioPhoneNumber" - }, - { - "$ref": "#/components/schemas/VonagePhoneNumber", - "title": "VonagePhoneNumber" - }, - { - "$ref": "#/components/schemas/VapiPhoneNumber", - "title": "VapiPhoneNumber" - }, - { - "$ref": "#/components/schemas/TelnyxPhoneNumber", - "title": "TelnyxPhoneNumber" - } - ], - "discriminator": { - "propertyName": "provider", - "mapping": { - "byo-phone-number": "#/components/schemas/ByoPhoneNumber", - "twilio": "#/components/schemas/TwilioPhoneNumber", - "vonage": "#/components/schemas/VonagePhoneNumber", - "vapi": "#/components/schemas/VapiPhoneNumber", - "telnyx": "#/components/schemas/TelnyxPhoneNumber" - } - } + "$ref": "#/components/schemas/Campaign" } } } } }, "tags": [ - "Phone Numbers" + "Campaigns" ], "security": [ { @@ -2055,251 +2149,82 @@ ] } }, - "/tool": { - "post": { - "operationId": "ToolController_create", - "summary": "Create Tool", - "parameters": [], + "/campaign/{id}": { + "get": { + "operationId": "CampaignController_findOne", + "summary": "Get Campaign", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "description": "The unique identifier for the resource.", + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Campaign" + } + } + } + } + }, + "tags": [ + "Campaigns" + ], + "security": [ + { + "bearer": [] + } + ] + }, + "patch": { + "operationId": "CampaignController_update", + "summary": "Update Campaign", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "description": "The unique identifier for the resource.", + "schema": { + "format": "uuid", + "type": "string" + } + } + ], "requestBody": { "required": true, "content": { "application/json": { "schema": { - "oneOf": [ - { - "$ref": "#/components/schemas/CreateApiRequestToolDTO", - "title": "ApiRequestTool" - }, - { - "$ref": "#/components/schemas/CreateDtmfToolDTO", - "title": "DtmfTool" - }, - { - "$ref": "#/components/schemas/CreateEndCallToolDTO", - "title": "EndCallTool" - }, - { - "$ref": "#/components/schemas/CreateFunctionToolDTO", - "title": "FunctionTool" - }, - { - "$ref": "#/components/schemas/CreateTransferCallToolDTO", - "title": "TransferCallTool" - }, - { - "$ref": "#/components/schemas/CreateHandoffToolDTO", - "title": "HandoffTool" - }, - { - "$ref": "#/components/schemas/CreateBashToolDTO", - "title": "BashTool" - }, - { - "$ref": "#/components/schemas/CreateComputerToolDTO", - "title": "ComputerTool" - }, - { - "$ref": "#/components/schemas/CreateTextEditorToolDTO", - "title": "TextEditorTool" - }, - { - "$ref": "#/components/schemas/CreateQueryToolDTO", - "title": "QueryTool" - }, - { - "$ref": "#/components/schemas/CreateGoogleCalendarCreateEventToolDTO", - "title": "GoogleCalendarCreateEventTool" - }, - { - "$ref": "#/components/schemas/CreateGoogleSheetsRowAppendToolDTO", - "title": "GoogleSheetsRowAppendTool" - }, - { - "$ref": "#/components/schemas/CreateGoogleCalendarCheckAvailabilityToolDTO", - "title": "GoogleCalendarCheckAvailabilityTool" - }, - { - "$ref": "#/components/schemas/CreateSlackSendMessageToolDTO", - "title": "SlackSendMessageTool" - }, - { - "$ref": "#/components/schemas/CreateSmsToolDTO", - "title": "SmsSendTool" - }, - { - "$ref": "#/components/schemas/CreateMcpToolDTO", - "title": "McpTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelCalendarAvailabilityToolDTO", - "title": "GoHighLevelCalendarAvailabilityTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelCalendarEventCreateToolDTO", - "title": "GoHighLevelCalendarEventCreateTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelContactCreateToolDTO", - "title": "GoHighLevelContactCreateTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelContactGetToolDTO", - "title": "GoHighLevelContactGetTool" - } - ], - "discriminator": { - "propertyName": "type", - "mapping": { - "apiRequest": "#/components/schemas/CreateApiRequestToolDTO", - "dtmf": "#/components/schemas/CreateDtmfToolDTO", - "endCall": "#/components/schemas/CreateEndCallToolDTO", - "function": "#/components/schemas/CreateFunctionToolDTO", - "transferCall": "#/components/schemas/CreateTransferCallToolDTO", - "handoff": "#/components/schemas/CreateHandoffToolDTO", - "bash": "#/components/schemas/CreateBashToolDTO", - "computer": "#/components/schemas/CreateComputerToolDTO", - "textEditor": "#/components/schemas/CreateTextEditorToolDTO", - "query": "#/components/schemas/CreateQueryToolDTO", - "google.calendar.event.create": "#/components/schemas/CreateGoogleCalendarCreateEventToolDTO", - "google.sheets.row.append": "#/components/schemas/CreateGoogleSheetsRowAppendToolDTO", - "google.calendar.availability.check": "#/components/schemas/CreateGoogleCalendarCheckAvailabilityToolDTO", - "slack.message.send": "#/components/schemas/CreateSlackSendMessageToolDTO", - "sms": "#/components/schemas/CreateSmsToolDTO", - "mcp": "#/components/schemas/CreateMcpToolDTO", - "gohighlevel.calendar.availability.check": "#/components/schemas/CreateGoHighLevelCalendarAvailabilityToolDTO", - "gohighlevel.calendar.event.create": "#/components/schemas/CreateGoHighLevelCalendarEventCreateToolDTO", - "gohighlevel.contact.create": "#/components/schemas/CreateGoHighLevelContactCreateToolDTO", - "gohighlevel.contact.get": "#/components/schemas/CreateGoHighLevelContactGetToolDTO" - } - } + "$ref": "#/components/schemas/UpdateCampaignDTO" } } } }, "responses": { - "201": { + "200": { "description": "", "content": { "application/json": { "schema": { - "oneOf": [ - { - "$ref": "#/components/schemas/ApiRequestTool", - "title": "ApiRequestTool" - }, - { - "$ref": "#/components/schemas/DtmfTool", - "title": "DtmfTool" - }, - { - "$ref": "#/components/schemas/EndCallTool", - "title": "EndCallTool" - }, - { - "$ref": "#/components/schemas/FunctionTool", - "title": "FunctionTool" - }, - { - "$ref": "#/components/schemas/GhlTool", - "title": "GhlTool" - }, - { - "$ref": "#/components/schemas/TransferCallTool", - "title": "TransferCallTool" - }, - { - "$ref": "#/components/schemas/HandoffTool", - "title": "HandoffTool" - }, - { - "$ref": "#/components/schemas/BashTool", - "title": "BashTool" - }, - { - "$ref": "#/components/schemas/ComputerTool", - "title": "ComputerTool" - }, - { - "$ref": "#/components/schemas/TextEditorTool", - "title": "TextEditorTool" - }, - { - "$ref": "#/components/schemas/QueryTool", - "title": "QueryTool" - }, - { - "$ref": "#/components/schemas/GoogleCalendarCreateEventTool", - "title": "GoogleCalendarCreateEventTool" - }, - { - "$ref": "#/components/schemas/GoogleSheetsRowAppendTool", - "title": "GoogleSheetsRowAppendTool" - }, - { - "$ref": "#/components/schemas/GoogleCalendarCheckAvailabilityTool", - "title": "GoogleCalendarCheckAvailabilityTool" - }, - { - "$ref": "#/components/schemas/SlackSendMessageTool", - "title": "SlackSendMessageTool" - }, - { - "$ref": "#/components/schemas/SmsTool", - "title": "SmsSendTool" - }, - { - "$ref": "#/components/schemas/McpTool", - "title": "McpTool" - }, - { - "$ref": "#/components/schemas/GoHighLevelCalendarAvailabilityTool", - "title": "GoHighLevelCalendarAvailabilityTool" - }, - { - "$ref": "#/components/schemas/GoHighLevelCalendarEventCreateTool", - "title": "GoHighLevelCalendarEventCreateTool" - }, - { - "$ref": "#/components/schemas/GoHighLevelContactCreateTool", - "title": "GoHighLevelContactCreateTool" - }, - { - "$ref": "#/components/schemas/GoHighLevelContactGetTool", - "title": "GoHighLevelContactGetTool" - } - ], - "discriminator": { - "propertyName": "type", - "mapping": { - "apiRequest": "#/components/schemas/ApiRequestTool", - "dtmf": "#/components/schemas/DtmfTool", - "endCall": "#/components/schemas/EndCallTool", - "function": "#/components/schemas/FunctionTool", - "transferCall": "#/components/schemas/TransferCallTool", - "handoff": "#/components/schemas/HandoffTool", - "bash": "#/components/schemas/BashTool", - "computer": "#/components/schemas/ComputerTool", - "textEditor": "#/components/schemas/TextEditorTool", - "query": "#/components/schemas/QueryTool", - "google.calendar.event.create": "#/components/schemas/GoogleCalendarCreateEventTool", - "google.sheets.row.append": "#/components/schemas/GoogleSheetsRowAppendTool", - "google.calendar.availability.check": "#/components/schemas/GoogleCalendarCheckAvailabilityTool", - "slack.message.send": "#/components/schemas/SlackSendMessageTool", - "sms": "#/components/schemas/SmsTool", - "mcp": "#/components/schemas/McpTool", - "gohighlevel.calendar.availability.check": "#/components/schemas/GoHighLevelCalendarAvailabilityTool", - "gohighlevel.calendar.event.create": "#/components/schemas/GoHighLevelCalendarEventCreateTool", - "gohighlevel.contact.create": "#/components/schemas/GoHighLevelContactCreateTool", - "gohighlevel.contact.get": "#/components/schemas/GoHighLevelContactGetTool" - } - } + "$ref": "#/components/schemas/Campaign" } } } } }, "tags": [ - "Tools" + "Campaigns" ], "security": [ { @@ -2307,10 +2232,402 @@ } ] }, + "delete": { + "operationId": "CampaignController_remove", + "summary": "Delete Campaign", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "description": "The unique identifier for the resource.", + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Campaign" + } + } + } + } + }, + "tags": [ + "Campaigns" + ], + "security": [ + { + "bearer": [] + } + ] + } + }, + "/v2/campaign/{id}/contacts": { "get": { - "operationId": "ToolController_findAll", - "summary": "List Tools", + "operationId": "CampaignController_getCampaignV2Contacts", + "summary": "Get Campaign V2 Contacts", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "description": "The unique identifier for the resource.", + "schema": { + "format": "uuid", + "type": "string" + } + }, + { + "name": "status", + "required": false, + "in": "query", + "description": "This is the status to filter contacts by. Pass once or multiple times to\nfilter on any of the provided statuses.", + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "contact.pending", + "contact.dispatched", + "contact.completed", + "contact.failed", + "contact.skipped", + "contact.predial-failed" + ] + } + } + }, + { + "name": "limit", + "required": false, + "in": "query", + "description": "This is the maximum number of contacts to return. Defaults to 50.", + "schema": { + "minimum": 1, + "maximum": 1000, + "type": "number" + } + }, + { + "name": "sortBy", + "required": false, + "in": "query", + "description": "This is the column to sort by. Defaults to `position` — the order contacts\nwere uploaded, which is also dial order.\n\n`status` sorts by the enum's declaration order rather than alphabetically,\nwhich means it reads as a lifecycle: pending, dispatched, completed,\nfailed, skipped, predial-failed.\n\nOnly columns on `campaign_contact` are sortable. Call-level values such as\ncost or duration live on the call and are attached after this query, so\nsorting by them here would only reorder the current page.", + "schema": { + "enum": [ + "position", + "status" + ], + "type": "string" + } + }, + { + "name": "page", + "required": false, + "in": "query", + "description": "This is the page number to return. Defaults to 1.", + "schema": { + "minimum": 1, + "type": "number" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CampaignContactPaginatedResponse" + } + } + } + } + }, + "tags": [ + "Campaigns" + ], + "security": [ + { + "bearer": [] + } + ] + } + }, + "/session": { + "post": { + "operationId": "SessionController_create", + "summary": "Create Session", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateSessionDTO" + } + } + } + }, + "responses": { + "201": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Session" + } + } + } + } + }, + "tags": [ + "Sessions" + ], + "security": [ + { + "bearer": [] + } + ] + }, + "get": { + "operationId": "SessionController_findAllPaginated", + "summary": "List Sessions", "parameters": [ + { + "name": "id", + "required": false, + "in": "query", + "description": "This is the unique identifier for the session to filter by.", + "schema": { + "type": "string" + } + }, + { + "name": "name", + "required": false, + "in": "query", + "description": "This is the name of the session to filter by.", + "schema": { + "type": "string" + } + }, + { + "name": "assistantId", + "required": false, + "in": "query", + "description": "This is the ID of the assistant to filter sessions by.", + "schema": { + "type": "string" + } + }, + { + "name": "assistantIdAny", + "required": false, + "in": "query", + "description": "Filter by multiple assistant IDs. Provide as comma-separated values.", + "schema": { + "example": "assistant-1,assistant-2,assistant-3", + "type": "string" + } + }, + { + "name": "squadId", + "required": false, + "in": "query", + "description": "This is the ID of the squad to filter sessions by.", + "schema": { + "type": "string" + } + }, + { + "name": "workflowId", + "required": false, + "in": "query", + "description": "This is the ID of the workflow to filter sessions by.", + "schema": { + "type": "string" + } + }, + { + "required": false, + "description": "This is the flag to toggle the E164 check for the `number` field. This is an advanced property which should be used if you know your use case requires it.\n\nUse cases:\n- `false`: To allow non-E164 numbers like `+001234567890`, `1234`, or `abc`. This is useful for dialing out to non-E164 numbers on your SIP trunks.\n- `true` (default): To allow only E164 numbers like `+14155551234`. This is standard for PSTN calls.\n\nIf `false`, the `number` is still required to only contain alphanumeric characters (regex: `/^\\+?[a-zA-Z0-9]+$/`).\n\n@default true (E164 check is enabled)", + "name": "numberE164CheckEnabled", + "in": "query", + "schema": { + "default": true, + "type": "boolean" + } + }, + { + "required": false, + "description": "This is the extension that will be dialed after the call is answered.", + "name": "extension", + "in": "query", + "schema": { + "maxLength": 10, + "example": null, + "type": "string" + } + }, + { + "name": "assistantOverrides", + "required": false, + "description": "These are the overrides for the assistant's settings and template variables specific to this customer.\nThis allows customization of the assistant's behavior for individual customers in batch calls.", + "allOf": [ + { + "$ref": "#/components/schemas/AssistantOverrides" + } + ], + "in": "query", + "schema": {} + }, + { + "name": "squadOverrides", + "required": false, + "description": "These are the overrides applied when the call targets a `squadId`. Mirrors\nthe call-level `squadOverrides` — use this instead of `assistantOverrides`\nwhen the campaign or call is squad-based.", + "allOf": [ + { + "$ref": "#/components/schemas/AssistantOverrides" + } + ], + "in": "query", + "schema": {} + }, + { + "required": false, + "description": "This is the number of the customer.", + "name": "number", + "in": "query", + "schema": { + "minLength": 3, + "maxLength": 40, + "type": "string" + } + }, + { + "required": false, + "description": "This is the SIP URI of the customer.", + "name": "sipUri", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "required": false, + "description": "This is the name of the customer. This is just for your own reference.\n\nFor SIP inbound calls, this is extracted from the `From` SIP header with format `\"Display Name\" `.", + "name": "name", + "in": "query", + "schema": { + "maxLength": 40, + "type": "string" + } + }, + { + "required": false, + "description": "This is the email of the customer.", + "name": "email", + "in": "query", + "schema": { + "maxLength": 40, + "type": "string" + } + }, + { + "required": false, + "description": "This is the external ID of the customer.", + "name": "externalId", + "in": "query", + "schema": { + "maxLength": 40, + "type": "string" + } + }, + { + "name": "customerNumberAny", + "required": false, + "in": "query", + "description": "Filter by any of the specified customer phone numbers (comma-separated).", + "schema": { + "example": "+1234567890,+0987654321", + "type": "string" + } + }, + { + "name": "idAny", + "required": false, + "in": "query", + "description": "Filter by multiple session IDs. Provide as comma-separated values.", + "schema": { + "type": "string" + } + }, + { + "name": "phoneNumberId", + "required": false, + "in": "query", + "description": "This will return sessions with the specified phoneNumberId.", + "schema": { + "type": "string" + } + }, + { + "name": "phoneNumberIdAny", + "required": false, + "in": "query", + "description": "This will return sessions with any of the specified phoneNumberIds.", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "page", + "required": false, + "in": "query", + "description": "This is the page number to return. Defaults to 1.", + "schema": { + "minimum": 1, + "type": "number" + } + }, + { + "name": "sortOrder", + "required": false, + "in": "query", + "description": "This is the sort order for pagination. Defaults to 'DESC'.", + "schema": { + "enum": [ + "ASC", + "DESC" + ], + "type": "string" + } + }, + { + "name": "sortBy", + "required": false, + "in": "query", + "description": "This is the column to sort by. Defaults to 'createdAt'.", + "schema": { + "enum": [ + "createdAt", + "duration", + "cost" + ], + "type": "string" + } + }, { "name": "limit", "required": false, @@ -2409,127 +2726,14 @@ "content": { "application/json": { "schema": { - "type": "array", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ApiRequestTool", - "title": "ApiRequestTool" - }, - { - "$ref": "#/components/schemas/DtmfTool", - "title": "DtmfTool" - }, - { - "$ref": "#/components/schemas/EndCallTool", - "title": "EndCallTool" - }, - { - "$ref": "#/components/schemas/FunctionTool", - "title": "FunctionTool" - }, - { - "$ref": "#/components/schemas/GhlTool", - "title": "GhlTool" - }, - { - "$ref": "#/components/schemas/TransferCallTool", - "title": "TransferCallTool" - }, - { - "$ref": "#/components/schemas/HandoffTool", - "title": "HandoffTool" - }, - { - "$ref": "#/components/schemas/BashTool", - "title": "BashTool" - }, - { - "$ref": "#/components/schemas/ComputerTool", - "title": "ComputerTool" - }, - { - "$ref": "#/components/schemas/TextEditorTool", - "title": "TextEditorTool" - }, - { - "$ref": "#/components/schemas/QueryTool", - "title": "QueryTool" - }, - { - "$ref": "#/components/schemas/GoogleCalendarCreateEventTool", - "title": "GoogleCalendarCreateEventTool" - }, - { - "$ref": "#/components/schemas/GoogleSheetsRowAppendTool", - "title": "GoogleSheetsRowAppendTool" - }, - { - "$ref": "#/components/schemas/GoogleCalendarCheckAvailabilityTool", - "title": "GoogleCalendarCheckAvailabilityTool" - }, - { - "$ref": "#/components/schemas/SlackSendMessageTool", - "title": "SlackSendMessageTool" - }, - { - "$ref": "#/components/schemas/SmsTool", - "title": "SmsSendTool" - }, - { - "$ref": "#/components/schemas/McpTool", - "title": "McpTool" - }, - { - "$ref": "#/components/schemas/GoHighLevelCalendarAvailabilityTool", - "title": "GoHighLevelCalendarAvailabilityTool" - }, - { - "$ref": "#/components/schemas/GoHighLevelCalendarEventCreateTool", - "title": "GoHighLevelCalendarEventCreateTool" - }, - { - "$ref": "#/components/schemas/GoHighLevelContactCreateTool", - "title": "GoHighLevelContactCreateTool" - }, - { - "$ref": "#/components/schemas/GoHighLevelContactGetTool", - "title": "GoHighLevelContactGetTool" - } - ], - "discriminator": { - "propertyName": "type", - "mapping": { - "apiRequest": "#/components/schemas/ApiRequestTool", - "dtmf": "#/components/schemas/DtmfTool", - "endCall": "#/components/schemas/EndCallTool", - "function": "#/components/schemas/FunctionTool", - "transferCall": "#/components/schemas/TransferCallTool", - "handoff": "#/components/schemas/HandoffTool", - "bash": "#/components/schemas/BashTool", - "computer": "#/components/schemas/ComputerTool", - "textEditor": "#/components/schemas/TextEditorTool", - "query": "#/components/schemas/QueryTool", - "google.calendar.event.create": "#/components/schemas/GoogleCalendarCreateEventTool", - "google.sheets.row.append": "#/components/schemas/GoogleSheetsRowAppendTool", - "google.calendar.availability.check": "#/components/schemas/GoogleCalendarCheckAvailabilityTool", - "slack.message.send": "#/components/schemas/SlackSendMessageTool", - "sms": "#/components/schemas/SmsTool", - "mcp": "#/components/schemas/McpTool", - "gohighlevel.calendar.availability.check": "#/components/schemas/GoHighLevelCalendarAvailabilityTool", - "gohighlevel.calendar.event.create": "#/components/schemas/GoHighLevelCalendarEventCreateTool", - "gohighlevel.contact.create": "#/components/schemas/GoHighLevelContactCreateTool", - "gohighlevel.contact.get": "#/components/schemas/GoHighLevelContactGetTool" - } - } - } + "$ref": "#/components/schemas/SessionPaginatedResponse" } } } } }, "tags": [ - "Tools" + "Sessions" ], "security": [ { @@ -2538,16 +2742,18 @@ ] } }, - "/tool/{id}": { + "/session/{id}": { "get": { - "operationId": "ToolController_findOne", - "summary": "Get Tool", + "operationId": "SessionController_findOne", + "summary": "Get Session", "parameters": [ { "name": "id", "required": true, "in": "path", + "description": "The unique identifier for the resource.", "schema": { + "format": "uuid", "type": "string" } } @@ -2558,124 +2764,14 @@ "content": { "application/json": { "schema": { - "oneOf": [ - { - "$ref": "#/components/schemas/ApiRequestTool", - "title": "ApiRequestTool" - }, - { - "$ref": "#/components/schemas/DtmfTool", - "title": "DtmfTool" - }, - { - "$ref": "#/components/schemas/EndCallTool", - "title": "EndCallTool" - }, - { - "$ref": "#/components/schemas/FunctionTool", - "title": "FunctionTool" - }, - { - "$ref": "#/components/schemas/GhlTool", - "title": "GhlTool" - }, - { - "$ref": "#/components/schemas/TransferCallTool", - "title": "TransferCallTool" - }, - { - "$ref": "#/components/schemas/HandoffTool", - "title": "HandoffTool" - }, - { - "$ref": "#/components/schemas/BashTool", - "title": "BashTool" - }, - { - "$ref": "#/components/schemas/ComputerTool", - "title": "ComputerTool" - }, - { - "$ref": "#/components/schemas/TextEditorTool", - "title": "TextEditorTool" - }, - { - "$ref": "#/components/schemas/QueryTool", - "title": "QueryTool" - }, - { - "$ref": "#/components/schemas/GoogleCalendarCreateEventTool", - "title": "GoogleCalendarCreateEventTool" - }, - { - "$ref": "#/components/schemas/GoogleSheetsRowAppendTool", - "title": "GoogleSheetsRowAppendTool" - }, - { - "$ref": "#/components/schemas/GoogleCalendarCheckAvailabilityTool", - "title": "GoogleCalendarCheckAvailabilityTool" - }, - { - "$ref": "#/components/schemas/SlackSendMessageTool", - "title": "SlackSendMessageTool" - }, - { - "$ref": "#/components/schemas/SmsTool", - "title": "SmsSendTool" - }, - { - "$ref": "#/components/schemas/McpTool", - "title": "McpTool" - }, - { - "$ref": "#/components/schemas/GoHighLevelCalendarAvailabilityTool", - "title": "GoHighLevelCalendarAvailabilityTool" - }, - { - "$ref": "#/components/schemas/GoHighLevelCalendarEventCreateTool", - "title": "GoHighLevelCalendarEventCreateTool" - }, - { - "$ref": "#/components/schemas/GoHighLevelContactCreateTool", - "title": "GoHighLevelContactCreateTool" - }, - { - "$ref": "#/components/schemas/GoHighLevelContactGetTool", - "title": "GoHighLevelContactGetTool" - } - ], - "discriminator": { - "propertyName": "type", - "mapping": { - "apiRequest": "#/components/schemas/ApiRequestTool", - "dtmf": "#/components/schemas/DtmfTool", - "endCall": "#/components/schemas/EndCallTool", - "function": "#/components/schemas/FunctionTool", - "transferCall": "#/components/schemas/TransferCallTool", - "handoff": "#/components/schemas/HandoffTool", - "bash": "#/components/schemas/BashTool", - "computer": "#/components/schemas/ComputerTool", - "textEditor": "#/components/schemas/TextEditorTool", - "query": "#/components/schemas/QueryTool", - "google.calendar.event.create": "#/components/schemas/GoogleCalendarCreateEventTool", - "google.sheets.row.append": "#/components/schemas/GoogleSheetsRowAppendTool", - "google.calendar.availability.check": "#/components/schemas/GoogleCalendarCheckAvailabilityTool", - "slack.message.send": "#/components/schemas/SlackSendMessageTool", - "sms": "#/components/schemas/SmsTool", - "mcp": "#/components/schemas/McpTool", - "gohighlevel.calendar.availability.check": "#/components/schemas/GoHighLevelCalendarAvailabilityTool", - "gohighlevel.calendar.event.create": "#/components/schemas/GoHighLevelCalendarEventCreateTool", - "gohighlevel.contact.create": "#/components/schemas/GoHighLevelContactCreateTool", - "gohighlevel.contact.get": "#/components/schemas/GoHighLevelContactGetTool" - } - } + "$ref": "#/components/schemas/Session" } } } } }, "tags": [ - "Tools" + "Sessions" ], "security": [ { @@ -2684,18 +2780,93 @@ ] }, "patch": { - "operationId": "ToolController_update", - "summary": "Update Tool", + "operationId": "SessionController_update", + "summary": "Update Session", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "description": "The unique identifier for the resource.", + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateSessionDTO" + } + } + } + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Session" + } + } + } + } + }, + "tags": [ + "Sessions" + ], + "security": [ + { + "bearer": [] + } + ] + }, + "delete": { + "operationId": "SessionController_remove", + "summary": "Delete Session", "parameters": [ { "name": "id", "required": true, "in": "path", + "description": "The unique identifier for the resource.", "schema": { + "format": "uuid", "type": "string" } } ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Session" + } + } + } + } + }, + "tags": [ + "Sessions" + ], + "security": [ + { + "bearer": [] + } + ] + } + }, + "/phone-number": { + "post": { + "operationId": "PhoneNumberController_create", + "summary": "Create Phone Number", + "parameters": [], "requestBody": { "required": true, "content": { @@ -2703,109 +2874,34 @@ "schema": { "oneOf": [ { - "$ref": "#/components/schemas/UpdateApiRequestToolDTO", - "title": "ApiRequestTool" - }, - { - "$ref": "#/components/schemas/UpdateDtmfToolDTO", - "title": "DtmfTool" - }, - { - "$ref": "#/components/schemas/UpdateEndCallToolDTO", - "title": "EndCallTool" - }, - { - "$ref": "#/components/schemas/UpdateFunctionToolDTO", - "title": "FunctionTool" - }, - { - "$ref": "#/components/schemas/UpdateTransferCallToolDTO", - "title": "TransferCallTool" - }, - { - "$ref": "#/components/schemas/UpdateHandoffToolDTO", - "title": "HandoffTool" - }, - { - "$ref": "#/components/schemas/UpdateBashToolDTO", - "title": "BashTool" - }, - { - "$ref": "#/components/schemas/UpdateComputerToolDTO", - "title": "ComputerTool" - }, - { - "$ref": "#/components/schemas/UpdateTextEditorToolDTO", - "title": "TextEditorTool" - }, - { - "$ref": "#/components/schemas/UpdateQueryToolDTO", - "title": "QueryTool" - }, - { - "$ref": "#/components/schemas/UpdateGoogleCalendarCreateEventToolDTO", - "title": "GoogleCalendarCreateEventTool" - }, - { - "$ref": "#/components/schemas/UpdateGoogleSheetsRowAppendToolDTO", - "title": "GoogleSheetsRowAppendTool" - }, - { - "$ref": "#/components/schemas/UpdateGoogleCalendarCheckAvailabilityToolDTO", - "title": "GoogleCalendarCheckAvailabilityTool" - }, - { - "$ref": "#/components/schemas/UpdateSlackSendMessageToolDTO", - "title": "SlackSendMessageTool" - }, - { - "$ref": "#/components/schemas/UpdateSmsToolDTO", - "title": "SmsSendTool" - }, - { - "$ref": "#/components/schemas/UpdateMcpToolDTO", - "title": "McpTool" + "$ref": "#/components/schemas/CreateByoPhoneNumberDTO", + "title": "ByoPhoneNumber" }, { - "$ref": "#/components/schemas/UpdateGoHighLevelCalendarAvailabilityToolDTO", - "title": "GoHighLevelCalendarAvailabilityTool" + "$ref": "#/components/schemas/CreateTwilioPhoneNumberDTO", + "title": "TwilioPhoneNumber" }, { - "$ref": "#/components/schemas/UpdateGoHighLevelCalendarEventCreateToolDTO", - "title": "GoHighLevelCalendarEventCreateTool" + "$ref": "#/components/schemas/CreateVonagePhoneNumberDTO", + "title": "VonagePhoneNumber" }, { - "$ref": "#/components/schemas/UpdateGoHighLevelContactCreateToolDTO", - "title": "GoHighLevelContactCreateTool" + "$ref": "#/components/schemas/CreateVapiPhoneNumberDTO", + "title": "VapiPhoneNumber" }, { - "$ref": "#/components/schemas/UpdateGoHighLevelContactGetToolDTO", - "title": "GoHighLevelContactGetTool" + "$ref": "#/components/schemas/CreateTelnyxPhoneNumberDTO", + "title": "TelnyxPhoneNumber" } ], "discriminator": { - "propertyName": "type", + "propertyName": "provider", "mapping": { - "apiRequest": "#/components/schemas/UpdateApiRequestToolDTO", - "dtmf": "#/components/schemas/UpdateDtmfToolDTO", - "endCall": "#/components/schemas/UpdateEndCallToolDTO", - "function": "#/components/schemas/UpdateFunctionToolDTO", - "transferCall": "#/components/schemas/UpdateTransferCallToolDTO", - "handoff": "#/components/schemas/UpdateHandoffToolDTO", - "bash": "#/components/schemas/UpdateBashToolDTO", - "computer": "#/components/schemas/UpdateComputerToolDTO", - "textEditor": "#/components/schemas/UpdateTextEditorToolDTO", - "query": "#/components/schemas/UpdateQueryToolDTO", - "google.calendar.event.create": "#/components/schemas/UpdateGoogleCalendarCreateEventToolDTO", - "google.sheets.row.append": "#/components/schemas/UpdateGoogleSheetsRowAppendToolDTO", - "google.calendar.availability.check": "#/components/schemas/UpdateGoogleCalendarCheckAvailabilityToolDTO", - "slack.message.send": "#/components/schemas/UpdateSlackSendMessageToolDTO", - "sms": "#/components/schemas/UpdateSmsToolDTO", - "mcp": "#/components/schemas/UpdateMcpToolDTO", - "gohighlevel.calendar.availability.check": "#/components/schemas/UpdateGoHighLevelCalendarAvailabilityToolDTO", - "gohighlevel.calendar.event.create": "#/components/schemas/UpdateGoHighLevelCalendarEventCreateToolDTO", - "gohighlevel.contact.create": "#/components/schemas/UpdateGoHighLevelContactCreateToolDTO", - "gohighlevel.contact.get": "#/components/schemas/UpdateGoHighLevelContactGetToolDTO" + "byo-phone-number": "#/components/schemas/CreateByoPhoneNumberDTO", + "twilio": "#/components/schemas/CreateTwilioPhoneNumberDTO", + "vonage": "#/components/schemas/CreateVonagePhoneNumberDTO", + "vapi": "#/components/schemas/CreateVapiPhoneNumberDTO", + "telnyx": "#/components/schemas/CreateTelnyxPhoneNumberDTO" } } } @@ -2813,120 +2909,42 @@ } }, "responses": { - "200": { + "201": { "description": "", "content": { "application/json": { "schema": { + "title": "PhoneNumber", "oneOf": [ { - "$ref": "#/components/schemas/ApiRequestTool", - "title": "ApiRequestTool" - }, - { - "$ref": "#/components/schemas/DtmfTool", - "title": "DtmfTool" - }, - { - "$ref": "#/components/schemas/EndCallTool", - "title": "EndCallTool" - }, - { - "$ref": "#/components/schemas/FunctionTool", - "title": "FunctionTool" - }, - { - "$ref": "#/components/schemas/GhlTool", - "title": "GhlTool" - }, - { - "$ref": "#/components/schemas/TransferCallTool", - "title": "TransferCallTool" - }, - { - "$ref": "#/components/schemas/HandoffTool", - "title": "HandoffTool" - }, - { - "$ref": "#/components/schemas/BashTool", - "title": "BashTool" - }, - { - "$ref": "#/components/schemas/ComputerTool", - "title": "ComputerTool" - }, - { - "$ref": "#/components/schemas/TextEditorTool", - "title": "TextEditorTool" - }, - { - "$ref": "#/components/schemas/QueryTool", - "title": "QueryTool" - }, - { - "$ref": "#/components/schemas/GoogleCalendarCreateEventTool", - "title": "GoogleCalendarCreateEventTool" - }, - { - "$ref": "#/components/schemas/GoogleSheetsRowAppendTool", - "title": "GoogleSheetsRowAppendTool" - }, - { - "$ref": "#/components/schemas/GoogleCalendarCheckAvailabilityTool", - "title": "GoogleCalendarCheckAvailabilityTool" - }, - { - "$ref": "#/components/schemas/SlackSendMessageTool", - "title": "SlackSendMessageTool" - }, - { - "$ref": "#/components/schemas/SmsTool", - "title": "SmsSendTool" - }, - { - "$ref": "#/components/schemas/McpTool", - "title": "McpTool" + "$ref": "#/components/schemas/ByoPhoneNumber", + "title": "ByoPhoneNumber" }, { - "$ref": "#/components/schemas/GoHighLevelCalendarAvailabilityTool", - "title": "GoHighLevelCalendarAvailabilityTool" + "$ref": "#/components/schemas/TwilioPhoneNumber", + "title": "TwilioPhoneNumber" }, { - "$ref": "#/components/schemas/GoHighLevelCalendarEventCreateTool", - "title": "GoHighLevelCalendarEventCreateTool" + "$ref": "#/components/schemas/VonagePhoneNumber", + "title": "VonagePhoneNumber" }, { - "$ref": "#/components/schemas/GoHighLevelContactCreateTool", - "title": "GoHighLevelContactCreateTool" + "$ref": "#/components/schemas/VapiPhoneNumber", + "title": "VapiPhoneNumber" }, { - "$ref": "#/components/schemas/GoHighLevelContactGetTool", - "title": "GoHighLevelContactGetTool" + "$ref": "#/components/schemas/TelnyxPhoneNumber", + "title": "TelnyxPhoneNumber" } ], "discriminator": { - "propertyName": "type", + "propertyName": "provider", "mapping": { - "apiRequest": "#/components/schemas/ApiRequestTool", - "dtmf": "#/components/schemas/DtmfTool", - "endCall": "#/components/schemas/EndCallTool", - "function": "#/components/schemas/FunctionTool", - "transferCall": "#/components/schemas/TransferCallTool", - "handoff": "#/components/schemas/HandoffTool", - "bash": "#/components/schemas/BashTool", - "computer": "#/components/schemas/ComputerTool", - "textEditor": "#/components/schemas/TextEditorTool", - "query": "#/components/schemas/QueryTool", - "google.calendar.event.create": "#/components/schemas/GoogleCalendarCreateEventTool", - "google.sheets.row.append": "#/components/schemas/GoogleSheetsRowAppendTool", - "google.calendar.availability.check": "#/components/schemas/GoogleCalendarCheckAvailabilityTool", - "slack.message.send": "#/components/schemas/SlackSendMessageTool", - "sms": "#/components/schemas/SmsTool", - "mcp": "#/components/schemas/McpTool", - "gohighlevel.calendar.availability.check": "#/components/schemas/GoHighLevelCalendarAvailabilityTool", - "gohighlevel.calendar.event.create": "#/components/schemas/GoHighLevelCalendarEventCreateTool", - "gohighlevel.contact.create": "#/components/schemas/GoHighLevelContactCreateTool", - "gohighlevel.contact.get": "#/components/schemas/GoHighLevelContactGetTool" + "byo-phone-number": "#/components/schemas/ByoPhoneNumber", + "twilio": "#/components/schemas/TwilioPhoneNumber", + "vonage": "#/components/schemas/VonagePhoneNumber", + "vapi": "#/components/schemas/VapiPhoneNumber", + "telnyx": "#/components/schemas/TelnyxPhoneNumber" } } } @@ -2935,7 +2953,7 @@ } }, "tags": [ - "Tools" + "Phone Numbers" ], "security": [ { @@ -2943,405 +2961,211 @@ } ] }, - "delete": { - "operationId": "ToolController_remove", - "summary": "Delete Tool", + "get": { + "operationId": "PhoneNumberController_findAll", + "summary": "List Phone Numbers", "parameters": [ { - "name": "id", - "required": true, - "in": "path", + "name": "limit", + "required": false, + "in": "query", + "description": "This is the maximum number of items to return. Defaults to 100.", + "schema": { + "minimum": 0, + "maximum": 1000, + "type": "number" + } + }, + { + "name": "createdAtGt", + "required": false, + "in": "query", + "description": "This will return items where the createdAt is greater than the specified value.", "schema": { + "format": "date-time", "type": "string" } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "oneOf": [ - { - "$ref": "#/components/schemas/ApiRequestTool", - "title": "ApiRequestTool" - }, - { - "$ref": "#/components/schemas/DtmfTool", - "title": "DtmfTool" - }, - { - "$ref": "#/components/schemas/EndCallTool", - "title": "EndCallTool" - }, - { - "$ref": "#/components/schemas/FunctionTool", - "title": "FunctionTool" - }, - { - "$ref": "#/components/schemas/GhlTool", - "title": "GhlTool" - }, - { - "$ref": "#/components/schemas/TransferCallTool", - "title": "TransferCallTool" - }, - { - "$ref": "#/components/schemas/HandoffTool", - "title": "HandoffTool" - }, - { - "$ref": "#/components/schemas/BashTool", - "title": "BashTool" - }, - { - "$ref": "#/components/schemas/ComputerTool", - "title": "ComputerTool" - }, - { - "$ref": "#/components/schemas/TextEditorTool", - "title": "TextEditorTool" - }, - { - "$ref": "#/components/schemas/QueryTool", - "title": "QueryTool" - }, - { - "$ref": "#/components/schemas/GoogleCalendarCreateEventTool", - "title": "GoogleCalendarCreateEventTool" - }, - { - "$ref": "#/components/schemas/GoogleSheetsRowAppendTool", - "title": "GoogleSheetsRowAppendTool" - }, - { - "$ref": "#/components/schemas/GoogleCalendarCheckAvailabilityTool", - "title": "GoogleCalendarCheckAvailabilityTool" - }, - { - "$ref": "#/components/schemas/SlackSendMessageTool", - "title": "SlackSendMessageTool" - }, - { - "$ref": "#/components/schemas/SmsTool", - "title": "SmsSendTool" - }, - { - "$ref": "#/components/schemas/McpTool", - "title": "McpTool" - }, - { - "$ref": "#/components/schemas/GoHighLevelCalendarAvailabilityTool", - "title": "GoHighLevelCalendarAvailabilityTool" - }, - { - "$ref": "#/components/schemas/GoHighLevelCalendarEventCreateTool", - "title": "GoHighLevelCalendarEventCreateTool" - }, - { - "$ref": "#/components/schemas/GoHighLevelContactCreateTool", - "title": "GoHighLevelContactCreateTool" - }, - { - "$ref": "#/components/schemas/GoHighLevelContactGetTool", - "title": "GoHighLevelContactGetTool" - } - ], - "discriminator": { - "propertyName": "type", - "mapping": { - "apiRequest": "#/components/schemas/ApiRequestTool", - "dtmf": "#/components/schemas/DtmfTool", - "endCall": "#/components/schemas/EndCallTool", - "function": "#/components/schemas/FunctionTool", - "transferCall": "#/components/schemas/TransferCallTool", - "handoff": "#/components/schemas/HandoffTool", - "bash": "#/components/schemas/BashTool", - "computer": "#/components/schemas/ComputerTool", - "textEditor": "#/components/schemas/TextEditorTool", - "query": "#/components/schemas/QueryTool", - "google.calendar.event.create": "#/components/schemas/GoogleCalendarCreateEventTool", - "google.sheets.row.append": "#/components/schemas/GoogleSheetsRowAppendTool", - "google.calendar.availability.check": "#/components/schemas/GoogleCalendarCheckAvailabilityTool", - "slack.message.send": "#/components/schemas/SlackSendMessageTool", - "sms": "#/components/schemas/SmsTool", - "mcp": "#/components/schemas/McpTool", - "gohighlevel.calendar.availability.check": "#/components/schemas/GoHighLevelCalendarAvailabilityTool", - "gohighlevel.calendar.event.create": "#/components/schemas/GoHighLevelCalendarEventCreateTool", - "gohighlevel.contact.create": "#/components/schemas/GoHighLevelContactCreateTool", - "gohighlevel.contact.get": "#/components/schemas/GoHighLevelContactGetTool" - } - } - } - } - } - } - }, - "tags": [ - "Tools" - ], - "security": [ + }, { - "bearer": [] - } - ] - } - }, - "/file": { - "post": { - "operationId": "FileController_create", - "summary": "Upload File", - "parameters": [], - "requestBody": { - "required": true, - "content": { - "multipart/form-data": { - "schema": { - "$ref": "#/components/schemas/CreateFileDTO" - } - } - } - }, - "responses": { - "201": { - "description": "File uploaded successfully", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/File" - } - } + "name": "createdAtLt", + "required": false, + "in": "query", + "description": "This will return items where the createdAt is less than the specified value.", + "schema": { + "format": "date-time", + "type": "string" } }, - "400": { - "description": "Invalid file" - } - }, - "tags": [ - "Files" - ], - "security": [ { - "bearer": [] - } - ] - }, - "get": { - "operationId": "FileController_findAll", - "summary": "List Files", - "parameters": [], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/File" - } - } - } + "name": "createdAtGe", + "required": false, + "in": "query", + "description": "This will return items where the createdAt is greater than or equal to the specified value.", + "schema": { + "format": "date-time", + "type": "string" } - } - }, - "tags": [ - "Files" - ], - "security": [ + }, { - "bearer": [] - } - ] - } - }, - "/file/{id}": { - "get": { - "operationId": "FileController_findOne", - "summary": "Get File", - "parameters": [ + "name": "createdAtLe", + "required": false, + "in": "query", + "description": "This will return items where the createdAt is less than or equal to the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } + }, { - "name": "id", - "required": true, - "in": "path", + "name": "updatedAtGt", + "required": false, + "in": "query", + "description": "This will return items where the updatedAt is greater than the specified value.", "schema": { + "format": "date-time", "type": "string" } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/File" - } - } + }, + { + "name": "updatedAtLt", + "required": false, + "in": "query", + "description": "This will return items where the updatedAt is less than the specified value.", + "schema": { + "format": "date-time", + "type": "string" } - } - }, - "tags": [ - "Files" - ], - "security": [ + }, { - "bearer": [] - } - ] - }, - "patch": { - "operationId": "FileController_update", - "summary": "Update File", - "parameters": [ + "name": "updatedAtGe", + "required": false, + "in": "query", + "description": "This will return items where the updatedAt is greater than or equal to the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } + }, { - "name": "id", - "required": true, - "in": "path", + "name": "updatedAtLe", + "required": false, + "in": "query", + "description": "This will return items where the updatedAt is less than or equal to the specified value.", "schema": { + "format": "date-time", "type": "string" } } ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateFileDTO" - } - } - } - }, "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/File" + "type": "array", + "items": { + "title": "PhoneNumber", + "oneOf": [ + { + "$ref": "#/components/schemas/ByoPhoneNumber", + "title": "ByoPhoneNumber" + }, + { + "$ref": "#/components/schemas/TwilioPhoneNumber", + "title": "TwilioPhoneNumber" + }, + { + "$ref": "#/components/schemas/VonagePhoneNumber", + "title": "VonagePhoneNumber" + }, + { + "$ref": "#/components/schemas/VapiPhoneNumber", + "title": "VapiPhoneNumber" + }, + { + "$ref": "#/components/schemas/TelnyxPhoneNumber", + "title": "TelnyxPhoneNumber" + } + ], + "discriminator": { + "propertyName": "provider", + "mapping": { + "byo-phone-number": "#/components/schemas/ByoPhoneNumber", + "twilio": "#/components/schemas/TwilioPhoneNumber", + "vonage": "#/components/schemas/VonagePhoneNumber", + "vapi": "#/components/schemas/VapiPhoneNumber", + "telnyx": "#/components/schemas/TelnyxPhoneNumber" + } + } + } } } } } }, "tags": [ - "Files" + "Phone Numbers" ], "security": [ { "bearer": [] } ] - }, - "delete": { - "operationId": "FileController_remove", - "summary": "Delete File", + } + }, + "/v2/phone-number": { + "get": { + "operationId": "PhoneNumberController_findAllPaginated", + "summary": "List Phone Numbers", "parameters": [ { - "name": "id", - "required": true, - "in": "path", + "name": "search", + "required": false, + "in": "query", + "description": "This will search phone numbers by name, number, or SIP URI (partial match, case-insensitive).", "schema": { + "maxLength": 100, "type": "string" } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/File" - } - } - } - } - }, - "tags": [ - "Files" - ], - "security": [ + }, { - "bearer": [] - } - ] - } - }, - "/knowledge-base": { - "post": { - "operationId": "KnowledgeBaseController_create", - "summary": "Create Knowledge Base", - "parameters": [], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "oneOf": [ - { - "$ref": "#/components/schemas/CreateTrieveKnowledgeBaseDTO", - "title": "TrieveKnowledgeBaseDTO" - }, - { - "$ref": "#/components/schemas/CreateCustomKnowledgeBaseDTO", - "title": "CustomKnowledgeBaseDTO" - } - ], - "discriminator": { - "propertyName": "provider", - "mapping": { - "trieve": "#/components/schemas/CreateTrieveKnowledgeBaseDTO", - "custom-knowledge-base": "#/components/schemas/CreateCustomKnowledgeBaseDTO" - } - } - } + "name": "page", + "required": false, + "in": "query", + "description": "This is the page number to return. Defaults to 1.", + "schema": { + "minimum": 1, + "type": "number" } - } - }, - "responses": { - "201": { - "description": "", - "content": { - "application/json": { - "schema": { - "oneOf": [ - { - "$ref": "#/components/schemas/TrieveKnowledgeBase", - "title": "TrieveKnowledgeBase" - }, - { - "$ref": "#/components/schemas/CustomKnowledgeBase", - "title": "CustomKnowledgeBase" - } - ], - "discriminator": { - "propertyName": "provider", - "mapping": { - "trieve": "#/components/schemas/TrieveKnowledgeBase", - "custom-knowledge-base": "#/components/schemas/CustomKnowledgeBase" - } - } - } - } + }, + { + "name": "sortOrder", + "required": false, + "in": "query", + "description": "This is the sort order for pagination. Defaults to 'DESC'.", + "schema": { + "enum": [ + "ASC", + "DESC" + ], + "type": "string" } - } - }, - "tags": [ - "Knowledge Base" - ], - "security": [ + }, { - "bearer": [] - } - ] - }, - "get": { - "operationId": "KnowledgeBaseController_findAll", - "summary": "List Knowledge Bases", - "parameters": [ + "name": "sortBy", + "required": false, + "in": "query", + "description": "This is the column to sort by. Defaults to 'createdAt'.", + "schema": { + "enum": [ + "createdAt", + "duration", + "cost" + ], + "type": "string" + } + }, { "name": "limit", "required": false, @@ -3440,33 +3264,14 @@ "content": { "application/json": { "schema": { - "type": "array", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/TrieveKnowledgeBase", - "title": "TrieveKnowledgeBase" - }, - { - "$ref": "#/components/schemas/CustomKnowledgeBase", - "title": "CustomKnowledgeBase" - } - ], - "discriminator": { - "propertyName": "provider", - "mapping": { - "trieve": "#/components/schemas/TrieveKnowledgeBase", - "custom-knowledge-base": "#/components/schemas/CustomKnowledgeBase" - } - } - } + "$ref": "#/components/schemas/PhoneNumberPaginatedResponse" } } } } }, "tags": [ - "Knowledge Base" + "Phone Numbers" ], "security": [ { @@ -3475,16 +3280,18 @@ ] } }, - "/knowledge-base/{id}": { + "/phone-number/{id}": { "get": { - "operationId": "KnowledgeBaseController_findOne", - "summary": "Get Knowledge Base", + "operationId": "PhoneNumberController_findOne", + "summary": "Get Phone Number", "parameters": [ { "name": "id", "required": true, "in": "path", + "description": "The unique identifier for the resource.", "schema": { + "format": "uuid", "type": "string" } } @@ -3495,21 +3302,37 @@ "content": { "application/json": { "schema": { + "title": "PhoneNumber", "oneOf": [ { - "$ref": "#/components/schemas/TrieveKnowledgeBase", - "title": "TrieveKnowledgeBase" + "$ref": "#/components/schemas/ByoPhoneNumber", + "title": "ByoPhoneNumber" + }, + { + "$ref": "#/components/schemas/TwilioPhoneNumber", + "title": "TwilioPhoneNumber" + }, + { + "$ref": "#/components/schemas/VonagePhoneNumber", + "title": "VonagePhoneNumber" + }, + { + "$ref": "#/components/schemas/VapiPhoneNumber", + "title": "VapiPhoneNumber" }, { - "$ref": "#/components/schemas/CustomKnowledgeBase", - "title": "CustomKnowledgeBase" + "$ref": "#/components/schemas/TelnyxPhoneNumber", + "title": "TelnyxPhoneNumber" } ], "discriminator": { "propertyName": "provider", "mapping": { - "trieve": "#/components/schemas/TrieveKnowledgeBase", - "custom-knowledge-base": "#/components/schemas/CustomKnowledgeBase" + "byo-phone-number": "#/components/schemas/ByoPhoneNumber", + "twilio": "#/components/schemas/TwilioPhoneNumber", + "vonage": "#/components/schemas/VonagePhoneNumber", + "vapi": "#/components/schemas/VapiPhoneNumber", + "telnyx": "#/components/schemas/TelnyxPhoneNumber" } } } @@ -3518,7 +3341,7 @@ } }, "tags": [ - "Knowledge Base" + "Phone Numbers" ], "security": [ { @@ -3527,14 +3350,16 @@ ] }, "patch": { - "operationId": "KnowledgeBaseController_update", - "summary": "Update Knowledge Base", + "operationId": "PhoneNumberController_update", + "summary": "Update Phone Number", "parameters": [ { "name": "id", "required": true, "in": "path", + "description": "The unique identifier for the resource.", "schema": { + "format": "uuid", "type": "string" } } @@ -3546,19 +3371,34 @@ "schema": { "oneOf": [ { - "$ref": "#/components/schemas/UpdateTrieveKnowledgeBaseDTO", - "title": "UpdateTrieveKnowledgeBaseDTO" + "$ref": "#/components/schemas/UpdateByoPhoneNumberDTO", + "title": "ByoPhoneNumber" + }, + { + "$ref": "#/components/schemas/UpdateTwilioPhoneNumberDTO", + "title": "TwilioPhoneNumber" + }, + { + "$ref": "#/components/schemas/UpdateVonagePhoneNumberDTO", + "title": "VonagePhoneNumber" + }, + { + "$ref": "#/components/schemas/UpdateVapiPhoneNumberDTO", + "title": "VapiPhoneNumber" }, { - "$ref": "#/components/schemas/UpdateCustomKnowledgeBaseDTO", - "title": "UpdateCustomKnowledgeBaseDTO" + "$ref": "#/components/schemas/UpdateTelnyxPhoneNumberDTO", + "title": "TelnyxPhoneNumber" } ], "discriminator": { "propertyName": "provider", "mapping": { - "trieve": "#/components/schemas/UpdateTrieveKnowledgeBaseDTO", - "custom-knowledge-base": "#/components/schemas/UpdateCustomKnowledgeBaseDTO" + "byo-phone-number": "#/components/schemas/UpdateByoPhoneNumberDTO", + "twilio": "#/components/schemas/UpdateTwilioPhoneNumberDTO", + "vonage": "#/components/schemas/UpdateVonagePhoneNumberDTO", + "vapi": "#/components/schemas/UpdateVapiPhoneNumberDTO", + "telnyx": "#/components/schemas/UpdateTelnyxPhoneNumberDTO" } } } @@ -3571,71 +3411,37 @@ "content": { "application/json": { "schema": { + "title": "PhoneNumber", "oneOf": [ { - "$ref": "#/components/schemas/TrieveKnowledgeBase", - "title": "TrieveKnowledgeBase" + "$ref": "#/components/schemas/ByoPhoneNumber", + "title": "ByoPhoneNumber" }, { - "$ref": "#/components/schemas/CustomKnowledgeBase", - "title": "CustomKnowledgeBase" - } - ], - "discriminator": { - "propertyName": "provider", - "mapping": { - "trieve": "#/components/schemas/TrieveKnowledgeBase", - "custom-knowledge-base": "#/components/schemas/CustomKnowledgeBase" - } - } - } - } - } - } - }, - "tags": [ - "Knowledge Base" - ], - "security": [ - { - "bearer": [] - } - ] - }, - "delete": { - "operationId": "KnowledgeBaseController_remove", - "summary": "Delete Knowledge Base", - "parameters": [ - { - "name": "id", - "required": true, - "in": "path", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "oneOf": [ + "$ref": "#/components/schemas/TwilioPhoneNumber", + "title": "TwilioPhoneNumber" + }, + { + "$ref": "#/components/schemas/VonagePhoneNumber", + "title": "VonagePhoneNumber" + }, { - "$ref": "#/components/schemas/TrieveKnowledgeBase", - "title": "TrieveKnowledgeBase" + "$ref": "#/components/schemas/VapiPhoneNumber", + "title": "VapiPhoneNumber" }, { - "$ref": "#/components/schemas/CustomKnowledgeBase", - "title": "CustomKnowledgeBase" + "$ref": "#/components/schemas/TelnyxPhoneNumber", + "title": "TelnyxPhoneNumber" } ], "discriminator": { "propertyName": "provider", "mapping": { - "trieve": "#/components/schemas/TrieveKnowledgeBase", - "custom-knowledge-base": "#/components/schemas/CustomKnowledgeBase" + "byo-phone-number": "#/components/schemas/ByoPhoneNumber", + "twilio": "#/components/schemas/TwilioPhoneNumber", + "vonage": "#/components/schemas/VonagePhoneNumber", + "vapi": "#/components/schemas/VapiPhoneNumber", + "telnyx": "#/components/schemas/TelnyxPhoneNumber" } } } @@ -3644,108 +3450,7 @@ } }, "tags": [ - "Knowledge Base" - ], - "security": [ - { - "bearer": [] - } - ] - } - }, - "/workflow": { - "get": { - "operationId": "WorkflowController_findAll", - "summary": "Get Workflows", - "parameters": [], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Workflow" - } - } - } - } - } - }, - "tags": [ - "Workflow" - ], - "security": [ - { - "bearer": [] - } - ] - }, - "post": { - "operationId": "WorkflowController_create", - "summary": "Create Workflow", - "parameters": [], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateWorkflowDTO" - } - } - } - }, - "responses": { - "201": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Workflow" - } - } - } - } - }, - "tags": [ - "Workflow" - ], - "security": [ - { - "bearer": [] - } - ] - } - }, - "/workflow/{id}": { - "get": { - "operationId": "WorkflowController_findOne", - "summary": "Get Workflow", - "parameters": [ - { - "name": "id", - "required": true, - "in": "path", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Workflow" - } - } - } - } - }, - "tags": [ - "Workflow" + "Phone Numbers" ], "security": [ { @@ -3754,76 +3459,66 @@ ] }, "delete": { - "operationId": "WorkflowController_delete", - "summary": "Delete Workflow", - "parameters": [ - { - "name": "id", - "required": true, - "in": "path", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Workflow" - } - } - } - } - }, - "tags": [ - "Workflow" - ], - "security": [ - { - "bearer": [] - } - ] - }, - "patch": { - "operationId": "WorkflowController_update", - "summary": "Update Workflow", + "operationId": "PhoneNumberController_remove", + "summary": "Delete Phone Number", "parameters": [ { "name": "id", "required": true, "in": "path", + "description": "The unique identifier for the resource.", "schema": { + "format": "uuid", "type": "string" } } ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateWorkflowDTO" - } - } - } - }, "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Workflow" + "title": "PhoneNumber", + "oneOf": [ + { + "$ref": "#/components/schemas/ByoPhoneNumber", + "title": "ByoPhoneNumber" + }, + { + "$ref": "#/components/schemas/TwilioPhoneNumber", + "title": "TwilioPhoneNumber" + }, + { + "$ref": "#/components/schemas/VonagePhoneNumber", + "title": "VonagePhoneNumber" + }, + { + "$ref": "#/components/schemas/VapiPhoneNumber", + "title": "VapiPhoneNumber" + }, + { + "$ref": "#/components/schemas/TelnyxPhoneNumber", + "title": "TelnyxPhoneNumber" + } + ], + "discriminator": { + "propertyName": "provider", + "mapping": { + "byo-phone-number": "#/components/schemas/ByoPhoneNumber", + "twilio": "#/components/schemas/TwilioPhoneNumber", + "vonage": "#/components/schemas/VonagePhoneNumber", + "vapi": "#/components/schemas/VapiPhoneNumber", + "telnyx": "#/components/schemas/TelnyxPhoneNumber" + } + } } } } } }, "tags": [ - "Workflow" + "Phone Numbers" ], "security": [ { @@ -3832,17 +3527,137 @@ ] } }, - "/squad": { + "/tool": { "post": { - "operationId": "SquadController_create", - "summary": "Create Squad", + "operationId": "ToolController_create", + "summary": "Create Tool", "parameters": [], "requestBody": { "required": true, "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateSquadDTO" + "oneOf": [ + { + "$ref": "#/components/schemas/CreateApiRequestToolDTO", + "title": "ApiRequestTool" + }, + { + "$ref": "#/components/schemas/CreateCodeToolDTO", + "title": "CodeTool" + }, + { + "$ref": "#/components/schemas/CreateDtmfToolDTO", + "title": "DtmfTool" + }, + { + "$ref": "#/components/schemas/CreateEndCallToolDTO", + "title": "EndCallTool" + }, + { + "$ref": "#/components/schemas/CreateFunctionToolDTO", + "title": "FunctionTool" + }, + { + "$ref": "#/components/schemas/CreateTransferCallToolDTO", + "title": "TransferCallTool" + }, + { + "$ref": "#/components/schemas/CreateHandoffToolDTO", + "title": "HandoffTool" + }, + { + "$ref": "#/components/schemas/CreateBashToolDTO", + "title": "BashTool" + }, + { + "$ref": "#/components/schemas/CreateComputerToolDTO", + "title": "ComputerTool" + }, + { + "$ref": "#/components/schemas/CreateTextEditorToolDTO", + "title": "TextEditorTool" + }, + { + "$ref": "#/components/schemas/CreateQueryToolDTO", + "title": "QueryTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarCreateEventToolDTO", + "title": "GoogleCalendarCreateEventTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleSheetsRowAppendToolDTO", + "title": "GoogleSheetsRowAppendTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarCheckAvailabilityToolDTO", + "title": "GoogleCalendarCheckAvailabilityTool" + }, + { + "$ref": "#/components/schemas/CreateSlackSendMessageToolDTO", + "title": "SlackSendMessageTool" + }, + { + "$ref": "#/components/schemas/CreateSmsToolDTO", + "title": "SmsSendTool" + }, + { + "$ref": "#/components/schemas/CreateMcpToolDTO", + "title": "McpTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelCalendarAvailabilityToolDTO", + "title": "GoHighLevelCalendarAvailabilityTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelCalendarEventCreateToolDTO", + "title": "GoHighLevelCalendarEventCreateTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelContactCreateToolDTO", + "title": "GoHighLevelContactCreateTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelContactGetToolDTO", + "title": "GoHighLevelContactGetTool" + }, + { + "$ref": "#/components/schemas/CreateSipRequestToolDTO", + "title": "SipRequestTool" + }, + { + "$ref": "#/components/schemas/CreateVoicemailToolDTO", + "title": "VoicemailTool" + } + ], + "discriminator": { + "propertyName": "type", + "mapping": { + "apiRequest": "#/components/schemas/CreateApiRequestToolDTO", + "dtmf": "#/components/schemas/CreateDtmfToolDTO", + "endCall": "#/components/schemas/CreateEndCallToolDTO", + "function": "#/components/schemas/CreateFunctionToolDTO", + "transferCall": "#/components/schemas/CreateTransferCallToolDTO", + "handoff": "#/components/schemas/CreateHandoffToolDTO", + "bash": "#/components/schemas/CreateBashToolDTO", + "computer": "#/components/schemas/CreateComputerToolDTO", + "textEditor": "#/components/schemas/CreateTextEditorToolDTO", + "query": "#/components/schemas/CreateQueryToolDTO", + "google.calendar.event.create": "#/components/schemas/CreateGoogleCalendarCreateEventToolDTO", + "google.sheets.row.append": "#/components/schemas/CreateGoogleSheetsRowAppendToolDTO", + "google.calendar.availability.check": "#/components/schemas/CreateGoogleCalendarCheckAvailabilityToolDTO", + "slack.message.send": "#/components/schemas/CreateSlackSendMessageToolDTO", + "sms": "#/components/schemas/CreateSmsToolDTO", + "mcp": "#/components/schemas/CreateMcpToolDTO", + "gohighlevel.calendar.availability.check": "#/components/schemas/CreateGoHighLevelCalendarAvailabilityToolDTO", + "gohighlevel.calendar.event.create": "#/components/schemas/CreateGoHighLevelCalendarEventCreateToolDTO", + "gohighlevel.contact.create": "#/components/schemas/CreateGoHighLevelContactCreateToolDTO", + "gohighlevel.contact.get": "#/components/schemas/CreateGoHighLevelContactGetToolDTO", + "sipRequest": "#/components/schemas/CreateSipRequestToolDTO", + "voicemail": "#/components/schemas/CreateVoicemailToolDTO" + } + } } } } @@ -3853,14 +3668,144 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Squad" + "oneOf": [ + { + "$ref": "#/components/schemas/ApiRequestTool", + "title": "ApiRequestTool" + }, + { + "$ref": "#/components/schemas/CodeTool", + "title": "CodeTool" + }, + { + "$ref": "#/components/schemas/DtmfTool", + "title": "DtmfTool" + }, + { + "$ref": "#/components/schemas/EndCallTool", + "title": "EndCallTool" + }, + { + "$ref": "#/components/schemas/FunctionTool", + "title": "FunctionTool" + }, + { + "$ref": "#/components/schemas/KnowledgeBaseTool", + "title": "KnowledgeBaseTool" + }, + { + "$ref": "#/components/schemas/GhlTool", + "title": "GhlTool" + }, + { + "$ref": "#/components/schemas/TransferCallTool", + "title": "TransferCallTool" + }, + { + "$ref": "#/components/schemas/HandoffTool", + "title": "HandoffTool" + }, + { + "$ref": "#/components/schemas/BashTool", + "title": "BashTool" + }, + { + "$ref": "#/components/schemas/ComputerTool", + "title": "ComputerTool" + }, + { + "$ref": "#/components/schemas/TextEditorTool", + "title": "TextEditorTool" + }, + { + "$ref": "#/components/schemas/QueryTool", + "title": "QueryTool" + }, + { + "$ref": "#/components/schemas/GoogleCalendarCreateEventTool", + "title": "GoogleCalendarCreateEventTool" + }, + { + "$ref": "#/components/schemas/GoogleSheetsRowAppendTool", + "title": "GoogleSheetsRowAppendTool" + }, + { + "$ref": "#/components/schemas/GoogleCalendarCheckAvailabilityTool", + "title": "GoogleCalendarCheckAvailabilityTool" + }, + { + "$ref": "#/components/schemas/SlackSendMessageTool", + "title": "SlackSendMessageTool" + }, + { + "$ref": "#/components/schemas/SmsTool", + "title": "SmsSendTool" + }, + { + "$ref": "#/components/schemas/McpTool", + "title": "McpTool" + }, + { + "$ref": "#/components/schemas/GoHighLevelCalendarAvailabilityTool", + "title": "GoHighLevelCalendarAvailabilityTool" + }, + { + "$ref": "#/components/schemas/GoHighLevelCalendarEventCreateTool", + "title": "GoHighLevelCalendarEventCreateTool" + }, + { + "$ref": "#/components/schemas/GoHighLevelContactCreateTool", + "title": "GoHighLevelContactCreateTool" + }, + { + "$ref": "#/components/schemas/GoHighLevelContactGetTool", + "title": "GoHighLevelContactGetTool" + }, + { + "$ref": "#/components/schemas/SipRequestTool", + "title": "SipRequestTool" + }, + { + "$ref": "#/components/schemas/VoicemailTool", + "title": "VoicemailTool" + } + ], + "discriminator": { + "propertyName": "type", + "mapping": { + "apiRequest": "#/components/schemas/ApiRequestTool", + "code": "#/components/schemas/CodeTool", + "dtmf": "#/components/schemas/DtmfTool", + "endCall": "#/components/schemas/EndCallTool", + "function": "#/components/schemas/FunctionTool", + "knowledgeBase": "#/components/schemas/KnowledgeBaseTool", + "transferCall": "#/components/schemas/TransferCallTool", + "handoff": "#/components/schemas/HandoffTool", + "bash": "#/components/schemas/BashTool", + "computer": "#/components/schemas/ComputerTool", + "textEditor": "#/components/schemas/TextEditorTool", + "query": "#/components/schemas/QueryTool", + "google.calendar.event.create": "#/components/schemas/GoogleCalendarCreateEventTool", + "google.sheets.row.append": "#/components/schemas/GoogleSheetsRowAppendTool", + "google.calendar.availability.check": "#/components/schemas/GoogleCalendarCheckAvailabilityTool", + "slack.message.send": "#/components/schemas/SlackSendMessageTool", + "sms": "#/components/schemas/SmsTool", + "mcp": "#/components/schemas/McpTool", + "gohighlevel.calendar.availability.check": "#/components/schemas/GoHighLevelCalendarAvailabilityTool", + "gohighlevel.calendar.event.create": "#/components/schemas/GoHighLevelCalendarEventCreateTool", + "gohighlevel.contact.create": "#/components/schemas/GoHighLevelContactCreateTool", + "gohighlevel.contact.get": "#/components/schemas/GoHighLevelContactGetTool", + "sipRequest": "#/components/schemas/SipRequestTool", + "voicemail": "#/components/schemas/VoicemailTool" + } + } } } } } }, "tags": [ - "Squads" + "Tools" ], "security": [ { @@ -3869,8 +3814,8 @@ ] }, "get": { - "operationId": "SquadController_findAll", - "summary": "List Squads", + "operationId": "ToolController_findAll", + "summary": "List Tools", "parameters": [ { "name": "limit", @@ -3972,306 +3917,145 @@ "schema": { "type": "array", "items": { - "$ref": "#/components/schemas/Squad" - } - } - } - } - } - }, - "tags": [ - "Squads" - ], - "security": [ - { - "bearer": [] - } - ] - } - }, - "/squad/{id}": { - "get": { - "operationId": "SquadController_findOne", - "summary": "Get Squad", - "parameters": [ - { - "name": "id", - "required": true, - "in": "path", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Squad" - } - } - } - } - }, - "tags": [ - "Squads" - ], - "security": [ - { - "bearer": [] - } - ] - }, - "patch": { - "operationId": "SquadController_update", - "summary": "Update Squad", - "parameters": [ - { - "name": "id", - "required": true, - "in": "path", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateSquadDTO" - } - } - } - }, - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Squad" - } - } - } - } - }, - "tags": [ - "Squads" - ], - "security": [ - { - "bearer": [] - } - ] - }, - "delete": { - "operationId": "SquadController_remove", - "summary": "Delete Squad", - "parameters": [ - { - "name": "id", - "required": true, - "in": "path", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Squad" - } - } - } - } - }, - "tags": [ - "Squads" - ], - "security": [ - { - "bearer": [] - } - ] - } - }, - "/test-suite": { - "get": { - "operationId": "TestSuiteController_findAllPaginated", - "summary": "List Test Suites", - "parameters": [ - { - "name": "page", - "required": false, - "in": "query", - "description": "This is the page number to return. Defaults to 1.", - "schema": { - "minimum": 1, - "type": "number" - } - }, - { - "name": "sortOrder", - "required": false, - "in": "query", - "description": "This is the sort order for pagination. Defaults to 'DESC'.", - "schema": { - "enum": [ - "ASC", - "DESC" - ], - "type": "string" - } - }, - { - "name": "limit", - "required": false, - "in": "query", - "description": "This is the maximum number of items to return. Defaults to 100.", - "schema": { - "minimum": 0, - "maximum": 1000, - "type": "number" - } - }, - { - "name": "createdAtGt", - "required": false, - "in": "query", - "description": "This will return items where the createdAt is greater than the specified value.", - "schema": { - "format": "date-time", - "type": "string" - } - }, - { - "name": "createdAtLt", - "required": false, - "in": "query", - "description": "This will return items where the createdAt is less than the specified value.", - "schema": { - "format": "date-time", - "type": "string" - } - }, - { - "name": "createdAtGe", - "required": false, - "in": "query", - "description": "This will return items where the createdAt is greater than or equal to the specified value.", - "schema": { - "format": "date-time", - "type": "string" - } - }, - { - "name": "createdAtLe", - "required": false, - "in": "query", - "description": "This will return items where the createdAt is less than or equal to the specified value.", - "schema": { - "format": "date-time", - "type": "string" - } - }, - { - "name": "updatedAtGt", - "required": false, - "in": "query", - "description": "This will return items where the updatedAt is greater than the specified value.", - "schema": { - "format": "date-time", - "type": "string" - } - }, - { - "name": "updatedAtLt", - "required": false, - "in": "query", - "description": "This will return items where the updatedAt is less than the specified value.", - "schema": { - "format": "date-time", - "type": "string" - } - }, - { - "name": "updatedAtGe", - "required": false, - "in": "query", - "description": "This will return items where the updatedAt is greater than or equal to the specified value.", - "schema": { - "format": "date-time", - "type": "string" - } - }, - { - "name": "updatedAtLe", - "required": false, - "in": "query", - "description": "This will return items where the updatedAt is less than or equal to the specified value.", - "schema": { - "format": "date-time", - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TestSuitesPaginatedResponse" - } - } - } - } - }, - "tags": [ - "Test Suites" - ], - "security": [ - { - "bearer": [] - } - ] - }, - "post": { - "operationId": "TestSuiteController_create", - "summary": "Create Test Suite", - "parameters": [], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateTestSuiteDto" - } - } - } - }, - "responses": { - "201": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TestSuite" + "oneOf": [ + { + "$ref": "#/components/schemas/ApiRequestTool", + "title": "ApiRequestTool" + }, + { + "$ref": "#/components/schemas/CodeTool", + "title": "CodeTool" + }, + { + "$ref": "#/components/schemas/DtmfTool", + "title": "DtmfTool" + }, + { + "$ref": "#/components/schemas/EndCallTool", + "title": "EndCallTool" + }, + { + "$ref": "#/components/schemas/FunctionTool", + "title": "FunctionTool" + }, + { + "$ref": "#/components/schemas/KnowledgeBaseTool", + "title": "KnowledgeBaseTool" + }, + { + "$ref": "#/components/schemas/GhlTool", + "title": "GhlTool" + }, + { + "$ref": "#/components/schemas/TransferCallTool", + "title": "TransferCallTool" + }, + { + "$ref": "#/components/schemas/HandoffTool", + "title": "HandoffTool" + }, + { + "$ref": "#/components/schemas/BashTool", + "title": "BashTool" + }, + { + "$ref": "#/components/schemas/ComputerTool", + "title": "ComputerTool" + }, + { + "$ref": "#/components/schemas/TextEditorTool", + "title": "TextEditorTool" + }, + { + "$ref": "#/components/schemas/QueryTool", + "title": "QueryTool" + }, + { + "$ref": "#/components/schemas/GoogleCalendarCreateEventTool", + "title": "GoogleCalendarCreateEventTool" + }, + { + "$ref": "#/components/schemas/GoogleSheetsRowAppendTool", + "title": "GoogleSheetsRowAppendTool" + }, + { + "$ref": "#/components/schemas/GoogleCalendarCheckAvailabilityTool", + "title": "GoogleCalendarCheckAvailabilityTool" + }, + { + "$ref": "#/components/schemas/SlackSendMessageTool", + "title": "SlackSendMessageTool" + }, + { + "$ref": "#/components/schemas/SmsTool", + "title": "SmsSendTool" + }, + { + "$ref": "#/components/schemas/McpTool", + "title": "McpTool" + }, + { + "$ref": "#/components/schemas/GoHighLevelCalendarAvailabilityTool", + "title": "GoHighLevelCalendarAvailabilityTool" + }, + { + "$ref": "#/components/schemas/GoHighLevelCalendarEventCreateTool", + "title": "GoHighLevelCalendarEventCreateTool" + }, + { + "$ref": "#/components/schemas/GoHighLevelContactCreateTool", + "title": "GoHighLevelContactCreateTool" + }, + { + "$ref": "#/components/schemas/GoHighLevelContactGetTool", + "title": "GoHighLevelContactGetTool" + }, + { + "$ref": "#/components/schemas/SipRequestTool", + "title": "SipRequestTool" + }, + { + "$ref": "#/components/schemas/VoicemailTool", + "title": "VoicemailTool" + } + ], + "discriminator": { + "propertyName": "type", + "mapping": { + "apiRequest": "#/components/schemas/ApiRequestTool", + "code": "#/components/schemas/CodeTool", + "dtmf": "#/components/schemas/DtmfTool", + "endCall": "#/components/schemas/EndCallTool", + "function": "#/components/schemas/FunctionTool", + "knowledgeBase": "#/components/schemas/KnowledgeBaseTool", + "transferCall": "#/components/schemas/TransferCallTool", + "handoff": "#/components/schemas/HandoffTool", + "bash": "#/components/schemas/BashTool", + "computer": "#/components/schemas/ComputerTool", + "textEditor": "#/components/schemas/TextEditorTool", + "query": "#/components/schemas/QueryTool", + "google.calendar.event.create": "#/components/schemas/GoogleCalendarCreateEventTool", + "google.sheets.row.append": "#/components/schemas/GoogleSheetsRowAppendTool", + "google.calendar.availability.check": "#/components/schemas/GoogleCalendarCheckAvailabilityTool", + "slack.message.send": "#/components/schemas/SlackSendMessageTool", + "sms": "#/components/schemas/SmsTool", + "mcp": "#/components/schemas/McpTool", + "gohighlevel.calendar.availability.check": "#/components/schemas/GoHighLevelCalendarAvailabilityTool", + "gohighlevel.calendar.event.create": "#/components/schemas/GoHighLevelCalendarEventCreateTool", + "gohighlevel.contact.create": "#/components/schemas/GoHighLevelContactCreateTool", + "gohighlevel.contact.get": "#/components/schemas/GoHighLevelContactGetTool", + "sipRequest": "#/components/schemas/SipRequestTool", + "voicemail": "#/components/schemas/VoicemailTool" + } + } + } } } } } }, "tags": [ - "Test Suites" + "Tools" ], "security": [ { @@ -4280,16 +4064,18 @@ ] } }, - "/test-suite/{id}": { + "/tool/{id}": { "get": { - "operationId": "TestSuiteController_findOne", - "summary": "Get Test Suite", + "operationId": "ToolController_findOne", + "summary": "Get Tool", "parameters": [ { "name": "id", "required": true, "in": "path", + "description": "The unique identifier for the resource.", "schema": { + "format": "uuid", "type": "string" } } @@ -4300,14 +4086,144 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/TestSuite" + "oneOf": [ + { + "$ref": "#/components/schemas/ApiRequestTool", + "title": "ApiRequestTool" + }, + { + "$ref": "#/components/schemas/CodeTool", + "title": "CodeTool" + }, + { + "$ref": "#/components/schemas/DtmfTool", + "title": "DtmfTool" + }, + { + "$ref": "#/components/schemas/EndCallTool", + "title": "EndCallTool" + }, + { + "$ref": "#/components/schemas/FunctionTool", + "title": "FunctionTool" + }, + { + "$ref": "#/components/schemas/KnowledgeBaseTool", + "title": "KnowledgeBaseTool" + }, + { + "$ref": "#/components/schemas/GhlTool", + "title": "GhlTool" + }, + { + "$ref": "#/components/schemas/TransferCallTool", + "title": "TransferCallTool" + }, + { + "$ref": "#/components/schemas/HandoffTool", + "title": "HandoffTool" + }, + { + "$ref": "#/components/schemas/BashTool", + "title": "BashTool" + }, + { + "$ref": "#/components/schemas/ComputerTool", + "title": "ComputerTool" + }, + { + "$ref": "#/components/schemas/TextEditorTool", + "title": "TextEditorTool" + }, + { + "$ref": "#/components/schemas/QueryTool", + "title": "QueryTool" + }, + { + "$ref": "#/components/schemas/GoogleCalendarCreateEventTool", + "title": "GoogleCalendarCreateEventTool" + }, + { + "$ref": "#/components/schemas/GoogleSheetsRowAppendTool", + "title": "GoogleSheetsRowAppendTool" + }, + { + "$ref": "#/components/schemas/GoogleCalendarCheckAvailabilityTool", + "title": "GoogleCalendarCheckAvailabilityTool" + }, + { + "$ref": "#/components/schemas/SlackSendMessageTool", + "title": "SlackSendMessageTool" + }, + { + "$ref": "#/components/schemas/SmsTool", + "title": "SmsSendTool" + }, + { + "$ref": "#/components/schemas/McpTool", + "title": "McpTool" + }, + { + "$ref": "#/components/schemas/GoHighLevelCalendarAvailabilityTool", + "title": "GoHighLevelCalendarAvailabilityTool" + }, + { + "$ref": "#/components/schemas/GoHighLevelCalendarEventCreateTool", + "title": "GoHighLevelCalendarEventCreateTool" + }, + { + "$ref": "#/components/schemas/GoHighLevelContactCreateTool", + "title": "GoHighLevelContactCreateTool" + }, + { + "$ref": "#/components/schemas/GoHighLevelContactGetTool", + "title": "GoHighLevelContactGetTool" + }, + { + "$ref": "#/components/schemas/SipRequestTool", + "title": "SipRequestTool" + }, + { + "$ref": "#/components/schemas/VoicemailTool", + "title": "VoicemailTool" + } + ], + "discriminator": { + "propertyName": "type", + "mapping": { + "apiRequest": "#/components/schemas/ApiRequestTool", + "code": "#/components/schemas/CodeTool", + "dtmf": "#/components/schemas/DtmfTool", + "endCall": "#/components/schemas/EndCallTool", + "function": "#/components/schemas/FunctionTool", + "knowledgeBase": "#/components/schemas/KnowledgeBaseTool", + "transferCall": "#/components/schemas/TransferCallTool", + "handoff": "#/components/schemas/HandoffTool", + "bash": "#/components/schemas/BashTool", + "computer": "#/components/schemas/ComputerTool", + "textEditor": "#/components/schemas/TextEditorTool", + "query": "#/components/schemas/QueryTool", + "google.calendar.event.create": "#/components/schemas/GoogleCalendarCreateEventTool", + "google.sheets.row.append": "#/components/schemas/GoogleSheetsRowAppendTool", + "google.calendar.availability.check": "#/components/schemas/GoogleCalendarCheckAvailabilityTool", + "slack.message.send": "#/components/schemas/SlackSendMessageTool", + "sms": "#/components/schemas/SmsTool", + "mcp": "#/components/schemas/McpTool", + "gohighlevel.calendar.availability.check": "#/components/schemas/GoHighLevelCalendarAvailabilityTool", + "gohighlevel.calendar.event.create": "#/components/schemas/GoHighLevelCalendarEventCreateTool", + "gohighlevel.contact.create": "#/components/schemas/GoHighLevelContactCreateTool", + "gohighlevel.contact.get": "#/components/schemas/GoHighLevelContactGetTool", + "sipRequest": "#/components/schemas/SipRequestTool", + "voicemail": "#/components/schemas/VoicemailTool" + } + } } } } } }, "tags": [ - "Test Suites" + "Tools" ], "security": [ { @@ -4316,242 +4232,16 @@ ] }, "patch": { - "operationId": "TestSuiteController_update", - "summary": "Update Test Suite", + "operationId": "ToolController_update", + "summary": "Update Tool", "parameters": [ { "name": "id", "required": true, "in": "path", + "description": "The unique identifier for the resource.", "schema": { - "type": "string" - } - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateTestSuiteDto" - } - } - } - }, - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TestSuite" - } - } - } - } - }, - "tags": [ - "Test Suites" - ], - "security": [ - { - "bearer": [] - } - ] - }, - "delete": { - "operationId": "TestSuiteController_remove", - "summary": "Delete Test Suite", - "parameters": [ - { - "name": "id", - "required": true, - "in": "path", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TestSuite" - } - } - } - } - }, - "tags": [ - "Test Suites" - ], - "security": [ - { - "bearer": [] - } - ] - } - }, - "/test-suite/{testSuiteId}/test": { - "get": { - "operationId": "TestSuiteTestController_findAllPaginated", - "summary": "List Tests", - "parameters": [ - { - "name": "testSuiteId", - "required": true, - "in": "path", - "schema": { - "type": "string" - } - }, - { - "name": "page", - "required": false, - "in": "query", - "description": "This is the page number to return. Defaults to 1.", - "schema": { - "minimum": 1, - "type": "number" - } - }, - { - "name": "sortOrder", - "required": false, - "in": "query", - "description": "This is the sort order for pagination. Defaults to 'DESC'.", - "schema": { - "enum": [ - "ASC", - "DESC" - ], - "type": "string" - } - }, - { - "name": "limit", - "required": false, - "in": "query", - "description": "This is the maximum number of items to return. Defaults to 100.", - "schema": { - "minimum": 0, - "maximum": 1000, - "type": "number" - } - }, - { - "name": "createdAtGt", - "required": false, - "in": "query", - "description": "This will return items where the createdAt is greater than the specified value.", - "schema": { - "format": "date-time", - "type": "string" - } - }, - { - "name": "createdAtLt", - "required": false, - "in": "query", - "description": "This will return items where the createdAt is less than the specified value.", - "schema": { - "format": "date-time", - "type": "string" - } - }, - { - "name": "createdAtGe", - "required": false, - "in": "query", - "description": "This will return items where the createdAt is greater than or equal to the specified value.", - "schema": { - "format": "date-time", - "type": "string" - } - }, - { - "name": "createdAtLe", - "required": false, - "in": "query", - "description": "This will return items where the createdAt is less than or equal to the specified value.", - "schema": { - "format": "date-time", - "type": "string" - } - }, - { - "name": "updatedAtGt", - "required": false, - "in": "query", - "description": "This will return items where the updatedAt is greater than the specified value.", - "schema": { - "format": "date-time", - "type": "string" - } - }, - { - "name": "updatedAtLt", - "required": false, - "in": "query", - "description": "This will return items where the updatedAt is less than the specified value.", - "schema": { - "format": "date-time", - "type": "string" - } - }, - { - "name": "updatedAtGe", - "required": false, - "in": "query", - "description": "This will return items where the updatedAt is greater than or equal to the specified value.", - "schema": { - "format": "date-time", - "type": "string" - } - }, - { - "name": "updatedAtLe", - "required": false, - "in": "query", - "description": "This will return items where the updatedAt is less than or equal to the specified value.", - "schema": { - "format": "date-time", - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TestSuiteTestsPaginatedResponse" - } - } - } - } - }, - "tags": [ - "Test Suite Tests" - ], - "security": [ - { - "bearer": [] - } - ] - }, - "post": { - "operationId": "TestSuiteTestController_create", - "summary": "Create Test", - "parameters": [ - { - "name": "testSuiteId", - "required": true, - "in": "path", - "schema": { + "format": "uuid", "type": "string" } } @@ -4563,19 +4253,128 @@ "schema": { "oneOf": [ { - "$ref": "#/components/schemas/CreateTestSuiteTestVoiceDto", - "title": "TestSuiteTestVoice" + "$ref": "#/components/schemas/UpdateApiRequestToolDTO", + "title": "ApiRequestTool" + }, + { + "$ref": "#/components/schemas/UpdateCodeToolDTO", + "title": "CodeTool" + }, + { + "$ref": "#/components/schemas/UpdateDtmfToolDTO", + "title": "DtmfTool" + }, + { + "$ref": "#/components/schemas/UpdateEndCallToolDTO", + "title": "EndCallTool" + }, + { + "$ref": "#/components/schemas/UpdateFunctionToolDTO", + "title": "FunctionTool" + }, + { + "$ref": "#/components/schemas/UpdateKnowledgeBaseToolDTO", + "title": "KnowledgeBaseTool" + }, + { + "$ref": "#/components/schemas/UpdateTransferCallToolDTO", + "title": "TransferCallTool" + }, + { + "$ref": "#/components/schemas/UpdateHandoffToolDTO", + "title": "HandoffTool" + }, + { + "$ref": "#/components/schemas/UpdateBashToolDTO", + "title": "BashTool" + }, + { + "$ref": "#/components/schemas/UpdateComputerToolDTO", + "title": "ComputerTool" + }, + { + "$ref": "#/components/schemas/UpdateTextEditorToolDTO", + "title": "TextEditorTool" + }, + { + "$ref": "#/components/schemas/UpdateQueryToolDTO", + "title": "QueryTool" + }, + { + "$ref": "#/components/schemas/UpdateGoogleCalendarCreateEventToolDTO", + "title": "GoogleCalendarCreateEventTool" + }, + { + "$ref": "#/components/schemas/UpdateGoogleSheetsRowAppendToolDTO", + "title": "GoogleSheetsRowAppendTool" + }, + { + "$ref": "#/components/schemas/UpdateGoogleCalendarCheckAvailabilityToolDTO", + "title": "GoogleCalendarCheckAvailabilityTool" + }, + { + "$ref": "#/components/schemas/UpdateSlackSendMessageToolDTO", + "title": "SlackSendMessageTool" + }, + { + "$ref": "#/components/schemas/UpdateSmsToolDTO", + "title": "SmsSendTool" + }, + { + "$ref": "#/components/schemas/UpdateMcpToolDTO", + "title": "McpTool" + }, + { + "$ref": "#/components/schemas/UpdateGoHighLevelCalendarAvailabilityToolDTO", + "title": "GoHighLevelCalendarAvailabilityTool" + }, + { + "$ref": "#/components/schemas/UpdateGoHighLevelCalendarEventCreateToolDTO", + "title": "GoHighLevelCalendarEventCreateTool" + }, + { + "$ref": "#/components/schemas/UpdateGoHighLevelContactCreateToolDTO", + "title": "GoHighLevelContactCreateTool" + }, + { + "$ref": "#/components/schemas/UpdateGoHighLevelContactGetToolDTO", + "title": "GoHighLevelContactGetTool" + }, + { + "$ref": "#/components/schemas/UpdateSipRequestToolDTO", + "title": "SipRequestTool" }, { - "$ref": "#/components/schemas/CreateTestSuiteTestChatDto", - "title": "TestSuiteTestChat" + "$ref": "#/components/schemas/UpdateVoicemailToolDTO", + "title": "VoicemailTool" } ], "discriminator": { "propertyName": "type", "mapping": { - "voice": "#/components/schemas/CreateTestSuiteTestVoiceDto", - "chat": "#/components/schemas/CreateTestSuiteTestChatDto" + "apiRequest": "#/components/schemas/UpdateApiRequestToolDTO", + "dtmf": "#/components/schemas/UpdateDtmfToolDTO", + "endCall": "#/components/schemas/UpdateEndCallToolDTO", + "function": "#/components/schemas/UpdateFunctionToolDTO", + "knowledgeBase": "#/components/schemas/UpdateKnowledgeBaseToolDTO", + "transferCall": "#/components/schemas/UpdateTransferCallToolDTO", + "handoff": "#/components/schemas/UpdateHandoffToolDTO", + "bash": "#/components/schemas/UpdateBashToolDTO", + "computer": "#/components/schemas/UpdateComputerToolDTO", + "textEditor": "#/components/schemas/UpdateTextEditorToolDTO", + "query": "#/components/schemas/UpdateQueryToolDTO", + "google.calendar.event.create": "#/components/schemas/UpdateGoogleCalendarCreateEventToolDTO", + "google.sheets.row.append": "#/components/schemas/UpdateGoogleSheetsRowAppendToolDTO", + "google.calendar.availability.check": "#/components/schemas/UpdateGoogleCalendarCheckAvailabilityToolDTO", + "slack.message.send": "#/components/schemas/UpdateSlackSendMessageToolDTO", + "sms": "#/components/schemas/UpdateSmsToolDTO", + "mcp": "#/components/schemas/UpdateMcpToolDTO", + "gohighlevel.calendar.availability.check": "#/components/schemas/UpdateGoHighLevelCalendarAvailabilityToolDTO", + "gohighlevel.calendar.event.create": "#/components/schemas/UpdateGoHighLevelCalendarEventCreateToolDTO", + "gohighlevel.contact.create": "#/components/schemas/UpdateGoHighLevelContactCreateToolDTO", + "gohighlevel.contact.get": "#/components/schemas/UpdateGoHighLevelContactGetToolDTO", + "sipRequest": "#/components/schemas/UpdateSipRequestToolDTO", + "voicemail": "#/components/schemas/UpdateVoicemailToolDTO" } } } @@ -4583,26 +4382,140 @@ } }, "responses": { - "201": { + "200": { "description": "", "content": { "application/json": { "schema": { "oneOf": [ { - "$ref": "#/components/schemas/TestSuiteTestVoice", - "title": "Voice" + "$ref": "#/components/schemas/ApiRequestTool", + "title": "ApiRequestTool" + }, + { + "$ref": "#/components/schemas/CodeTool", + "title": "CodeTool" + }, + { + "$ref": "#/components/schemas/DtmfTool", + "title": "DtmfTool" + }, + { + "$ref": "#/components/schemas/EndCallTool", + "title": "EndCallTool" + }, + { + "$ref": "#/components/schemas/FunctionTool", + "title": "FunctionTool" + }, + { + "$ref": "#/components/schemas/KnowledgeBaseTool", + "title": "KnowledgeBaseTool" + }, + { + "$ref": "#/components/schemas/GhlTool", + "title": "GhlTool" + }, + { + "$ref": "#/components/schemas/TransferCallTool", + "title": "TransferCallTool" + }, + { + "$ref": "#/components/schemas/HandoffTool", + "title": "HandoffTool" + }, + { + "$ref": "#/components/schemas/BashTool", + "title": "BashTool" + }, + { + "$ref": "#/components/schemas/ComputerTool", + "title": "ComputerTool" + }, + { + "$ref": "#/components/schemas/TextEditorTool", + "title": "TextEditorTool" + }, + { + "$ref": "#/components/schemas/QueryTool", + "title": "QueryTool" + }, + { + "$ref": "#/components/schemas/GoogleCalendarCreateEventTool", + "title": "GoogleCalendarCreateEventTool" + }, + { + "$ref": "#/components/schemas/GoogleSheetsRowAppendTool", + "title": "GoogleSheetsRowAppendTool" + }, + { + "$ref": "#/components/schemas/GoogleCalendarCheckAvailabilityTool", + "title": "GoogleCalendarCheckAvailabilityTool" + }, + { + "$ref": "#/components/schemas/SlackSendMessageTool", + "title": "SlackSendMessageTool" + }, + { + "$ref": "#/components/schemas/SmsTool", + "title": "SmsSendTool" + }, + { + "$ref": "#/components/schemas/McpTool", + "title": "McpTool" + }, + { + "$ref": "#/components/schemas/GoHighLevelCalendarAvailabilityTool", + "title": "GoHighLevelCalendarAvailabilityTool" + }, + { + "$ref": "#/components/schemas/GoHighLevelCalendarEventCreateTool", + "title": "GoHighLevelCalendarEventCreateTool" + }, + { + "$ref": "#/components/schemas/GoHighLevelContactCreateTool", + "title": "GoHighLevelContactCreateTool" + }, + { + "$ref": "#/components/schemas/GoHighLevelContactGetTool", + "title": "GoHighLevelContactGetTool" + }, + { + "$ref": "#/components/schemas/SipRequestTool", + "title": "SipRequestTool" }, { - "$ref": "#/components/schemas/TestSuiteTestChat", - "title": "Chat" + "$ref": "#/components/schemas/VoicemailTool", + "title": "VoicemailTool" } ], "discriminator": { "propertyName": "type", "mapping": { - "voice": "#/components/schemas/TestSuiteTestVoice", - "chat": "#/components/schemas/TestSuiteTestChat" + "apiRequest": "#/components/schemas/ApiRequestTool", + "code": "#/components/schemas/CodeTool", + "dtmf": "#/components/schemas/DtmfTool", + "endCall": "#/components/schemas/EndCallTool", + "function": "#/components/schemas/FunctionTool", + "knowledgeBase": "#/components/schemas/KnowledgeBaseTool", + "transferCall": "#/components/schemas/TransferCallTool", + "handoff": "#/components/schemas/HandoffTool", + "bash": "#/components/schemas/BashTool", + "computer": "#/components/schemas/ComputerTool", + "textEditor": "#/components/schemas/TextEditorTool", + "query": "#/components/schemas/QueryTool", + "google.calendar.event.create": "#/components/schemas/GoogleCalendarCreateEventTool", + "google.sheets.row.append": "#/components/schemas/GoogleSheetsRowAppendTool", + "google.calendar.availability.check": "#/components/schemas/GoogleCalendarCheckAvailabilityTool", + "slack.message.send": "#/components/schemas/SlackSendMessageTool", + "sms": "#/components/schemas/SmsTool", + "mcp": "#/components/schemas/McpTool", + "gohighlevel.calendar.availability.check": "#/components/schemas/GoHighLevelCalendarAvailabilityTool", + "gohighlevel.calendar.event.create": "#/components/schemas/GoHighLevelCalendarEventCreateTool", + "gohighlevel.contact.create": "#/components/schemas/GoHighLevelContactCreateTool", + "gohighlevel.contact.get": "#/components/schemas/GoHighLevelContactGetTool", + "sipRequest": "#/components/schemas/SipRequestTool", + "voicemail": "#/components/schemas/VoicemailTool" } } } @@ -4611,33 +4524,25 @@ } }, "tags": [ - "Test Suite Tests" + "Tools" ], "security": [ { "bearer": [] } ] - } - }, - "/test-suite/{testSuiteId}/test/{id}": { - "get": { - "operationId": "TestSuiteTestController_findOne", - "summary": "Get Test", + }, + "delete": { + "operationId": "ToolController_remove", + "summary": "Delete Tool", "parameters": [ - { - "name": "testSuiteId", - "required": true, - "in": "path", - "schema": { - "type": "string" - } - }, { "name": "id", "required": true, "in": "path", + "description": "The unique identifier for the resource.", "schema": { + "format": "uuid", "type": "string" } } @@ -4650,52 +4555,285 @@ "schema": { "oneOf": [ { - "$ref": "#/components/schemas/TestSuiteTestVoice", - "title": "Voice" + "$ref": "#/components/schemas/ApiRequestTool", + "title": "ApiRequestTool" + }, + { + "$ref": "#/components/schemas/CodeTool", + "title": "CodeTool" + }, + { + "$ref": "#/components/schemas/DtmfTool", + "title": "DtmfTool" + }, + { + "$ref": "#/components/schemas/EndCallTool", + "title": "EndCallTool" + }, + { + "$ref": "#/components/schemas/FunctionTool", + "title": "FunctionTool" + }, + { + "$ref": "#/components/schemas/KnowledgeBaseTool", + "title": "KnowledgeBaseTool" + }, + { + "$ref": "#/components/schemas/GhlTool", + "title": "GhlTool" + }, + { + "$ref": "#/components/schemas/TransferCallTool", + "title": "TransferCallTool" + }, + { + "$ref": "#/components/schemas/HandoffTool", + "title": "HandoffTool" + }, + { + "$ref": "#/components/schemas/BashTool", + "title": "BashTool" + }, + { + "$ref": "#/components/schemas/ComputerTool", + "title": "ComputerTool" + }, + { + "$ref": "#/components/schemas/TextEditorTool", + "title": "TextEditorTool" + }, + { + "$ref": "#/components/schemas/QueryTool", + "title": "QueryTool" + }, + { + "$ref": "#/components/schemas/GoogleCalendarCreateEventTool", + "title": "GoogleCalendarCreateEventTool" + }, + { + "$ref": "#/components/schemas/GoogleSheetsRowAppendTool", + "title": "GoogleSheetsRowAppendTool" + }, + { + "$ref": "#/components/schemas/GoogleCalendarCheckAvailabilityTool", + "title": "GoogleCalendarCheckAvailabilityTool" + }, + { + "$ref": "#/components/schemas/SlackSendMessageTool", + "title": "SlackSendMessageTool" + }, + { + "$ref": "#/components/schemas/SmsTool", + "title": "SmsSendTool" + }, + { + "$ref": "#/components/schemas/McpTool", + "title": "McpTool" + }, + { + "$ref": "#/components/schemas/GoHighLevelCalendarAvailabilityTool", + "title": "GoHighLevelCalendarAvailabilityTool" + }, + { + "$ref": "#/components/schemas/GoHighLevelCalendarEventCreateTool", + "title": "GoHighLevelCalendarEventCreateTool" + }, + { + "$ref": "#/components/schemas/GoHighLevelContactCreateTool", + "title": "GoHighLevelContactCreateTool" + }, + { + "$ref": "#/components/schemas/GoHighLevelContactGetTool", + "title": "GoHighLevelContactGetTool" + }, + { + "$ref": "#/components/schemas/SipRequestTool", + "title": "SipRequestTool" }, { - "$ref": "#/components/schemas/TestSuiteTestChat", - "title": "Chat" + "$ref": "#/components/schemas/VoicemailTool", + "title": "VoicemailTool" } ], "discriminator": { "propertyName": "type", "mapping": { - "voice": "#/components/schemas/TestSuiteTestVoice", - "chat": "#/components/schemas/TestSuiteTestChat" + "apiRequest": "#/components/schemas/ApiRequestTool", + "code": "#/components/schemas/CodeTool", + "dtmf": "#/components/schemas/DtmfTool", + "endCall": "#/components/schemas/EndCallTool", + "function": "#/components/schemas/FunctionTool", + "knowledgeBase": "#/components/schemas/KnowledgeBaseTool", + "transferCall": "#/components/schemas/TransferCallTool", + "handoff": "#/components/schemas/HandoffTool", + "bash": "#/components/schemas/BashTool", + "computer": "#/components/schemas/ComputerTool", + "textEditor": "#/components/schemas/TextEditorTool", + "query": "#/components/schemas/QueryTool", + "google.calendar.event.create": "#/components/schemas/GoogleCalendarCreateEventTool", + "google.sheets.row.append": "#/components/schemas/GoogleSheetsRowAppendTool", + "google.calendar.availability.check": "#/components/schemas/GoogleCalendarCheckAvailabilityTool", + "slack.message.send": "#/components/schemas/SlackSendMessageTool", + "sms": "#/components/schemas/SmsTool", + "mcp": "#/components/schemas/McpTool", + "gohighlevel.calendar.availability.check": "#/components/schemas/GoHighLevelCalendarAvailabilityTool", + "gohighlevel.calendar.event.create": "#/components/schemas/GoHighLevelCalendarEventCreateTool", + "gohighlevel.contact.create": "#/components/schemas/GoHighLevelContactCreateTool", + "gohighlevel.contact.get": "#/components/schemas/GoHighLevelContactGetTool", + "sipRequest": "#/components/schemas/SipRequestTool", + "voicemail": "#/components/schemas/VoicemailTool" } } } } } + }, + "409": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ToolPinnedConflictResponseDTO" + } + } + } + } + }, + "tags": [ + "Tools" + ], + "security": [ + { + "bearer": [] + } + ] + } + }, + "/file": { + "post": { + "operationId": "FileController_create", + "summary": "Upload File", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "multipart/form-data": { + "schema": { + "$ref": "#/components/schemas/CreateFileDTO" + } + } + } + }, + "responses": { + "201": { + "description": "File uploaded successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/File" + } + } + } + }, + "400": { + "description": "Invalid file" + } + }, + "tags": [ + "Files" + ], + "security": [ + { + "bearer": [] } - }, - "tags": [ - "Test Suite Tests" - ], - "security": [ - { - "bearer": [] - } ] }, - "patch": { - "operationId": "TestSuiteTestController_update", - "summary": "Update Test", + "get": { + "operationId": "FileController_findAll", + "summary": "List Files", + "parameters": [ + { + "name": "purpose", + "required": true, + "in": "query", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/File" + } + } + } + } + } + }, + "tags": [ + "Files" + ], + "security": [ + { + "bearer": [] + } + ] + } + }, + "/file/{id}": { + "get": { + "operationId": "FileController_findOne", + "summary": "Get File", "parameters": [ { - "name": "testSuiteId", + "name": "id", "required": true, "in": "path", + "description": "The unique identifier for the resource.", "schema": { + "format": "uuid", "type": "string" } - }, + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/File" + } + } + } + } + }, + "tags": [ + "Files" + ], + "security": [ + { + "bearer": [] + } + ] + }, + "patch": { + "operationId": "FileController_update", + "summary": "Update File", + "parameters": [ { "name": "id", "required": true, "in": "path", + "description": "The unique identifier for the resource.", "schema": { + "format": "uuid", "type": "string" } } @@ -4705,23 +4843,7 @@ "content": { "application/json": { "schema": { - "oneOf": [ - { - "$ref": "#/components/schemas/UpdateTestSuiteTestVoiceDto", - "title": "TestSuiteTestVoice" - }, - { - "$ref": "#/components/schemas/UpdateTestSuiteTestChatDto", - "title": "TestSuiteTestChat" - } - ], - "discriminator": { - "propertyName": "type", - "mapping": { - "voice": "#/components/schemas/UpdateTestSuiteTestVoiceDto", - "chat": "#/components/schemas/UpdateTestSuiteTestChatDto" - } - } + "$ref": "#/components/schemas/UpdateFileDTO" } } } @@ -4732,30 +4854,14 @@ "content": { "application/json": { "schema": { - "oneOf": [ - { - "$ref": "#/components/schemas/TestSuiteTestVoice", - "title": "Voice" - }, - { - "$ref": "#/components/schemas/TestSuiteTestChat", - "title": "Chat" - } - ], - "discriminator": { - "propertyName": "type", - "mapping": { - "voice": "#/components/schemas/TestSuiteTestVoice", - "chat": "#/components/schemas/TestSuiteTestChat" - } - } + "$ref": "#/components/schemas/File" } } } } }, "tags": [ - "Test Suite Tests" + "Files" ], "security": [ { @@ -4764,22 +4870,16 @@ ] }, "delete": { - "operationId": "TestSuiteTestController_remove", - "summary": "Delete Test", + "operationId": "FileController_remove", + "summary": "Delete File", "parameters": [ - { - "name": "testSuiteId", - "required": true, - "in": "path", - "schema": { - "type": "string" - } - }, { "name": "id", "required": true, "in": "path", + "description": "The unique identifier for the resource.", "schema": { + "format": "uuid", "type": "string" } } @@ -4790,30 +4890,14 @@ "content": { "application/json": { "schema": { - "oneOf": [ - { - "$ref": "#/components/schemas/TestSuiteTestVoice", - "title": "Voice" - }, - { - "$ref": "#/components/schemas/TestSuiteTestChat", - "title": "Chat" - } - ], - "discriminator": { - "propertyName": "type", - "mapping": { - "voice": "#/components/schemas/TestSuiteTestVoice", - "chat": "#/components/schemas/TestSuiteTestChat" - } - } + "$ref": "#/components/schemas/File" } } } } }, "tags": [ - "Test Suite Tests" + "Files" ], "security": [ { @@ -4822,130 +4906,94 @@ ] } }, - "/test-suite/{testSuiteId}/run": { - "get": { - "operationId": "TestSuiteRunController_findAllPaginated", - "summary": "List Test Suite Runs", - "parameters": [ - { - "name": "testSuiteId", - "required": true, - "in": "path", - "schema": { - "type": "string" + "/v2/knowledge-base": { + "post": { + "operationId": "KnowledgeBaseV2Controller_create", + "summary": "Create a Knowledge Base V2", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateKnowledgeBaseV2DTO" + } } - }, - { - "name": "page", - "required": false, - "in": "query", - "description": "This is the page number to return. Defaults to 1.", - "schema": { - "minimum": 1, - "type": "number" + } + }, + "responses": { + "201": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/KnowledgeBaseV2" + } + } } - }, + } + }, + "tags": [ + "Knowledge Bases V2" + ], + "security": [ { - "name": "sortOrder", - "required": false, - "in": "query", - "description": "This is the sort order for pagination. Defaults to 'DESC'.", - "schema": { - "enum": [ - "ASC", - "DESC" - ], - "type": "string" - } - }, + "bearer": [] + } + ] + }, + "get": { + "operationId": "KnowledgeBaseV2Controller_findAll", + "summary": "List Knowledge Bases V2", + "parameters": [ { "name": "limit", "required": false, "in": "query", - "description": "This is the maximum number of items to return. Defaults to 100.", "schema": { "minimum": 0, "maximum": 1000, "type": "number" } - }, - { - "name": "createdAtGt", - "required": false, - "in": "query", - "description": "This will return items where the createdAt is greater than the specified value.", - "schema": { - "format": "date-time", - "type": "string" - } - }, - { - "name": "createdAtLt", - "required": false, - "in": "query", - "description": "This will return items where the createdAt is less than the specified value.", - "schema": { - "format": "date-time", - "type": "string" - } - }, - { - "name": "createdAtGe", - "required": false, - "in": "query", - "description": "This will return items where the createdAt is greater than or equal to the specified value.", - "schema": { - "format": "date-time", - "type": "string" - } - }, - { - "name": "createdAtLe", - "required": false, - "in": "query", - "description": "This will return items where the createdAt is less than or equal to the specified value.", - "schema": { - "format": "date-time", - "type": "string" - } - }, - { - "name": "updatedAtGt", - "required": false, - "in": "query", - "description": "This will return items where the updatedAt is greater than the specified value.", - "schema": { - "format": "date-time", - "type": "string" - } - }, - { - "name": "updatedAtLt", - "required": false, - "in": "query", - "description": "This will return items where the updatedAt is less than the specified value.", - "schema": { - "format": "date-time", - "type": "string" + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/KnowledgeBaseV2" + } + } + } } - }, + } + }, + "tags": [ + "Knowledge Bases V2" + ], + "security": [ { - "name": "updatedAtGe", - "required": false, - "in": "query", - "description": "This will return items where the updatedAt is greater than or equal to the specified value.", - "schema": { - "format": "date-time", - "type": "string" - } - }, + "bearer": [] + } + ] + } + }, + "/v2/knowledge-base/{id}/file": { + "get": { + "operationId": "KnowledgeBaseV2Controller_filesGet", + "summary": "List files in a Knowledge Base V2", + "parameters": [ { - "name": "updatedAtLe", - "required": false, - "in": "query", - "description": "This will return items where the updatedAt is less than or equal to the specified value.", + "name": "id", + "required": true, + "in": "path", + "description": "The unique identifier for the resource.", "schema": { - "format": "date-time", + "format": "uuid", "type": "string" } } @@ -4956,14 +5004,17 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/TestSuiteRunsPaginatedResponse" + "type": "array", + "items": { + "$ref": "#/components/schemas/KnowledgeBaseV2File" + } } } } } }, "tags": [ - "Test Suite Runs" + "Knowledge Bases V2" ], "security": [ { @@ -4972,14 +5023,16 @@ ] }, "post": { - "operationId": "TestSuiteRunController_create", - "summary": "Create Test Suite Run", + "operationId": "KnowledgeBaseV2Controller_fileAttach", + "summary": "Attach and ingest a file", "parameters": [ { - "name": "testSuiteId", + "name": "id", "required": true, "in": "path", + "description": "The unique identifier for the resource.", "schema": { + "format": "uuid", "type": "string" } } @@ -4989,7 +5042,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/CreateTestSuiteRunDto" + "$ref": "#/components/schemas/AttachKnowledgeBaseV2FileDTO" } } } @@ -5000,14 +5053,14 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/TestSuiteRun" + "$ref": "#/components/schemas/KnowledgeBaseV2File" } } } } }, "tags": [ - "Test Suite Runs" + "Knowledge Bases V2" ], "security": [ { @@ -5016,24 +5069,27 @@ ] } }, - "/test-suite/{testSuiteId}/run/{id}": { - "get": { - "operationId": "TestSuiteRunController_findOne", - "summary": "Get Test Suite Run", + "/v2/knowledge-base/{id}/file/{fileId}": { + "delete": { + "operationId": "KnowledgeBaseV2Controller_fileDetach", + "summary": "Detach a file", "parameters": [ { - "name": "testSuiteId", + "name": "id", "required": true, "in": "path", + "description": "The unique identifier for the resource.", "schema": { + "format": "uuid", "type": "string" } }, { - "name": "id", + "name": "fileId", "required": true, "in": "path", "schema": { + "format": "uuid", "type": "string" } } @@ -5044,38 +5100,81 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/TestSuiteRun" + "$ref": "#/components/schemas/KnowledgeBaseV2File" } } } } }, "tags": [ - "Test Suite Runs" + "Knowledge Bases V2" ], "security": [ { "bearer": [] } ] - }, - "patch": { - "operationId": "TestSuiteRunController_update", - "summary": "Update Test Suite Run", + } + }, + "/v2/knowledge-base/{id}/file/{fileId}/retry": { + "post": { + "operationId": "KnowledgeBaseV2Controller_fileRetry", + "summary": "Retry indexing a failed file", "parameters": [ { - "name": "testSuiteId", + "name": "id", "required": true, "in": "path", + "description": "The unique identifier for the resource.", "schema": { + "format": "uuid", "type": "string" } }, + { + "name": "fileId", + "required": true, + "in": "path", + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "201": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/KnowledgeBaseV2File" + } + } + } + } + }, + "tags": [ + "Knowledge Bases V2" + ], + "security": [ + { + "bearer": [] + } + ] + } + }, + "/v2/knowledge-base/{id}": { + "patch": { + "operationId": "KnowledgeBaseV2Controller_update", + "summary": "Update a Knowledge Base V2", + "parameters": [ { "name": "id", "required": true, "in": "path", + "description": "The unique identifier for the resource.", "schema": { + "format": "uuid", "type": "string" } } @@ -5085,7 +5184,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpdateTestSuiteRunDto" + "$ref": "#/components/schemas/UpdateKnowledgeBaseV2DTO" } } } @@ -5096,14 +5195,14 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/TestSuiteRun" + "$ref": "#/components/schemas/KnowledgeBaseV2" } } } } }, "tags": [ - "Test Suite Runs" + "Knowledge Bases V2" ], "security": [ { @@ -5111,23 +5210,17 @@ } ] }, - "delete": { - "operationId": "TestSuiteRunController_remove", - "summary": "Delete Test Suite Run", + "get": { + "operationId": "KnowledgeBaseV2Controller_findOne", + "summary": "Get a Knowledge Base V2", "parameters": [ - { - "name": "testSuiteId", - "required": true, - "in": "path", - "schema": { - "type": "string" - } - }, { "name": "id", "required": true, "in": "path", + "description": "The unique identifier for the resource.", "schema": { + "format": "uuid", "type": "string" } } @@ -5138,57 +5231,50 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/TestSuiteRun" + "$ref": "#/components/schemas/KnowledgeBaseV2WithFiles" } } } } }, "tags": [ - "Test Suite Runs" + "Knowledge Bases V2" ], "security": [ { "bearer": [] } ] - } - }, - "/analytics": { - "post": { - "operationId": "AnalyticsController_query", - "summary": "Create Analytics Queries", - "parameters": [], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/AnalyticsQueryDTO" - } + }, + "delete": { + "operationId": "KnowledgeBaseV2Controller_remove", + "summary": "Delete a Knowledge Base V2", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "description": "The unique identifier for the resource.", + "schema": { + "format": "uuid", + "type": "string" } } - }, + ], "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/AnalyticsQueryResult" - } + "$ref": "#/components/schemas/KnowledgeBaseV2" } } } - }, - "201": { - "description": "" } }, "tags": [ - "Analytics" + "Knowledge Bases V2" ], "security": [ { @@ -5197,77 +5283,25 @@ ] } }, - "/logs": { + "/structured-output": { "get": { - "operationId": "LoggingController_logsQuery", - "summary": "Get Logs", - "deprecated": true, + "operationId": "StructuredOutputController_findAll", + "summary": "List Structured Outputs", "parameters": [ { - "name": "type", - "required": false, - "in": "query", - "description": "This is the type of the log.", - "schema": { - "enum": [ - "API", - "Webhook", - "Call", - "Provider" - ], - "type": "string" - } - }, - { - "name": "webhookType", - "required": false, - "in": "query", - "description": "This is the type of the webhook, given the log is from a webhook.", - "schema": { - "type": "string" - } - }, - { - "name": "assistantId", - "required": false, - "in": "query", - "description": "This is the ID of the assistant.", - "schema": { - "type": "string" - } - }, - { - "name": "phoneNumberId", - "required": false, - "in": "query", - "description": "This is the ID of the phone number.", - "schema": { - "type": "string" - } - }, - { - "name": "customerId", - "required": false, - "in": "query", - "description": "This is the ID of the customer.", - "schema": { - "type": "string" - } - }, - { - "name": "squadId", + "name": "id", "required": false, "in": "query", - "description": "This is the ID of the squad.", + "description": "This will return structured outputs where the id matches the specified value.", "schema": { "type": "string" } }, { - "name": "callId", + "name": "name", "required": false, "in": "query", - "description": "This is the ID of the call.", + "description": "This will return structured outputs where the name matches the specified value.", "schema": { "type": "string" } @@ -5295,6 +5329,20 @@ "type": "string" } }, + { + "name": "sortBy", + "required": false, + "in": "query", + "description": "This is the column to sort by. Defaults to 'createdAt'.", + "schema": { + "enum": [ + "createdAt", + "duration", + "cost" + ], + "type": "string" + } + }, { "name": "limit", "required": false, @@ -5393,14 +5441,14 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/LogsPaginatedResponse" + "$ref": "#/components/schemas/StructuredOutputPaginatedResponse" } } } } }, "tags": [ - "Logs" + "Structured Outputs" ], "security": [ { @@ -5408,109 +5456,275 @@ } ] }, - "delete": { - "operationId": "LoggingController_logsDeleteQuery", - "summary": "Delete Logs", - "deprecated": true, - "parameters": [ - { - "name": "type", - "required": false, - "in": "query", - "description": "This is the type of the log.", - "schema": { - "enum": [ - "API", - "Webhook", - "Call", - "Provider" - ], - "type": "string" + "post": { + "operationId": "StructuredOutputController_create", + "summary": "Create Structured Output", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateStructuredOutputDTO" + } } - }, - { - "name": "assistantId", - "required": false, - "in": "query", - "schema": { - "type": "string" + } + }, + "responses": { + "201": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StructuredOutput" + } + } } - }, + } + }, + "tags": [ + "Structured Outputs" + ], + "security": [ { - "name": "phoneNumberId", - "required": false, - "in": "query", - "description": "This is the ID of the phone number.", - "schema": { - "type": "string" - } - }, + "bearer": [] + } + ] + } + }, + "/structured-output/{id}": { + "get": { + "operationId": "StructuredOutputController_findOne", + "summary": "Get Structured Output", + "parameters": [ { - "name": "customerId", - "required": false, - "in": "query", - "description": "This is the ID of the customer.", + "name": "id", + "required": true, + "in": "path", + "description": "The unique identifier for the resource.", "schema": { + "format": "uuid", "type": "string" } - }, + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StructuredOutput" + } + } + } + } + }, + "tags": [ + "Structured Outputs" + ], + "security": [ { - "name": "squadId", - "required": false, - "in": "query", - "description": "This is the ID of the squad.", + "bearer": [] + } + ] + }, + "patch": { + "operationId": "StructuredOutputController_update", + "summary": "Update Structured Output", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "description": "The unique identifier for the resource.", "schema": { + "format": "uuid", "type": "string" } }, { - "name": "callId", - "required": false, + "name": "schemaOverride", + "required": true, "in": "query", - "description": "This is the ID of the call.", "schema": { "type": "string" } } ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateStructuredOutputDTO" + } + } + } + }, "responses": { - "202": { - "description": "" + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StructuredOutput" + } + } + } } }, "tags": [ - "Logs" + "Structured Outputs" ], "security": [ { "bearer": [] } ] - } - }, - "/structured-output": { - "get": { - "operationId": "StructuredOutputController_findAll", - "summary": "List Structured Outputs", + }, + "delete": { + "operationId": "StructuredOutputController_remove", + "summary": "Delete Structured Output", "parameters": [ { "name": "id", - "required": false, - "in": "query", - "description": "This will return structured outputs where the id matches the specified value.", + "required": true, + "in": "path", + "description": "The unique identifier for the resource.", "schema": { + "format": "uuid", "type": "string" } - }, + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StructuredOutput" + } + } + } + } + }, + "tags": [ + "Structured Outputs" + ], + "security": [ { - "name": "name", - "required": false, - "in": "query", - "description": "This will return structured outputs where the name matches the specified value.", - "schema": { - "type": "string" + "bearer": [] + } + ] + } + }, + "/structured-output/run": { + "post": { + "operationId": "StructuredOutputController_run", + "summary": "Run Structured Output", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StructuredOutputRunDTO" + } + } + } + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "oneOf": [ + { + "title": "StructuredOutputRunPreviewResponse", + "allOf": [ + { + "$ref": "#/components/schemas/StructuredOutputRunPreviewResponse" + }, + { + "additionalProperties": { + "$ref": "#/components/schemas/StructuredOutputRunResult" + } + } + ] + }, + { + "title": "StructuredOutputRerunResponse", + "$ref": "#/components/schemas/StructuredOutputRerunResponse" + } + ] + } + } } }, + "201": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object" + } + } + } + } + }, + "tags": [ + "Structured Outputs" + ], + "security": [ + { + "bearer": [] + } + ] + } + }, + "/eval/simulation/personality": { + "post": { + "operationId": "PersonalityController_create", + "summary": "Create Personality", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreatePersonalityDTO" + } + } + } + }, + "responses": { + "201": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Personality" + } + } + } + } + }, + "tags": [ + "Simulation Personalities" + ], + "security": [ + { + "bearer": [] + } + ] + }, + "get": { + "operationId": "PersonalityController_findAll", + "summary": "List Personalities", + "parameters": [ { "name": "page", "required": false, @@ -5534,6 +5748,20 @@ "type": "string" } }, + { + "name": "sortBy", + "required": false, + "in": "query", + "description": "This is the column to sort by. Defaults to 'createdAt'.", + "schema": { + "enum": [ + "createdAt", + "duration", + "cost" + ], + "type": "string" + } + }, { "name": "limit", "required": false, @@ -5632,49 +5860,17 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/StructuredOutputPaginatedResponse" - } - } - } - } - }, - "tags": [ - "Structured Outputs" - ], - "security": [ - { - "bearer": [] - } - ] - }, - "post": { - "operationId": "StructuredOutputController_create", - "summary": "Create Structured Output", - "parameters": [], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateStructuredOutputDTO" - } - } - } - }, - "responses": { - "201": { - "description": "", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/StructuredOutput" + "type": "array", + "items": { + "$ref": "#/components/schemas/Personality" + } } } } } }, "tags": [ - "Structured Outputs" + "Simulation Personalities" ], "security": [ { @@ -5683,16 +5879,18 @@ ] } }, - "/structured-output/{id}": { + "/eval/simulation/personality/{id}": { "get": { - "operationId": "StructuredOutputController_findOne", - "summary": "Get Structured Output", + "operationId": "PersonalityController_findOne", + "summary": "Get Personality", "parameters": [ { "name": "id", "required": true, "in": "path", + "description": "The unique identifier for the resource.", "schema": { + "format": "uuid", "type": "string" } } @@ -5703,14 +5901,14 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/StructuredOutput" + "$ref": "#/components/schemas/Personality" } } } } }, "tags": [ - "Structured Outputs" + "Simulation Personalities" ], "security": [ { @@ -5719,22 +5917,16 @@ ] }, "patch": { - "operationId": "StructuredOutputController_update", - "summary": "Update Structured Output", + "operationId": "PersonalityController_update", + "summary": "Update Personality", "parameters": [ { "name": "id", "required": true, "in": "path", + "description": "The unique identifier for the resource.", "schema": { - "type": "string" - } - }, - { - "name": "schemaOverride", - "required": true, - "in": "query", - "schema": { + "format": "uuid", "type": "string" } } @@ -5744,7 +5936,7 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/UpdateStructuredOutputDTO" + "$ref": "#/components/schemas/UpdatePersonalityDTO" } } } @@ -5755,14 +5947,14 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/StructuredOutput" + "$ref": "#/components/schemas/Personality" } } } } }, "tags": [ - "Structured Outputs" + "Simulation Personalities" ], "security": [ { @@ -5771,14 +5963,16 @@ ] }, "delete": { - "operationId": "StructuredOutputController_remove", - "summary": "Delete Structured Output", + "operationId": "PersonalityController_remove", + "summary": "Delete Personality", "parameters": [ { "name": "id", "required": true, "in": "path", + "description": "The unique identifier for the resource.", "schema": { + "format": "uuid", "type": "string" } } @@ -5789,14 +5983,14 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/StructuredOutput" + "$ref": "#/components/schemas/Personality" } } } } }, "tags": [ - "Structured Outputs" + "Simulation Personalities" ], "security": [ { @@ -5805,58 +5999,35 @@ ] } }, - "/provider/{provider}/{resourceName}": { + "/eval/simulation/scenario": { "post": { - "operationId": "ProviderResourceController_createProviderResource", - "summary": "Create Provider Resource", - "parameters": [ - { - "name": "content-type", - "required": true, - "in": "header", - "schema": { - "type": "string" - } - }, - { - "name": "provider", - "required": true, - "in": "path", - "description": "The provider (e.g., 11labs)", - "schema": { - "enum": [ - "11labs" - ], - "type": "string" - } - }, - { - "name": "resourceName", - "required": true, - "in": "path", - "description": "The resource name (e.g., pronunciation-dictionary)", - "schema": { - "enum": [ - "pronunciation-dictionary" - ], - "type": "string" + "operationId": "ScenarioController_create", + "summary": "Create Scenario", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateScenarioDTO" + } } } - ], + }, "responses": { "201": { - "description": "Successfully created provider resource", + "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ProviderResource" + "$ref": "#/components/schemas/Scenario" } } } } }, "tags": [ - "Provider Resources" + "Simulation Scenarios" ], "security": [ { @@ -5865,45 +6036,27 @@ ] }, "get": { - "operationId": "ProviderResourceController_getProviderResourcesPaginated", - "summary": "List Provider Resources", + "operationId": "ScenarioController_findAll", + "summary": "List Scenarios", "parameters": [ { - "name": "provider", - "required": true, - "in": "path", - "description": "The provider (e.g., 11labs)", - "schema": { - "enum": [ - "11labs" - ], - "type": "string" - } - }, - { - "name": "resourceName", - "required": true, - "in": "path", - "description": "The resource name (e.g., pronunciation-dictionary)", - "schema": { - "enum": [ - "pronunciation-dictionary" - ], - "type": "string" - } - }, - { - "name": "id", + "name": "idAny", "required": false, "in": "query", + "description": "Return only scenarios matching the provided ids", "schema": { - "type": "string" + "format": "uuid", + "type": "array", + "items": { + "type": "string" + } } }, { - "name": "resourceId", + "name": "name", "required": false, "in": "query", + "description": "Search by scenario name", "schema": { "type": "string" } @@ -5931,6 +6084,20 @@ "type": "string" } }, + { + "name": "sortBy", + "required": false, + "in": "query", + "description": "This is the column to sort by. Defaults to 'createdAt'.", + "schema": { + "enum": [ + "createdAt", + "duration", + "cost" + ], + "type": "string" + } + }, { "name": "limit", "required": false, @@ -6025,18 +6192,21 @@ ], "responses": { "200": { - "description": "List of provider resources", + "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ProviderResourcePaginatedResponse" + "type": "array", + "items": { + "$ref": "#/components/schemas/Scenario" + } } } } } }, "tags": [ - "Provider Resources" + "Simulation Scenarios" ], "security": [ { @@ -6045,39 +6215,16 @@ ] } }, - "/provider/{provider}/{resourceName}/{id}": { + "/eval/simulation/scenario/{id}": { "get": { - "operationId": "ProviderResourceController_getProviderResource", - "summary": "Get Provider Resource", + "operationId": "ScenarioController_findOne", + "summary": "Get Scenario", "parameters": [ - { - "name": "provider", - "required": true, - "in": "path", - "description": "The provider (e.g., 11labs)", - "schema": { - "enum": [ - "11labs" - ], - "type": "string" - } - }, - { - "name": "resourceName", - "required": true, - "in": "path", - "description": "The resource name (e.g., pronunciation-dictionary)", - "schema": { - "enum": [ - "pronunciation-dictionary" - ], - "type": "string" - } - }, { "name": "id", "required": true, "in": "path", + "description": "The unique identifier for the resource.", "schema": { "format": "uuid", "type": "string" @@ -6086,21 +6233,18 @@ ], "responses": { "200": { - "description": "Successfully retrieved provider resource", + "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ProviderResource" + "$ref": "#/components/schemas/Scenario" } } } - }, - "404": { - "description": "Provider resource not found" } }, "tags": [ - "Provider Resources" + "Simulation Scenarios" ], "security": [ { @@ -6108,61 +6252,45 @@ } ] }, - "delete": { - "operationId": "ProviderResourceController_deleteProviderResource", - "summary": "Delete Provider Resource", + "patch": { + "operationId": "ScenarioController_update", + "summary": "Update Scenario", "parameters": [ - { - "name": "provider", - "required": true, - "in": "path", - "description": "The provider (e.g., 11labs)", - "schema": { - "enum": [ - "11labs" - ], - "type": "string" - } - }, - { - "name": "resourceName", - "required": true, - "in": "path", - "description": "The resource name (e.g., pronunciation-dictionary)", - "schema": { - "enum": [ - "pronunciation-dictionary" - ], - "type": "string" - } - }, { "name": "id", "required": true, "in": "path", + "description": "The unique identifier for the resource.", "schema": { "format": "uuid", "type": "string" } } ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateScenarioDTO" + } + } + } + }, "responses": { "200": { "description": "", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ProviderResource" + "$ref": "#/components/schemas/Scenario" } } } - }, - "404": { - "description": "Provider resource not found" } }, "tags": [ - "Provider Resources" + "Simulation Scenarios" ], "security": [ { @@ -6170,38 +6298,15 @@ } ] }, - "patch": { - "operationId": "ProviderResourceController_updateProviderResource", - "summary": "Update Provider Resource", + "delete": { + "operationId": "ScenarioController_remove", + "summary": "Delete Scenario", "parameters": [ - { - "name": "provider", - "required": true, - "in": "path", - "description": "The provider (e.g., 11labs)", - "schema": { - "enum": [ - "11labs" - ], - "type": "string" - } - }, - { - "name": "resourceName", - "required": true, - "in": "path", - "description": "The resource name (e.g., pronunciation-dictionary)", - "schema": { - "enum": [ - "pronunciation-dictionary" - ], - "type": "string" - } - }, { "name": "id", "required": true, "in": "path", + "description": "The unique identifier for the resource.", "schema": { "format": "uuid", "type": "string" @@ -6214,17 +6319,14 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ProviderResource" + "$ref": "#/components/schemas/Scenario" } } } - }, - "404": { - "description": "Provider resource not found" } }, "tags": [ - "Provider Resources" + "Simulation Scenarios" ], "security": [ { @@ -6232,6540 +6334,6423 @@ } ] } - } - }, - "info": { - "title": "Vapi API", - "description": "Voice AI for developers.", - "version": "1.0", - "contact": {} - }, - "tags": [], - "servers": [ - { - "url": "https://api.vapi.ai" - } - ], - "components": { - "securitySchemes": { - "bearer": { - "scheme": "bearer", - "bearerFormat": "Bearer", - "type": "http", - "description": "Retrieve your API Key from [Dashboard](dashboard.vapi.ai)." - } }, - "schemas": { - "AnalysisCostBreakdown": { - "type": "object", - "properties": { - "summary": { - "type": "number", - "description": "This is the cost to summarize the call." - }, - "summaryPromptTokens": { - "type": "number", - "description": "This is the number of prompt tokens used to summarize the call." - }, - "summaryCompletionTokens": { - "type": "number", - "description": "This is the number of completion tokens used to summarize the call." - }, - "structuredData": { - "type": "number", - "description": "This is the cost to extract structured data from the call." - }, - "structuredDataPromptTokens": { - "type": "number", - "description": "This is the number of prompt tokens used to extract structured data from the call." - }, - "structuredDataCompletionTokens": { - "type": "number", - "description": "This is the number of completion tokens used to extract structured data from the call." - }, - "successEvaluation": { - "type": "number", - "description": "This is the cost to evaluate if the call was successful." - }, - "successEvaluationPromptTokens": { - "type": "number", - "description": "This is the number of prompt tokens used to evaluate if the call was successful." - }, - "successEvaluationCompletionTokens": { - "type": "number", - "description": "This is the number of completion tokens used to evaluate if the call was successful." - }, - "structuredOutput": { - "type": "number", - "description": "This is the cost to evaluate structuredOutputs from the call." - }, - "structuredOutputPromptTokens": { - "type": "number", - "description": "This is the number of prompt tokens used to evaluate structuredOutputs from the call." - }, - "structuredOutputCompletionTokens": { - "type": "number", - "description": "This is the number of completion tokens used to evaluate structuredOutputs from the call." + "/eval/simulation/run": { + "post": { + "operationId": "SimulationRunController_create", + "summary": "Create Simulation Run", + "parameters": [ + { + "name": "user-agent", + "required": false, + "in": "header", + "description": "Identifies the client starting the simulation run", + "schema": { + "type": "string" + } } - } - }, - "CostBreakdown": { - "type": "object", - "properties": { - "transport": { - "type": "number", - "description": "This is the cost of the transport provider, like Twilio or Vonage." - }, - "stt": { - "type": "number", - "description": "This is the cost of the speech-to-text service." - }, - "llm": { - "type": "number", - "description": "This is the cost of the language model." - }, - "tts": { - "type": "number", - "description": "This is the cost of the text-to-speech service." - }, - "vapi": { - "type": "number", - "description": "This is the cost of Vapi." - }, - "chat": { - "type": "number", - "description": "This is the cost of chat interactions." - }, - "total": { - "type": "number", - "description": "This is the total cost of the call." - }, - "llmPromptTokens": { - "type": "number", - "description": "This is the LLM prompt tokens used for the call." - }, - "llmCompletionTokens": { - "type": "number", - "description": "This is the LLM completion tokens used for the call." - }, - "ttsCharacters": { - "type": "number", - "description": "This is the TTS characters used for the call." + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateSimulationRunDTO" + } + } + } + }, + "responses": { + "201": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateSimulationRunResponse" + } + } + } }, - "analysisCostBreakdown": { - "description": "This is the cost of the analysis.", - "allOf": [ - { - "$ref": "#/components/schemas/AnalysisCostBreakdown" + "402": { + "description": "The organization is not eligible to start this run.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SimulationRunPaymentRequiredResponse" + } } - ] + } } - } + }, + "tags": [ + "Simulation Runs" + ], + "security": [ + { + "bearer": [] + } + ] }, - "TranscriptPlan": { - "type": "object", - "properties": { - "enabled": { - "type": "boolean", - "description": "This determines whether the transcript is stored in `call.artifact.transcript`. Defaults to true.\n\n@default true", - "example": true + "get": { + "operationId": "SimulationRunController_findAll", + "summary": "List Simulation Runs", + "parameters": [ + { + "name": "status", + "required": false, + "in": "query", + "description": "Filter by status", + "schema": { + "enum": [ + "queued", + "running", + "ended" + ], + "type": "string" + } }, - "assistantName": { - "type": "string", - "description": "This is the name of the assistant in the transcript. Defaults to 'AI'.\n\nUsage:\n- If you want to change the name of the assistant in the transcript, set this. Example, here is what the transcript would look like with `assistantName` set to 'Buyer':\n```\nUser: Hello, how are you?\nBuyer: I'm fine.\nUser: Do you want to buy a car?\nBuyer: No.\n```\n\n@default 'AI'" + { + "name": "filterStatus", + "required": false, + "in": "query", + "description": "Filter by aggregate run result status", + "schema": { + "enum": [ + "passed", + "failed", + "running" + ], + "type": "string" + } }, - "userName": { - "type": "string", - "description": "This is the name of the user in the transcript. Defaults to 'User'.\n\nUsage:\n- If you want to change the name of the user in the transcript, set this. Example, here is what the transcript would look like with `userName` set to 'Seller':\n```\nSeller: Hello, how are you?\nAI: I'm fine.\nSeller: Do you want to buy a car?\nAI: No.\n```\n\n@default 'User'" - } - } - }, - "ArtifactPlan": { - "type": "object", - "properties": { - "recordingEnabled": { - "type": "boolean", - "description": "This determines whether assistant's calls are recorded. Defaults to true.\n\nUsage:\n- If you don't want to record the calls, set this to false.\n- If you want to record the calls when `assistant.hipaaEnabled` (deprecated) or `assistant.compliancePlan.hipaaEnabled` explicity set this to true and make sure to provide S3 or GCP credentials on the Provider Credentials page in the Dashboard.\n\nYou can find the recording at `call.artifact.recordingUrl` and `call.artifact.stereoRecordingUrl` after the call is ended.\n\n@default true", - "example": true + { + "name": "targetType", + "required": false, + "in": "query", + "description": "Filter by target type", + "schema": { + "enum": [ + "assistant", + "squad" + ], + "type": "string" + } }, - "recordingFormat": { - "type": "string", - "description": "This determines the format of the recording. Defaults to `wav;l16`.\n\n@default 'wav;l16'", - "enum": [ - "wav;l16", - "mp3" - ] + { + "name": "targetId", + "required": false, + "in": "query", + "description": "Filter by target id", + "schema": { + "format": "uuid", + "type": "string" + } }, - "videoRecordingEnabled": { - "type": "boolean", - "description": "This determines whether the video is recorded during the call. Defaults to false. Only relevant for `webCall` type.\n\nYou can find the video recording at `call.artifact.videoRecordingUrl` after the call is ended.\n\n@default false", - "example": false + { + "name": "page", + "required": false, + "in": "query", + "description": "This is the page number to return. Defaults to 1.", + "schema": { + "minimum": 1, + "type": "number" + } }, - "pcapEnabled": { - "type": "boolean", - "description": "This determines whether the SIP packet capture is enabled. Defaults to true. Only relevant for `phone` type calls where phone number's provider is `vapi` or `byo-phone-number`.\n\nYou can find the packet capture at `call.artifact.pcapUrl` after the call is ended.\n\n@default true", - "example": true + { + "name": "sortOrder", + "required": false, + "in": "query", + "description": "This is the sort order for pagination. Defaults to 'DESC'.", + "schema": { + "enum": [ + "ASC", + "DESC" + ], + "type": "string" + } }, - "pcapS3PathPrefix": { - "type": "string", - "description": "This is the path where the SIP packet capture will be uploaded. This is only used if you have provided S3 or GCP credentials on the Provider Credentials page in the Dashboard.\n\nIf credential.s3PathPrefix or credential.bucketPlan.path is set, this will append to it.\n\nUsage:\n- If you want to upload the packet capture to a specific path, set this to the path. Example: `/my-assistant-captures`.\n- If you want to upload the packet capture to the root of the bucket, set this to `/`.\n\n@default '/'", - "example": "/pcaps" + { + "name": "sortBy", + "required": false, + "in": "query", + "description": "This is the column to sort by. Defaults to 'createdAt'.", + "schema": { + "enum": [ + "createdAt", + "duration", + "cost" + ], + "type": "string" + } }, - "loggingEnabled": { - "type": "boolean", - "description": "This determines whether the call logs are enabled. Defaults to true.\n\n@default true", - "example": true + { + "name": "limit", + "required": false, + "in": "query", + "description": "This is the maximum number of items to return. Defaults to 100.", + "schema": { + "minimum": 0, + "maximum": 1000, + "type": "number" + } }, - "transcriptPlan": { - "description": "This is the plan for `call.artifact.transcript`. To disable, set `transcriptPlan.enabled` to false.", - "allOf": [ - { - "$ref": "#/components/schemas/TranscriptPlan" - } - ] + { + "name": "createdAtGt", + "required": false, + "in": "query", + "description": "This will return items where the createdAt is greater than the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } }, - "recordingPath": { - "type": "string", - "description": "This is the path where the recording will be uploaded. This is only used if you have provided S3 or GCP credentials on the Provider Credentials page in the Dashboard.\n\nIf credential.s3PathPrefix or credential.bucketPlan.path is set, this will append to it.\n\nUsage:\n- If you want to upload the recording to a specific path, set this to the path. Example: `/my-assistant-recordings`.\n- If you want to upload the recording to the root of the bucket, set this to `/`.\n\n@default '/'" + { + "name": "createdAtLt", + "required": false, + "in": "query", + "description": "This will return items where the createdAt is less than the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } }, - "structuredOutputIds": { - "description": "This is an array of structured output IDs to be calculated during the call.\nThe outputs will be extracted and stored in `call.artifact.structuredOutputs` after the call is ended.", - "type": "array", - "items": { + { + "name": "createdAtGe", + "required": false, + "in": "query", + "description": "This will return items where the createdAt is greater than or equal to the specified value.", + "schema": { + "format": "date-time", "type": "string" } }, - "loggingPath": { - "type": "string", - "description": "This is the path where the call logs will be uploaded. This is only used if you have provided S3 or GCP credentials on the Provider Credentials page in the Dashboard.\n\nIf credential.s3PathPrefix or credential.bucketPlan.path is set, this will append to it.\n\nUsage:\n- If you want to upload the call logs to a specific path, set this to the path. Example: `/my-assistant-logs`.\n- If you want to upload the call logs to the root of the bucket, set this to `/`.\n\n@default '/'" - } - } - }, - "Analysis": { - "type": "object", - "properties": { - "summary": { - "type": "string", - "description": "This is the summary of the call. Customize by setting `assistant.analysisPlan.summaryPrompt`." + { + "name": "createdAtLe", + "required": false, + "in": "query", + "description": "This will return items where the createdAt is less than or equal to the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } }, - "structuredData": { - "type": "object", - "description": "This is the structured data extracted from the call. Customize by setting `assistant.analysisPlan.structuredDataPrompt` and/or `assistant.analysisPlan.structuredDataSchema`." + { + "name": "updatedAtGt", + "required": false, + "in": "query", + "description": "This will return items where the updatedAt is greater than the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } }, - "structuredDataMulti": { - "description": "This is the structured data catalog of the call. Customize by setting `assistant.analysisPlan.structuredDataMultiPlan`.", - "type": "array", - "items": { - "type": "object" + { + "name": "updatedAtLt", + "required": false, + "in": "query", + "description": "This will return items where the updatedAt is less than the specified value.", + "schema": { + "format": "date-time", + "type": "string" } }, - "successEvaluation": { - "type": "string", - "description": "This is the evaluation of the call. Customize by setting `assistant.analysisPlan.successEvaluationPrompt` and/or `assistant.analysisPlan.successEvaluationRubric`." - } - } - }, - "Monitor": { - "type": "object", - "properties": { - "listenUrl": { - "type": "string", - "description": "This is the URL where the assistant's calls can be listened to in real-time. To enable, set `assistant.monitorPlan.listenEnabled` to `true`." + { + "name": "updatedAtGe", + "required": false, + "in": "query", + "description": "This will return items where the updatedAt is greater than or equal to the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } }, - "controlUrl": { - "type": "string", - "description": "This is the URL where the assistant's calls can be controlled in real-time. To enable, set `assistant.monitorPlan.controlEnabled` to `true`." + { + "name": "updatedAtLe", + "required": false, + "in": "query", + "description": "This will return items where the updatedAt is less than or equal to the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } } - } - }, - "OpenAIMessage": { - "type": "object", - "properties": { - "content": { - "type": "string", - "nullable": true, - "maxLength": 100000000 - }, - "role": { - "type": "string", - "enum": [ - "assistant", - "function", - "user", - "system", - "tool" - ] + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "oneOf": [ + { + "type": "array", + "items": { + "$ref": "#/components/schemas/SimulationRun" + } + }, + { + "$ref": "#/components/schemas/SimulationRunsPaginatedResponse" + } + ] + } + } + } } }, - "required": [ - "content", - "role" + "tags": [ + "Simulation Runs" + ], + "security": [ + { + "bearer": [] + } ] - }, - "Mono": { - "type": "object", - "properties": { - "combinedUrl": { - "type": "string", - "description": "This is the combined recording url for the call. To enable, set `assistant.artifactPlan.recordingEnabled`." - }, - "assistantUrl": { - "type": "string", - "description": "This is the mono recording url for the assistant. To enable, set `assistant.artifactPlan.recordingEnabled`." - }, - "customerUrl": { - "type": "string", - "description": "This is the mono recording url for the customer. To enable, set `assistant.artifactPlan.recordingEnabled`." + } + }, + "/eval/simulation/run/{id}": { + "get": { + "operationId": "SimulationRunController_findOne", + "summary": "Get Simulation Run", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "description": "The unique identifier for the resource.", + "schema": { + "format": "uuid", + "type": "string" + } } - } - }, - "Recording": { - "type": "object", - "properties": { - "stereoUrl": { - "type": "string", - "description": "This is the stereo recording url for the call. To enable, set `assistant.artifactPlan.recordingEnabled`." - }, - "videoUrl": { - "type": "string", - "description": "This is the video recording url for the call. To enable, set `assistant.artifactPlan.videoRecordingEnabled`." - }, - "videoRecordingStartDelaySeconds": { - "type": "number", - "description": "This is video recording start delay in ms. To enable, set `assistant.artifactPlan.videoRecordingEnabled`. This can be used to align the playback of the recording with artifact.messages timestamps." - }, - "mono": { - "description": "This is the mono recording url for the call. To enable, set `assistant.artifactPlan.recordingEnabled`.", - "allOf": [ - { - "$ref": "#/components/schemas/Mono" + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SimulationRun" + } } - ] + } } - } + }, + "tags": [ + "Simulation Runs" + ], + "security": [ + { + "bearer": [] + } + ] }, - "NodeArtifact": { - "type": "object", - "properties": { - "messages": { - "type": "array", - "description": "These are the messages that were spoken during the node.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/UserMessage", - "title": "UserMessage" - }, - { - "$ref": "#/components/schemas/SystemMessage", - "title": "SystemMessage" - }, - { - "$ref": "#/components/schemas/BotMessage", - "title": "BotMessage" - }, - { - "$ref": "#/components/schemas/ToolCallMessage", - "title": "ToolCallMessage" - }, - { - "$ref": "#/components/schemas/ToolCallResultMessage", - "title": "ToolCallResultMessage" + "patch": { + "operationId": "SimulationRunController_cancelGroup", + "summary": "Cancel Simulation Run", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "description": "The unique identifier for the resource.", + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SimulationRun" } - ] + } } - }, - "nodeName": { - "type": "string", - "description": "This is the node name." - }, - "variableValues": { - "type": "object", - "description": "These are the variable values that were extracted from the node." } - } - }, - "TurnLatency": { - "type": "object", - "properties": { - "modelLatency": { - "type": "number", - "description": "This is the model latency for the first token." - }, - "voiceLatency": { - "type": "number", - "description": "This is the voice latency from the model output." - }, - "transcriberLatency": { - "type": "number", - "description": "This is the transcriber latency from the user speech." - }, - "endpointingLatency": { - "type": "number", - "description": "This is the endpointing latency." - }, - "turnLatency": { - "type": "number", - "description": "This is the latency for the whole turn." + }, + "tags": [ + "Simulation Runs" + ], + "security": [ + { + "bearer": [] } - } - }, - "PerformanceMetrics": { - "type": "object", - "properties": { - "turnLatencies": { - "description": "These are the individual latencies for each turn.", - "type": "array", - "items": { - "$ref": "#/components/schemas/TurnLatency" + ] + } + }, + "/eval/simulation/run/{id}/item": { + "get": { + "operationId": "SimulationRunController_findItems", + "summary": "List Simulation Run Items", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "description": "The unique identifier for the resource.", + "schema": { + "format": "uuid", + "type": "string" } }, - "modelLatencyAverage": { - "type": "number", - "description": "This is the average latency for the model to output the first token." - }, - "voiceLatencyAverage": { - "type": "number", - "description": "This is the average latency for the text to speech." - }, - "transcriberLatencyAverage": { - "type": "number", - "description": "This is the average latency for the transcriber." + { + "name": "simulationId", + "required": false, + "in": "query", + "description": "This is the simulation ID to filter by.", + "schema": { + "format": "uuid", + "type": "string" + } }, - "endpointingLatencyAverage": { - "type": "number", - "description": "This is the average latency for the endpointing." + { + "name": "runId", + "required": false, + "in": "query", + "description": "This is the run ID (batch/group) to filter by.", + "schema": { + "format": "uuid", + "type": "string" + } }, - "turnLatencyAverage": { - "type": "number", - "description": "This is the average latency for complete turns." - } - } - }, - "Artifact": { - "type": "object", - "properties": { - "messages": { - "type": "array", - "description": "These are the messages that were spoken during the call.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/UserMessage", - "title": "UserMessage" - }, - { - "$ref": "#/components/schemas/SystemMessage", - "title": "SystemMessage" - }, - { - "$ref": "#/components/schemas/BotMessage", - "title": "BotMessage" - }, - { - "$ref": "#/components/schemas/ToolCallMessage", - "title": "ToolCallMessage" - }, - { - "$ref": "#/components/schemas/ToolCallResultMessage", - "title": "ToolCallResultMessage" - } - ] + { + "name": "status", + "required": false, + "in": "query", + "description": "This is the status to filter by.", + "schema": { + "enum": [ + "queued", + "running", + "evaluating", + "passed", + "failed", + "canceled" + ], + "type": "string" } }, - "messagesOpenAIFormatted": { - "description": "These are the messages that were spoken during the call, formatted for OpenAI.", - "type": "array", - "items": { - "$ref": "#/components/schemas/OpenAIMessage" + { + "name": "page", + "required": false, + "in": "query", + "description": "This is the page number to return. Defaults to 1.", + "schema": { + "minimum": 1, + "type": "number" } }, - "recordingUrl": { - "type": "string", - "description": "This is the recording url for the call. To enable, set `assistant.artifactPlan.recordingEnabled`.", - "deprecated": true + { + "name": "sortOrder", + "required": false, + "in": "query", + "description": "This is the sort order for pagination. Defaults to 'DESC'.", + "schema": { + "enum": [ + "ASC", + "DESC" + ], + "type": "string" + } }, - "stereoRecordingUrl": { - "type": "string", - "description": "This is the stereo recording url for the call. To enable, set `assistant.artifactPlan.recordingEnabled`.", - "deprecated": true + { + "name": "sortBy", + "required": false, + "in": "query", + "description": "This is the column to sort by. Defaults to 'createdAt'.", + "schema": { + "enum": [ + "createdAt", + "duration", + "cost" + ], + "type": "string" + } }, - "videoRecordingUrl": { - "type": "string", - "description": "This is video recording url for the call. To enable, set `assistant.artifactPlan.videoRecordingEnabled`.", - "deprecated": true + { + "name": "limit", + "required": false, + "in": "query", + "description": "This is the maximum number of items to return. Defaults to 100.", + "schema": { + "minimum": 0, + "maximum": 1000, + "type": "number" + } }, - "videoRecordingStartDelaySeconds": { - "type": "number", - "description": "This is video recording start delay in ms. To enable, set `assistant.artifactPlan.videoRecordingEnabled`. This can be used to align the playback of the recording with artifact.messages timestamps.", - "deprecated": true + { + "name": "createdAtGt", + "required": false, + "in": "query", + "description": "This will return items where the createdAt is greater than the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } }, - "recording": { - "description": "This is the recording url for the call. To enable, set `assistant.artifactPlan.recordingEnabled`.", - "allOf": [ - { - "$ref": "#/components/schemas/Recording" - } - ] + { + "name": "createdAtLt", + "required": false, + "in": "query", + "description": "This will return items where the createdAt is less than the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } }, - "transcript": { - "type": "string", - "description": "This is the transcript of the call. This is derived from `artifact.messages` but provided for convenience." + { + "name": "createdAtGe", + "required": false, + "in": "query", + "description": "This will return items where the createdAt is greater than or equal to the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } }, - "pcapUrl": { - "type": "string", - "description": "This is the packet capture url for the call. This is only available for `phone` type calls where phone number's provider is `vapi` or `byo-phone-number`." + { + "name": "createdAtLe", + "required": false, + "in": "query", + "description": "This will return items where the createdAt is less than or equal to the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } }, - "logUrl": { - "type": "string", - "description": "This is the url for the call logs. This includes all logging output during the call for debugging purposes." + { + "name": "updatedAtGt", + "required": false, + "in": "query", + "description": "This will return items where the updatedAt is greater than the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } }, - "nodes": { - "description": "This is the history of workflow nodes that were executed during the call.", - "type": "array", - "items": { - "$ref": "#/components/schemas/NodeArtifact" + { + "name": "updatedAtLt", + "required": false, + "in": "query", + "description": "This will return items where the updatedAt is less than the specified value.", + "schema": { + "format": "date-time", + "type": "string" } }, - "variableValues": { - "type": "object", - "description": "These are the variable values at the end of the workflow execution." + { + "name": "updatedAtGe", + "required": false, + "in": "query", + "description": "This will return items where the updatedAt is greater than or equal to the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } }, - "performanceMetrics": { - "description": "This is the performance metrics for the call. It contains the turn latency, broken down by component.", - "allOf": [ - { - "$ref": "#/components/schemas/PerformanceMetrics" + { + "name": "updatedAtLe", + "required": false, + "in": "query", + "description": "This will return items where the updatedAt is less than or equal to the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SimulationRunItem" + } + } } - ] + } + } + }, + "tags": [ + "Simulation Runs", + "Simulation Run Items" + ], + "security": [ + { + "bearer": [] + } + ] + } + }, + "/eval/simulation/run/{id}/item/{itemId}": { + "get": { + "operationId": "SimulationRunController_findItem", + "summary": "Get Simulation Run Item", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "string" + } }, - "structuredOutputs": { - "type": "object", - "description": "These are the structured outputs that will be extracted from the call.\nTo enable, set `assistant.artifactPlan.structuredOutputIds` with the IDs of the structured outputs you want to extract." + { + "name": "itemId", + "required": true, + "in": "path", + "schema": { + "type": "string" + } } - } - }, - "FallbackTranscriberPlan": { - "type": "object", - "properties": { - "transcribers": { - "type": "array", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/FallbackAssemblyAITranscriber", - "title": "AssemblyAI" - }, - { - "$ref": "#/components/schemas/FallbackAzureSpeechTranscriber", - "title": "Azure" - }, - { - "$ref": "#/components/schemas/FallbackCustomTranscriber", - "title": "Custom" - }, - { - "$ref": "#/components/schemas/FallbackDeepgramTranscriber", - "title": "Deepgram" - }, - { - "$ref": "#/components/schemas/FallbackElevenLabsTranscriber", - "title": "ElevenLabs" - }, - { - "$ref": "#/components/schemas/FallbackGladiaTranscriber", - "title": "Gladia" - }, - { - "$ref": "#/components/schemas/FallbackGoogleTranscriber", - "title": "Google" - }, - { - "$ref": "#/components/schemas/FallbackTalkscriberTranscriber", - "title": "Talkscriber" - }, - { - "$ref": "#/components/schemas/FallbackSpeechmaticsTranscriber", - "title": "Speechmatics" - }, - { - "$ref": "#/components/schemas/FallbackOpenAITranscriber", - "title": "OpenAI" - }, - { - "$ref": "#/components/schemas/FallbackCartesiaTranscriber", - "title": "Cartesia" + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SimulationRunItem" } - ] + } } } }, - "required": [ - "transcribers" + "tags": [ + "Simulation Runs", + "Simulation Run Items" + ], + "security": [ + { + "bearer": [] + } ] }, - "AssemblyAITranscriber": { - "type": "object", - "properties": { - "provider": { - "type": "string", - "description": "This is the transcription provider that will be used.", - "enum": [ - "assembly-ai" - ] + "patch": { + "operationId": "SimulationRunController_cancelItem", + "summary": "Cancel Simulation Run Item", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "string" + } }, - "language": { - "type": "string", - "description": "This is the language that will be set for the transcription.", - "enum": [ - "en" - ] + { + "name": "itemId", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SimulationRunItem" + } + } + } + } + }, + "tags": [ + "Simulation Runs", + "Simulation Run Items" + ], + "security": [ + { + "bearer": [] + } + ] + } + }, + "/eval/simulation/run/{id}/item/{itemId}/generate": { + "post": { + "operationId": "SimulationRunController_generateSuggestions", + "summary": "Generate Improvement Suggestions", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "string" + } }, - "confidenceThreshold": { - "type": "number", - "description": "Transcripts below this confidence threshold will be discarded.\n\n@default 0.4", - "minimum": 0, - "maximum": 1, - "example": 0.4 + { + "name": "itemId", + "required": true, + "in": "path", + "schema": { + "type": "string" + } }, - "formatTurns": { - "type": "boolean", - "description": "This enables formatting of transcripts.\n\n@default true", - "example": true + { + "name": "force", + "required": true, + "in": "query", + "schema": { + "type": "string" + } }, - "endOfTurnConfidenceThreshold": { - "type": "number", - "description": "This is the end of turn confidence threshold. The minimum confidence that the end of turn is detected.\n\n@min 0\n@max 1\n@default 0.7", - "minimum": 0, - "maximum": 1, - "example": 0.7 + { + "name": "persist", + "required": false, + "in": "query", + "schema": { + "type": "string" + } + } + ], + "responses": { + "201": { + "description": "" + } + }, + "tags": [ + "Simulation Runs", + "Simulation Run Items" + ], + "security": [ + { + "bearer": [] + } + ] + } + }, + "/eval/simulation/suite": { + "post": { + "operationId": "SimulationSuiteController_create", + "summary": "Create Simulation Suite", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateSimulationSuiteDTO" + } + } + } + }, + "responses": { + "201": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SimulationSuite" + } + } + } + } + }, + "tags": [ + "Simulation Suites" + ], + "security": [ + { + "bearer": [] + } + ] + }, + "get": { + "operationId": "SimulationSuiteController_findAll", + "summary": "List Simulation Suites", + "parameters": [ + { + "name": "name", + "required": false, + "in": "query", + "description": "Search by simulation suite name", + "schema": { + "type": "string" + } }, - "minEndOfTurnSilenceWhenConfident": { - "type": "number", - "description": "This is the minimum end of turn silence when confident in milliseconds.\n\n@default 160", - "minimum": 0, - "example": 160 + { + "name": "page", + "required": false, + "in": "query", + "description": "This is the page number to return. Defaults to 1.", + "schema": { + "minimum": 1, + "type": "number" + } }, - "wordFinalizationMaxWaitTime": { - "type": "number", - "description": "This is the maximum wait time for word finalization in milliseconds.\n\n@default 160", - "minimum": 0, - "example": 160 + { + "name": "sortOrder", + "required": false, + "in": "query", + "description": "This is the sort order for pagination. Defaults to 'DESC'.", + "schema": { + "enum": [ + "ASC", + "DESC" + ], + "type": "string" + } }, - "maxTurnSilence": { - "type": "number", - "description": "This is the maximum turn silence time in milliseconds.\n\n@default 400", - "minimum": 0, - "example": 400 + { + "name": "sortBy", + "required": false, + "in": "query", + "description": "This is the column to sort by. Defaults to 'createdAt'.", + "schema": { + "enum": [ + "createdAt", + "duration", + "cost" + ], + "type": "string" + } }, - "realtimeUrl": { - "type": "string", - "description": "The WebSocket URL that the transcriber connects to." + { + "name": "limit", + "required": false, + "in": "query", + "description": "This is the maximum number of items to return. Defaults to 100.", + "schema": { + "minimum": 0, + "maximum": 1000, + "type": "number" + } }, - "wordBoost": { - "description": "Add up to 2500 characters of custom vocabulary.", - "type": "array", - "items": { - "type": "string", - "maxLength": 2500 + { + "name": "createdAtGt", + "required": false, + "in": "query", + "description": "This will return items where the createdAt is greater than the specified value.", + "schema": { + "format": "date-time", + "type": "string" } }, - "endUtteranceSilenceThreshold": { - "type": "number", - "description": "The duration of the end utterance silence threshold in milliseconds." + { + "name": "createdAtLt", + "required": false, + "in": "query", + "description": "This will return items where the createdAt is less than the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } }, - "disablePartialTranscripts": { - "type": "boolean", - "description": "Disable partial transcripts.\nSet to `true` to not receive partial transcripts. Defaults to `false`." + { + "name": "createdAtGe", + "required": false, + "in": "query", + "description": "This will return items where the createdAt is greater than or equal to the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } }, - "fallbackPlan": { - "description": "This is the plan for voice provider fallbacks in the event that the primary voice provider fails.", - "allOf": [ - { - "$ref": "#/components/schemas/FallbackTranscriberPlan" + { + "name": "createdAtLe", + "required": false, + "in": "query", + "description": "This will return items where the createdAt is less than or equal to the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } + }, + { + "name": "updatedAtGt", + "required": false, + "in": "query", + "description": "This will return items where the updatedAt is greater than the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } + }, + { + "name": "updatedAtLt", + "required": false, + "in": "query", + "description": "This will return items where the updatedAt is less than the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } + }, + { + "name": "updatedAtGe", + "required": false, + "in": "query", + "description": "This will return items where the updatedAt is greater than or equal to the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } + }, + { + "name": "updatedAtLe", + "required": false, + "in": "query", + "description": "This will return items where the updatedAt is less than or equal to the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SimulationSuite" + } + } } - ] + } } }, - "required": [ - "provider" + "tags": [ + "Simulation Suites" + ], + "security": [ + { + "bearer": [] + } + ] + } + }, + "/eval/simulation/suite/{id}": { + "get": { + "operationId": "SimulationSuiteController_findOne", + "summary": "Get Simulation Suite", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "description": "The unique identifier for the resource.", + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SimulationSuite" + } + } + } + } + }, + "tags": [ + "Simulation Suites" + ], + "security": [ + { + "bearer": [] + } ] }, - "AzureSpeechTranscriber": { - "type": "object", - "properties": { - "provider": { - "type": "string", - "description": "This is the transcription provider that will be used.", - "enum": [ - "azure" - ] - }, - "language": { - "type": "string", - "description": "This is the language that will be set for the transcription. The list of languages Azure supports can be found here: https://learn.microsoft.com/en-us/azure/ai-services/speech-service/language-support?tabs=stt", - "enum": [ - "af-ZA", - "am-ET", - "ar-AE", - "ar-BH", - "ar-DZ", - "ar-EG", - "ar-IL", - "ar-IQ", - "ar-JO", - "ar-KW", - "ar-LB", - "ar-LY", - "ar-MA", - "ar-OM", - "ar-PS", - "ar-QA", - "ar-SA", - "ar-SY", - "ar-TN", - "ar-YE", - "az-AZ", - "bg-BG", - "bn-IN", - "bs-BA", - "ca-ES", - "cs-CZ", - "cy-GB", - "da-DK", - "de-AT", - "de-CH", - "de-DE", - "el-GR", - "en-AU", - "en-CA", - "en-GB", - "en-GH", - "en-HK", - "en-IE", - "en-IN", - "en-KE", - "en-NG", - "en-NZ", - "en-PH", - "en-SG", - "en-TZ", - "en-US", - "en-ZA", - "es-AR", - "es-BO", - "es-CL", - "es-CO", - "es-CR", - "es-CU", - "es-DO", - "es-EC", - "es-ES", - "es-GQ", - "es-GT", - "es-HN", - "es-MX", - "es-NI", - "es-PA", - "es-PE", - "es-PR", - "es-PY", - "es-SV", - "es-US", - "es-UY", - "es-VE", - "et-EE", - "eu-ES", - "fa-IR", - "fi-FI", - "fil-PH", - "fr-BE", - "fr-CA", - "fr-CH", - "fr-FR", - "ga-IE", - "gl-ES", - "gu-IN", - "he-IL", - "hi-IN", - "hr-HR", - "hu-HU", - "hy-AM", - "id-ID", - "is-IS", - "it-CH", - "it-IT", - "ja-JP", - "jv-ID", - "ka-GE", - "kk-KZ", - "km-KH", - "kn-IN", - "ko-KR", - "lo-LA", - "lt-LT", - "lv-LV", - "mk-MK", - "ml-IN", - "mn-MN", - "mr-IN", - "ms-MY", - "mt-MT", - "my-MM", - "nb-NO", - "ne-NP", - "nl-BE", - "nl-NL", - "pa-IN", - "pl-PL", - "ps-AF", - "pt-BR", - "pt-PT", - "ro-RO", - "ru-RU", - "si-LK", - "sk-SK", - "sl-SI", - "so-SO", - "sq-AL", - "sr-RS", - "sv-SE", - "sw-KE", - "sw-TZ", - "ta-IN", - "te-IN", - "th-TH", - "tr-TR", - "uk-UA", - "ur-IN", - "uz-UZ", - "vi-VN", - "wuu-CN", - "yue-CN", - "zh-CN", - "zh-CN-shandong", - "zh-CN-sichuan", - "zh-HK", - "zh-TW", - "zu-ZA" - ] - }, - "segmentationStrategy": { - "type": "string", - "description": "Controls how phrase boundaries are detected, enabling either simple time/silence heuristics or more advanced semantic segmentation.", - "enum": [ - "Default", - "Time", - "Semantic" - ] - }, - "segmentationSilenceTimeoutMs": { - "type": "number", - "description": "Duration of detected silence after which the service finalizes a phrase. Configure to adjust sensitivity to pauses in speech.", - "minimum": 100, - "maximum": 5000 - }, - "segmentationMaximumTimeMs": { - "type": "number", - "description": "Maximum duration a segment can reach before being cut off when using time-based segmentation.", - "minimum": 20000, - "maximum": 70000 - }, - "fallbackPlan": { - "description": "This is the plan for voice provider fallbacks in the event that the primary voice provider fails.", - "allOf": [ - { - "$ref": "#/components/schemas/FallbackTranscriberPlan" + "patch": { + "operationId": "SimulationSuiteController_update", + "summary": "Update Simulation Suite", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "description": "The unique identifier for the resource.", + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateSimulationSuiteDTO" } - ] + } } }, - "required": [ - "provider" + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SimulationSuite" + } + } + } + } + }, + "tags": [ + "Simulation Suites" + ], + "security": [ + { + "bearer": [] + } ] }, - "CartesiaTranscriber": { - "type": "object", - "properties": { - "provider": { - "type": "string", - "enum": [ - "cartesia" - ] - }, - "model": { - "type": "string", - "enum": [ - "ink-whisper" - ] - }, - "language": { - "type": "string", - "enum": [ - "aa", - "ab", - "ae", - "af", - "ak", - "am", - "an", - "ar", - "as", - "av", - "ay", - "az", - "ba", - "be", - "bg", - "bh", - "bi", - "bm", - "bn", - "bo", - "br", - "bs", - "ca", - "ce", - "ch", - "co", - "cr", - "cs", - "cu", - "cv", - "cy", - "da", - "de", - "dv", - "dz", - "ee", - "el", - "en", - "eo", - "es", - "et", - "eu", - "fa", - "ff", - "fi", - "fj", - "fo", - "fr", - "fy", - "ga", - "gd", - "gl", - "gn", - "gu", - "gv", - "ha", - "he", - "hi", - "ho", - "hr", - "ht", - "hu", - "hy", - "hz", - "ia", - "id", - "ie", - "ig", - "ii", - "ik", - "io", - "is", - "it", - "iu", - "ja", - "jv", - "ka", - "kg", - "ki", - "kj", - "kk", - "kl", - "km", - "kn", - "ko", - "kr", - "ks", - "ku", - "kv", - "kw", - "ky", - "la", - "lb", - "lg", - "li", - "ln", - "lo", - "lt", - "lu", - "lv", - "mg", - "mh", - "mi", - "mk", - "ml", - "mn", - "mr", - "ms", - "mt", - "my", - "na", - "nb", - "nd", - "ne", - "ng", - "nl", - "nn", - "no", - "nr", - "nv", - "ny", - "oc", - "oj", - "om", - "or", - "os", - "pa", - "pi", - "pl", - "ps", - "pt", - "qu", - "rm", - "rn", - "ro", - "ru", - "rw", - "sa", - "sc", - "sd", - "se", - "sg", - "si", - "sk", - "sl", - "sm", - "sn", - "so", - "sq", - "sr", - "ss", - "st", - "su", - "sv", - "sw", - "ta", - "te", - "tg", - "th", - "ti", - "tk", - "tl", - "tn", - "to", - "tr", - "ts", - "tt", - "tw", - "ty", - "ug", - "uk", - "ur", - "uz", - "ve", - "vi", - "vo", - "wa", - "wo", - "xh", - "yi", - "yue", - "yo", - "za", - "zh", - "zu" - ] - }, - "fallbackPlan": { - "description": "This is the plan for voice provider fallbacks in the event that the primary voice provider fails.", - "allOf": [ - { - "$ref": "#/components/schemas/FallbackTranscriberPlan" + "delete": { + "operationId": "SimulationSuiteController_remove", + "summary": "Delete Simulation Suite", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "description": "The unique identifier for the resource.", + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SimulationSuite" + } } - ] + } } }, - "required": [ - "provider" + "tags": [ + "Simulation Suites" + ], + "security": [ + { + "bearer": [] + } ] - }, - "BackoffPlan": { - "type": "object", - "properties": { - "type": { - "type": "object", - "description": "This is the type of backoff plan to use. Defaults to fixed.\n\n@default fixed", - "enum": [ - "fixed", - "exponential" - ], - "example": "fixed" - }, - "maxRetries": { - "type": "number", - "description": "This is the maximum number of retries to attempt if the request fails. Defaults to 0 (no retries).\n\n@default 0", - "minimum": 0, - "maximum": 10, - "example": 0 - }, - "baseDelaySeconds": { - "type": "number", - "description": "This is the base delay in seconds. For linear backoff, this is the delay between each retry. For exponential backoff, this is the initial delay.", - "minimum": 0, - "maximum": 10, - "example": 1 + } + }, + "/eval/simulation/scenario/generate": { + "post": { + "operationId": "SimulationGenerateController_generate", + "summary": "Generate Scenarios with AI", + "description": "Uses AI to analyze an assistant or squad configuration and generate test scenarios", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GenerateScenariosDTO" + } + } } }, - "required": [ - "type", - "maxRetries", - "baseDelaySeconds" - ] - }, - "Server": { - "type": "object", - "properties": { - "timeoutSeconds": { - "type": "number", - "description": "This is the timeout in seconds for the request. Defaults to 20 seconds.\n\n@default 20", - "minimum": 1, - "maximum": 300, - "example": 20 - }, - "url": { - "type": "string", - "description": "This is where the request will be sent." - }, - "headers": { - "type": "object", - "description": "These are the headers to include in the request.\n\nEach key-value pair represents a header name and its value." - }, - "backoffPlan": { - "description": "This is the backoff plan if the request fails. Defaults to undefined (the request will not be retried).\n\n@default undefined (the request will not be retried)", - "allOf": [ - { - "$ref": "#/components/schemas/BackoffPlan" + "responses": { + "201": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GenerateScenariosResponse" + } } - ] + } } - } - }, - "CustomTranscriber": { - "type": "object", - "properties": { - "provider": { - "type": "string", - "description": "This is the transcription provider that will be used. Use `custom-transcriber` for providers that are not natively supported.", - "enum": [ - "custom-transcriber" - ] - }, - "server": { - "description": "This is where the transcription request will be sent.\n\nUsage:\n1. Vapi will initiate a websocket connection with `server.url`.\n\n2. Vapi will send an initial text frame with the sample rate. Format:\n```\n {\n \"type\": \"start\",\n \"encoding\": \"linear16\", // 16-bit raw PCM format\n \"container\": \"raw\",\n \"sampleRate\": {{sampleRate}},\n \"channels\": 2 // customer is channel 0, assistant is channel 1\n }\n```\n\n3. Vapi will send the audio data in 16-bit raw PCM format as binary frames.\n\n4. You can read the messages something like this:\n```\nws.on('message', (data, isBinary) => {\n if (isBinary) {\n pcmBuffer = Buffer.concat([pcmBuffer, data]);\n console.log(`Received PCM data, buffer size: ${pcmBuffer.length}`);\n } else {\n console.log('Received message:', JSON.parse(data.toString()));\n }\n});\n```\n\n5. You will respond with transcriptions as you have them. Format:\n```\n {\n \"type\": \"transcriber-response\",\n \"transcription\": \"Hello, world!\",\n \"channel\": \"customer\" | \"assistant\"\n }\n```", - "allOf": [ - { - "$ref": "#/components/schemas/Server" + }, + "tags": [ + "Simulations" + ], + "security": [ + { + "bearer": [] + } + ] + } + }, + "/eval/simulation": { + "post": { + "operationId": "SimulationController_create", + "summary": "Create Simulation", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateSimulationDTO" } - ] - }, - "fallbackPlan": { - "description": "This is the plan for voice provider fallbacks in the event that the primary voice provider fails.", - "allOf": [ - { - "$ref": "#/components/schemas/FallbackTranscriberPlan" + } + } + }, + "responses": { + "201": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Simulation" + } } - ] + } } }, - "required": [ - "provider", - "server" + "tags": [ + "Simulations" + ], + "security": [ + { + "bearer": [] + } ] }, - "DeepgramTranscriber": { - "type": "object", - "properties": { - "provider": { - "type": "string", - "description": "This is the transcription provider that will be used.", - "enum": [ - "deepgram" - ] - }, - "model": { - "description": "This is the Deepgram model that will be used. A list of models can be found here: https://developers.deepgram.com/docs/models-languages-overview", - "oneOf": [ - { - "type": "string", - "enum": [ - "nova-3", - "nova-3-general", - "nova-3-medical", - "nova-2", - "nova-2-general", - "nova-2-meeting", - "nova-2-phonecall", - "nova-2-finance", - "nova-2-conversationalai", - "nova-2-voicemail", - "nova-2-video", - "nova-2-medical", - "nova-2-drivethru", - "nova-2-automotive", - "nova", - "nova-general", - "nova-phonecall", - "nova-medical", - "enhanced", - "enhanced-general", - "enhanced-meeting", - "enhanced-phonecall", - "enhanced-finance", - "base", - "base-general", - "base-meeting", - "base-phonecall", - "base-finance", - "base-conversationalai", - "base-voicemail", - "base-video", - "whisper" - ] - }, - { + "get": { + "operationId": "SimulationController_findAll", + "summary": "List Simulations", + "parameters": [ + { + "name": "idAny", + "required": false, + "in": "query", + "description": "Return only simulations matching the provided ids", + "schema": { + "format": "uuid", + "type": "array", + "items": { "type": "string" } - ] + } }, - "language": { - "type": "string", - "description": "This is the language that will be set for the transcription. The list of languages Deepgram supports can be found here: https://developers.deepgram.com/docs/models-languages-overview", - "enum": [ - "ar", - "az", - "ba", - "bg", - "br", - "ca", - "cs", - "da", - "da-DK", - "de", - "de-CH", - "el", - "en", - "en-AU", - "en-CA", - "en-GB", - "en-IE", - "en-IN", - "en-NZ", - "en-US", - "es", - "es-419", - "es-LATAM", - "et", - "eu", - "fi", - "fr", - "fr-CA", - "ha", - "haw", - "he", - "hi", - "hi-Latn", - "hu", - "id", - "is", - "it", - "ja", - "jw", - "kn", - "ko", - "ko-KR", - "ln", - "lt", - "lv", - "mk", - "ms", - "multi", - "nl", - "nl-BE", - "no", - "pl", - "pt", - "pt-BR", - "ro", - "ru", - "sk", - "sl", - "sn", - "so", - "sr", - "su", - "sv", - "sv-SE", - "ta", - "taq", - "th", - "th-TH", - "tr", - "tt", - "uk", - "ur", - "vi", - "yo", - "zh", - "zh-CN", - "zh-HK", - "zh-Hans", - "zh-Hant", - "zh-TW" - ] + { + "name": "standaloneOnly", + "required": false, + "in": "query", + "description": "Only include simulations that are not part of a suite", + "schema": { + "type": "boolean" + } }, - "smartFormat": { - "type": "boolean", - "description": "This will be use smart format option provided by Deepgram. It's default disabled because it can sometimes format numbers as times but it's getting better.", - "example": false + { + "name": "page", + "required": false, + "in": "query", + "description": "This is the page number to return. Defaults to 1.", + "schema": { + "minimum": 1, + "type": "number" + } }, - "mipOptOut": { - "type": "boolean", - "description": "If set to true, this will add mip_opt_out=true as a query parameter of all API requests. See https://developers.deepgram.com/docs/the-deepgram-model-improvement-partnership-program#want-to-opt-out\n\nThis will only be used if you are using your own Deepgram API key.\n\n@default false", - "example": false, - "default": false + { + "name": "sortOrder", + "required": false, + "in": "query", + "description": "This is the sort order for pagination. Defaults to 'DESC'.", + "schema": { + "enum": [ + "ASC", + "DESC" + ], + "type": "string" + } }, - "numerals": { - "type": "boolean", - "description": "If set to true, this will cause deepgram to convert spoken numbers to literal numerals. For example, \"my phone number is nine-seven-two...\" would become \"my phone number is 972...\"\n\n@default false", - "example": false + { + "name": "sortBy", + "required": false, + "in": "query", + "description": "This is the column to sort by. Defaults to 'createdAt'.", + "schema": { + "enum": [ + "createdAt", + "duration", + "cost" + ], + "type": "string" + } }, - "confidenceThreshold": { - "type": "number", - "description": "Transcripts below this confidence threshold will be discarded.\n\n@default 0.4", - "minimum": 0, - "maximum": 1, - "example": 0.4 + { + "name": "limit", + "required": false, + "in": "query", + "description": "This is the maximum number of items to return. Defaults to 100.", + "schema": { + "minimum": 0, + "maximum": 1000, + "type": "number" + } }, - "keywords": { - "description": "These keywords are passed to the transcription model to help it pick up use-case specific words. Anything that may not be a common word, like your company name, should be added here.", - "type": "array", - "items": { - "type": "string", - "pattern": "/^\\p{L}[\\p{L}\\d]*(?::[+-]?\\d+)?$/u" + { + "name": "createdAtGt", + "required": false, + "in": "query", + "description": "This will return items where the createdAt is greater than the specified value.", + "schema": { + "format": "date-time", + "type": "string" } }, - "keyterm": { - "description": "Keyterm Prompting allows you improve Keyword Recall Rate (KRR) for important keyterms or phrases up to 90%.", - "type": "array", - "items": { + { + "name": "createdAtLt", + "required": false, + "in": "query", + "description": "This will return items where the createdAt is less than the specified value.", + "schema": { + "format": "date-time", "type": "string" } }, - "endpointing": { - "type": "number", - "description": "This is the timeout after which Deepgram will send transcription on user silence. You can read in-depth documentation here: https://developers.deepgram.com/docs/endpointing.\n\nHere are the most important bits:\n- Defaults to 10. This is recommended for most use cases to optimize for latency.\n- 10 can cause some missing transcriptions since because of the shorter context. This mostly happens for one-word utterances. For those uses cases, it's recommended to try 300. It will add a bit of latency but the quality and reliability of the experience will be better.\n- If neither 10 nor 300 work, contact support@vapi.ai and we'll find another solution.\n\n@default 10", - "minimum": 10, - "maximum": 500 + { + "name": "createdAtGe", + "required": false, + "in": "query", + "description": "This will return items where the createdAt is greater than or equal to the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } }, - "fallbackPlan": { - "description": "This is the plan for voice provider fallbacks in the event that the primary voice provider fails.", - "allOf": [ - { - "$ref": "#/components/schemas/FallbackTranscriberPlan" - } - ] - } - }, - "required": [ - "provider" - ] - }, - "ElevenLabsTranscriber": { - "type": "object", - "properties": { - "provider": { - "type": "string", - "description": "This is the transcription provider that will be used.", - "enum": [ - "11labs" - ] + { + "name": "createdAtLe", + "required": false, + "in": "query", + "description": "This will return items where the createdAt is less than or equal to the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } }, - "model": { - "type": "string", - "description": "This is the model that will be used for the transcription.", - "enum": [ - "scribe_v1" - ] + { + "name": "updatedAtGt", + "required": false, + "in": "query", + "description": "This will return items where the updatedAt is greater than the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } }, - "language": { - "type": "string", - "enum": [ - "aa", - "ab", - "ae", - "af", - "ak", - "am", - "an", - "ar", - "as", - "av", - "ay", - "az", - "ba", - "be", - "bg", - "bh", - "bi", - "bm", - "bn", - "bo", - "br", - "bs", - "ca", - "ce", - "ch", - "co", - "cr", - "cs", - "cu", - "cv", - "cy", - "da", - "de", - "dv", - "dz", - "ee", - "el", - "en", - "eo", - "es", - "et", - "eu", - "fa", - "ff", - "fi", - "fj", - "fo", - "fr", - "fy", - "ga", - "gd", - "gl", - "gn", - "gu", - "gv", - "ha", - "he", - "hi", - "ho", - "hr", - "ht", - "hu", - "hy", - "hz", - "ia", - "id", - "ie", - "ig", - "ii", - "ik", - "io", - "is", - "it", - "iu", - "ja", - "jv", - "ka", - "kg", - "ki", - "kj", - "kk", - "kl", - "km", - "kn", - "ko", - "kr", - "ks", - "ku", - "kv", - "kw", - "ky", - "la", - "lb", - "lg", - "li", - "ln", - "lo", - "lt", - "lu", - "lv", - "mg", - "mh", - "mi", - "mk", - "ml", - "mn", - "mr", - "ms", - "mt", - "my", - "na", - "nb", - "nd", - "ne", - "ng", - "nl", - "nn", - "no", - "nr", - "nv", - "ny", - "oc", - "oj", - "om", - "or", - "os", - "pa", - "pi", - "pl", - "ps", - "pt", - "qu", - "rm", - "rn", - "ro", - "ru", - "rw", - "sa", - "sc", - "sd", - "se", - "sg", - "si", - "sk", - "sl", - "sm", - "sn", - "so", - "sq", - "sr", - "ss", - "st", - "su", - "sv", - "sw", - "ta", - "te", - "tg", - "th", - "ti", - "tk", - "tl", - "tn", - "to", - "tr", - "ts", - "tt", - "tw", - "ty", - "ug", - "uk", - "ur", - "uz", - "ve", - "vi", - "vo", - "wa", - "wo", - "xh", - "yi", - "yue", - "yo", - "za", - "zh", - "zu" - ] + { + "name": "updatedAtLt", + "required": false, + "in": "query", + "description": "This will return items where the updatedAt is less than the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } }, - "fallbackPlan": { - "description": "This is the plan for voice provider fallbacks in the event that the primary voice provider fails.", - "allOf": [ - { - "$ref": "#/components/schemas/FallbackTranscriberPlan" + { + "name": "updatedAtGe", + "required": false, + "in": "query", + "description": "This will return items where the updatedAt is greater than or equal to the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } + }, + { + "name": "updatedAtLe", + "required": false, + "in": "query", + "description": "This will return items where the updatedAt is less than or equal to the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Simulation" + } + } } - ] + } } }, - "required": [ - "provider" + "tags": [ + "Simulations" + ], + "security": [ + { + "bearer": [] + } ] - }, - "GladiaCustomVocabularyConfigDTO": { - "type": "object", - "properties": { - "vocabulary": { - "type": "array", - "description": "Array of vocabulary items (strings or objects with value, pronunciations, intensity, language)", - "items": { - "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/components/schemas/GladiaVocabularyItemDTO" + } + }, + "/eval/simulation/{id}": { + "get": { + "operationId": "SimulationController_findOne", + "summary": "Get Simulation", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "description": "The unique identifier for the resource.", + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Simulation" } - ] + } } - }, - "defaultIntensity": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Default intensity for vocabulary items (0.0 to 1.0)", - "default": 0.5 } }, - "required": [ - "vocabulary" + "tags": [ + "Simulations" + ], + "security": [ + { + "bearer": [] + } ] }, - "GladiaTranscriber": { - "type": "object", - "properties": { - "provider": { - "type": "string", - "description": "This is the transcription provider that will be used.", - "enum": [ - "gladia" - ] - }, - "model": { - "description": "This is the Gladia model that will be used. Default is 'fast'", - "oneOf": [ - { - "enum": [ - "fast", - "accurate", - "solaria-1" - ] + "patch": { + "operationId": "SimulationController_update", + "summary": "Update Simulation", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "description": "The unique identifier for the resource.", + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateSimulationDTO" } - ] - }, - "languageBehaviour": { - "description": "Defines how the transcription model detects the audio language. Default value is 'automatic single language'.", - "oneOf": [ - { - "type": "string", - "enum": [ - "manual", - "automatic single language", - "automatic multiple languages" - ] + } + } + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Simulation" + } } - ] - }, - "language": { - "type": "string", - "description": "Defines the language to use for the transcription. Required when languageBehaviour is 'manual'.", - "enum": [ - "af", - "sq", - "am", - "ar", - "hy", - "as", - "az", - "ba", - "eu", - "be", - "bn", - "bs", - "br", - "bg", - "ca", - "zh", - "hr", - "cs", - "da", - "nl", - "en", - "et", - "fo", - "fi", - "fr", - "gl", - "ka", - "de", - "el", - "gu", - "ht", - "ha", - "haw", - "he", - "hi", - "hu", - "is", - "id", - "it", - "ja", - "jv", - "kn", - "kk", - "km", - "ko", - "lo", - "la", - "lv", - "ln", - "lt", - "lb", - "mk", - "mg", - "ms", - "ml", - "mt", - "mi", - "mr", - "mn", - "my", - "ne", - "no", - "nn", - "oc", - "ps", - "fa", - "pl", - "pt", - "pa", - "ro", - "ru", - "sa", - "sr", - "sn", - "sd", - "si", - "sk", - "sl", - "so", - "es", - "su", - "sw", - "sv", - "tl", - "tg", - "ta", - "tt", - "te", - "th", - "bo", - "tr", - "tk", - "uk", - "ur", - "uz", - "vi", - "cy", - "yi", - "yo" - ] + } + } + }, + "tags": [ + "Simulations" + ], + "security": [ + { + "bearer": [] + } + ] + }, + "delete": { + "operationId": "SimulationController_remove", + "summary": "Delete Simulation", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "description": "The unique identifier for the resource.", + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Simulation" + } + } + } + } + }, + "tags": [ + "Simulations" + ], + "security": [ + { + "bearer": [] + } + ] + } + }, + "/eval/simulation/concurrency": { + "get": { + "operationId": "SimulationController_getConcurrency", + "summary": "Get Simulation Concurrency", + "parameters": [], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SimulationConcurrencyResponse" + } + } + } + } + }, + "tags": [ + "Simulations" + ], + "security": [ + { + "bearer": [] + } + ] + } + }, + "/reporting/insight": { + "post": { + "operationId": "InsightController_create", + "summary": "Create Insight", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "oneOf": [ + { + "$ref": "#/components/schemas/CreateBarInsightFromCallTableDTO", + "title": "CreateBarInsightFromCallTableDTO" + }, + { + "$ref": "#/components/schemas/CreatePieInsightFromCallTableDTO", + "title": "CreatePieInsightFromCallTableDTO" + }, + { + "$ref": "#/components/schemas/CreateLineInsightFromCallTableDTO", + "title": "CreateLineInsightFromCallTableDTO" + }, + { + "$ref": "#/components/schemas/CreateTextInsightFromCallTableDTO", + "title": "CreateTextInsightFromCallTableDTO" + } + ], + "discriminator": { + "propertyName": "type", + "mapping": { + "bar": "#/components/schemas/CreateBarInsightFromCallTableDTO", + "pie": "#/components/schemas/CreatePieInsightFromCallTableDTO", + "line": "#/components/schemas/CreateLineInsightFromCallTableDTO", + "text": "#/components/schemas/CreateTextInsightFromCallTableDTO" + } + } + } + } + } + }, + "responses": { + "201": { + "description": "", + "content": { + "application/json": { + "schema": { + "oneOf": [ + { + "$ref": "#/components/schemas/BarInsight" + }, + { + "$ref": "#/components/schemas/PieInsight" + }, + { + "$ref": "#/components/schemas/LineInsight" + }, + { + "$ref": "#/components/schemas/TextInsight" + } + ], + "discriminator": { + "propertyName": "type", + "mapping": { + "bar": "#/components/schemas/BarInsight", + "pie": "#/components/schemas/PieInsight", + "line": "#/components/schemas/LineInsight", + "text": "#/components/schemas/TextInsight" + } + } + } + } + } + } + }, + "tags": [ + "Insight" + ], + "security": [ + { + "bearer": [] + } + ] + }, + "get": { + "operationId": "InsightController_findAll", + "summary": "Get Insights", + "parameters": [ + { + "name": "id", + "required": false, + "in": "query", + "schema": { + "type": "string" + } }, - "languages": { - "type": "string", - "description": "Defines the languages to use for the transcription. Required when languageBehaviour is 'manual'.", - "enum": [ - "af", - "sq", - "am", - "ar", - "hy", - "as", - "az", - "ba", - "eu", - "be", - "bn", - "bs", - "br", - "bg", - "ca", - "zh", - "hr", - "cs", - "da", - "nl", - "en", - "et", - "fo", - "fi", - "fr", - "gl", - "ka", - "de", - "el", - "gu", - "ht", - "ha", - "haw", - "he", - "hi", - "hu", - "is", - "id", - "it", - "ja", - "jv", - "kn", - "kk", - "km", - "ko", - "lo", - "la", - "lv", - "ln", - "lt", - "lb", - "mk", - "mg", - "ms", - "ml", - "mt", - "mi", - "mr", - "mn", - "my", - "ne", - "no", - "nn", - "oc", - "ps", - "fa", - "pl", - "pt", - "pa", - "ro", - "ru", - "sa", - "sr", - "sn", - "sd", - "si", - "sk", - "sl", - "so", - "es", - "su", - "sw", - "sv", - "tl", - "tg", - "ta", - "tt", - "te", - "th", - "bo", - "tr", - "tk", - "uk", - "ur", - "uz", - "vi", - "cy", - "yi", - "yo" - ] + { + "name": "page", + "required": false, + "in": "query", + "description": "This is the page number to return. Defaults to 1.", + "schema": { + "minimum": 1, + "type": "number" + } }, - "transcriptionHint": { - "type": "string", - "description": "Provides a custom vocabulary to the model to improve accuracy of transcribing context specific words, technical terms, names, etc. If empty, this argument is ignored.\n⚠️ Warning ⚠️: Please be aware that the transcription_hint field has a character limit of 600. If you provide a transcription_hint longer than 600 characters, it will be automatically truncated to meet this limit.", - "maxLength": 600, - "example": "custom vocabulary" + { + "name": "sortOrder", + "required": false, + "in": "query", + "description": "This is the sort order for pagination. Defaults to 'DESC'.", + "schema": { + "enum": [ + "ASC", + "DESC" + ], + "type": "string" + } }, - "prosody": { - "type": "boolean", - "description": "If prosody is true, you will get a transcription that can contain prosodies i.e. (laugh) (giggles) (malefic laugh) (toss) (music)… Default value is false.", - "example": false + { + "name": "sortBy", + "required": false, + "in": "query", + "description": "This is the column to sort by. Defaults to 'createdAt'.", + "schema": { + "enum": [ + "createdAt", + "duration", + "cost" + ], + "type": "string" + } }, - "audioEnhancer": { - "type": "boolean", - "description": "If true, audio will be pre-processed to improve accuracy but latency will increase. Default value is false.", - "example": false + { + "name": "limit", + "required": false, + "in": "query", + "description": "This is the maximum number of items to return. Defaults to 100.", + "schema": { + "minimum": 0, + "maximum": 1000, + "type": "number" + } }, - "confidenceThreshold": { - "type": "number", - "description": "Transcripts below this confidence threshold will be discarded.\n\n@default 0.4", - "minimum": 0, - "maximum": 1, - "example": 0.4 + { + "name": "createdAtGt", + "required": false, + "in": "query", + "description": "This will return items where the createdAt is greater than the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } }, - "endpointing": { - "type": "number", - "minimum": 0.01, - "maximum": 10, - "example": 0.05, - "description": "Endpointing time in seconds - time to wait before considering speech ended" + { + "name": "createdAtLt", + "required": false, + "in": "query", + "description": "This will return items where the createdAt is less than the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } }, - "speechThreshold": { - "type": "number", - "minimum": 0, - "maximum": 1, - "example": 0.6, - "description": "Speech threshold - sensitivity configuration for speech detection (0.0 to 1.0)" + { + "name": "createdAtGe", + "required": false, + "in": "query", + "description": "This will return items where the createdAt is greater than or equal to the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } }, - "customVocabularyEnabled": { - "type": "boolean", - "example": false, - "description": "Enable custom vocabulary for improved accuracy" + { + "name": "createdAtLe", + "required": false, + "in": "query", + "description": "This will return items where the createdAt is less than or equal to the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } }, - "customVocabularyConfig": { - "description": "Custom vocabulary configuration", - "allOf": [ - { - "$ref": "#/components/schemas/GladiaCustomVocabularyConfigDTO" - } - ] + { + "name": "updatedAtGt", + "required": false, + "in": "query", + "description": "This will return items where the updatedAt is greater than the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } }, - "fallbackPlan": { - "description": "This is the plan for voice provider fallbacks in the event that the primary voice provider fails.", - "allOf": [ - { - "$ref": "#/components/schemas/FallbackTranscriberPlan" + { + "name": "updatedAtLt", + "required": false, + "in": "query", + "description": "This will return items where the updatedAt is less than the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } + }, + { + "name": "updatedAtGe", + "required": false, + "in": "query", + "description": "This will return items where the updatedAt is greater than or equal to the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } + }, + { + "name": "updatedAtLe", + "required": false, + "in": "query", + "description": "This will return items where the updatedAt is less than or equal to the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InsightPaginatedResponse" + } } - ] + } } }, - "required": [ - "provider" - ] - }, - "SpeechmaticsTranscriber": { - "type": "object", - "properties": { - "provider": { - "type": "string", - "description": "This is the transcription provider that will be used.", - "enum": [ - "speechmatics" - ] - }, - "model": { - "type": "string", - "description": "This is the model that will be used for the transcription.", - "enum": [ - "default" - ] - }, - "language": { - "type": "string", - "enum": [ - "auto", - "ar", - "ba", - "eu", - "be", - "bn", - "bg", - "yue", - "ca", - "hr", - "cs", - "da", - "nl", - "en", - "eo", - "et", - "fi", - "fr", - "gl", - "de", - "el", - "he", - "hi", - "hu", - "id", - "ia", - "ga", - "it", - "ja", - "ko", - "lv", - "lt", - "ms", - "mt", - "cmn", - "mr", - "mn", - "no", - "fa", - "pl", - "pt", - "ro", - "ru", - "sk", - "sl", - "es", - "sw", - "sv", - "ta", - "th", - "tr", - "uk", - "ur", - "ug", - "vi", - "cy" - ] - }, - "fallbackPlan": { - "description": "This is the plan for voice provider fallbacks in the event that the primary voice provider fails.", - "allOf": [ - { - "$ref": "#/components/schemas/FallbackTranscriberPlan" - } - ] + "tags": [ + "Insight" + ], + "security": [ + { + "bearer": [] } - }, - "required": [ - "provider" ] - }, - "TalkscriberTranscriber": { - "type": "object", - "properties": { - "provider": { - "type": "string", - "description": "This is the transcription provider that will be used.", - "enum": [ - "talkscriber" - ] - }, - "model": { - "type": "string", - "description": "This is the model that will be used for the transcription.", - "enum": [ - "whisper" - ] - }, - "language": { - "type": "string", - "description": "This is the language that will be set for the transcription. The list of languages Whisper supports can be found here: https://github.com/openai/whisper/blob/main/whisper/tokenizer.py", - "enum": [ - "en", - "zh", - "de", - "es", - "ru", - "ko", - "fr", - "ja", - "pt", - "tr", - "pl", - "ca", - "nl", - "ar", - "sv", - "it", - "id", - "hi", - "fi", - "vi", - "he", - "uk", - "el", - "ms", - "cs", - "ro", - "da", - "hu", - "ta", - "no", - "th", - "ur", - "hr", - "bg", - "lt", - "la", - "mi", - "ml", - "cy", - "sk", - "te", - "fa", - "lv", - "bn", - "sr", - "az", - "sl", - "kn", - "et", - "mk", - "br", - "eu", - "is", - "hy", - "ne", - "mn", - "bs", - "kk", - "sq", - "sw", - "gl", - "mr", - "pa", - "si", - "km", - "sn", - "yo", - "so", - "af", - "oc", - "ka", - "be", - "tg", - "sd", - "gu", - "am", - "yi", - "lo", - "uz", - "fo", - "ht", - "ps", - "tk", - "nn", - "mt", - "sa", - "lb", - "my", - "bo", - "tl", - "mg", - "as", - "tt", - "haw", - "ln", - "ha", - "ba", - "jw", - "su", - "yue" - ] - }, - "fallbackPlan": { - "description": "This is the plan for voice provider fallbacks in the event that the primary voice provider fails.", - "allOf": [ - { - "$ref": "#/components/schemas/FallbackTranscriberPlan" + } + }, + "/reporting/insight/{id}": { + "patch": { + "operationId": "InsightController_update", + "summary": "Update Insight", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "description": "The unique identifier for the resource.", + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "oneOf": [ + { + "$ref": "#/components/schemas/UpdateBarInsightFromCallTableDTO", + "title": "UpdateBarInsightFromCallTableDTO" + }, + { + "$ref": "#/components/schemas/UpdatePieInsightFromCallTableDTO", + "title": "UpdatePieInsightFromCallTableDTO" + }, + { + "$ref": "#/components/schemas/UpdateLineInsightFromCallTableDTO", + "title": "UpdateLineInsightFromCallTableDTO" + }, + { + "$ref": "#/components/schemas/UpdateTextInsightFromCallTableDTO", + "title": "UpdateTextInsightFromCallTableDTO" + } + ], + "discriminator": { + "propertyName": "type", + "mapping": { + "bar": "#/components/schemas/UpdateBarInsightFromCallTableDTO", + "pie": "#/components/schemas/UpdatePieInsightFromCallTableDTO", + "line": "#/components/schemas/UpdateLineInsightFromCallTableDTO", + "text": "#/components/schemas/UpdateTextInsightFromCallTableDTO" + } + } } - ] + } } }, - "required": [ - "provider" - ] - }, - "GoogleTranscriber": { - "type": "object", - "properties": { - "provider": { - "type": "string", - "description": "This is the transcription provider that will be used.", - "enum": [ - "google" - ] - }, - "model": { - "type": "string", - "description": "This is the model that will be used for the transcription.", - "enum": [ - "gemini-2.5-pro", - "gemini-2.5-flash", - "gemini-2.5-flash-lite", - "gemini-2.0-flash-thinking-exp", - "gemini-2.0-pro-exp-02-05", - "gemini-2.0-flash", - "gemini-2.0-flash-lite", - "gemini-2.0-flash-exp", - "gemini-2.0-flash-realtime-exp", - "gemini-1.5-flash", - "gemini-1.5-flash-002", - "gemini-1.5-pro", - "gemini-1.5-pro-002", - "gemini-1.0-pro" - ] - }, - "language": { - "type": "string", - "description": "This is the language that will be set for the transcription.", - "enum": [ - "Multilingual", - "Arabic", - "Bengali", - "Bulgarian", - "Chinese", - "Croatian", - "Czech", - "Danish", - "Dutch", - "English", - "Estonian", - "Finnish", - "French", - "German", - "Greek", - "Hebrew", - "Hindi", - "Hungarian", - "Indonesian", - "Italian", - "Japanese", - "Korean", - "Latvian", - "Lithuanian", - "Norwegian", - "Polish", - "Portuguese", - "Romanian", - "Russian", - "Serbian", - "Slovak", - "Slovenian", - "Spanish", - "Swahili", - "Swedish", - "Thai", - "Turkish", - "Ukrainian", - "Vietnamese" - ] - }, - "fallbackPlan": { - "description": "This is the plan for voice provider fallbacks in the event that the primary voice provider fails.", - "allOf": [ - { - "$ref": "#/components/schemas/FallbackTranscriberPlan" + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "oneOf": [ + { + "$ref": "#/components/schemas/BarInsight" + }, + { + "$ref": "#/components/schemas/PieInsight" + }, + { + "$ref": "#/components/schemas/LineInsight" + }, + { + "$ref": "#/components/schemas/TextInsight" + } + ], + "discriminator": { + "propertyName": "type", + "mapping": { + "bar": "#/components/schemas/BarInsight", + "pie": "#/components/schemas/PieInsight", + "line": "#/components/schemas/LineInsight", + "text": "#/components/schemas/TextInsight" + } + } + } } - ] + } } }, - "required": [ - "provider" + "tags": [ + "Insight" + ], + "security": [ + { + "bearer": [] + } ] }, - "OpenAITranscriber": { - "type": "object", - "properties": { - "provider": { - "type": "string", - "description": "This is the transcription provider that will be used.", - "enum": [ - "openai" - ] - }, - "model": { - "type": "string", - "description": "This is the model that will be used for the transcription.", - "enum": [ - "gpt-4o-transcribe", - "gpt-4o-mini-transcribe" - ] - }, - "language": { - "type": "string", - "description": "This is the language that will be set for the transcription.", - "enum": [ - "af", - "ar", - "hy", - "az", - "be", - "bs", - "bg", - "ca", - "zh", - "hr", - "cs", - "da", - "nl", - "en", - "et", - "fi", - "fr", - "gl", - "de", - "el", - "he", - "hi", - "hu", - "is", - "id", - "it", - "ja", - "kn", - "kk", - "ko", - "lv", - "lt", - "mk", - "ms", - "mr", - "mi", - "ne", - "no", - "fa", - "pl", - "pt", - "ro", - "ru", - "sr", - "sk", - "sl", - "es", - "sw", - "sv", - "tl", - "ta", - "th", - "tr", - "uk", - "ur", - "vi", - "cy" - ] - }, - "fallbackPlan": { - "description": "This is the plan for voice provider fallbacks in the event that the primary voice provider fails.", - "allOf": [ - { - "$ref": "#/components/schemas/FallbackTranscriberPlan" + "get": { + "operationId": "InsightController_findOne", + "summary": "Get Insight", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "description": "The unique identifier for the resource.", + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "oneOf": [ + { + "$ref": "#/components/schemas/BarInsight" + }, + { + "$ref": "#/components/schemas/PieInsight" + }, + { + "$ref": "#/components/schemas/LineInsight" + }, + { + "$ref": "#/components/schemas/TextInsight" + } + ], + "discriminator": { + "propertyName": "type", + "mapping": { + "bar": "#/components/schemas/BarInsight", + "pie": "#/components/schemas/PieInsight", + "line": "#/components/schemas/LineInsight", + "text": "#/components/schemas/TextInsight" + } + } + } } - ] + } } }, - "required": [ - "provider", - "model" + "tags": [ + "Insight" + ], + "security": [ + { + "bearer": [] + } ] }, - "FallbackAssemblyAITranscriber": { - "type": "object", - "properties": { - "provider": { - "type": "string", - "description": "This is the transcription provider that will be used.", - "enum": [ - "assembly-ai" - ] - }, - "language": { - "type": "string", - "description": "This is the language that will be set for the transcription.", - "enum": [ - "en" - ] + "delete": { + "operationId": "InsightController_remove", + "summary": "Delete Insight", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "description": "The unique identifier for the resource.", + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "oneOf": [ + { + "$ref": "#/components/schemas/BarInsight" + }, + { + "$ref": "#/components/schemas/PieInsight" + }, + { + "$ref": "#/components/schemas/LineInsight" + }, + { + "$ref": "#/components/schemas/TextInsight" + } + ], + "discriminator": { + "propertyName": "type", + "mapping": { + "bar": "#/components/schemas/BarInsight", + "pie": "#/components/schemas/PieInsight", + "line": "#/components/schemas/LineInsight", + "text": "#/components/schemas/TextInsight" + } + } + } + } + } + } + }, + "tags": [ + "Insight" + ], + "security": [ + { + "bearer": [] + } + ] + } + }, + "/reporting/insight/{id}/run": { + "post": { + "operationId": "InsightController_run", + "summary": "Run Insight", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "description": "The unique identifier for the resource.", + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InsightRunDTO" + } + } + } + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InsightRunResponse" + } + } + } }, - "confidenceThreshold": { - "type": "number", - "description": "Transcripts below this confidence threshold will be discarded.\n\n@default 0.4", - "minimum": 0, - "maximum": 1, - "example": 0.4 + "201": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InsightRunResponse" + } + } + } + } + }, + "tags": [ + "Insight" + ], + "security": [ + { + "bearer": [] + } + ] + } + }, + "/reporting/insight/preview": { + "post": { + "operationId": "InsightController_preview", + "summary": "Preview Insight", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "oneOf": [ + { + "$ref": "#/components/schemas/CreateBarInsightFromCallTableDTO", + "title": "CreateBarInsightFromCallTableDTO" + }, + { + "$ref": "#/components/schemas/CreatePieInsightFromCallTableDTO", + "title": "CreatePieInsightFromCallTableDTO" + }, + { + "$ref": "#/components/schemas/CreateLineInsightFromCallTableDTO", + "title": "CreateLineInsightFromCallTableDTO" + }, + { + "$ref": "#/components/schemas/CreateTextInsightFromCallTableDTO", + "title": "CreateTextInsightFromCallTableDTO" + } + ], + "discriminator": { + "propertyName": "type", + "mapping": { + "bar": "#/components/schemas/CreateBarInsightFromCallTableDTO", + "pie": "#/components/schemas/CreatePieInsightFromCallTableDTO", + "line": "#/components/schemas/CreateLineInsightFromCallTableDTO", + "text": "#/components/schemas/CreateTextInsightFromCallTableDTO" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InsightRunResponse" + } + } + } }, - "formatTurns": { - "type": "boolean", - "description": "This enables formatting of transcripts.\n\n@default true", - "example": true + "201": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InsightRunResponse" + } + } + } + } + }, + "tags": [ + "Insight" + ], + "security": [ + { + "bearer": [] + } + ] + } + }, + "/reporting/board": { + "post": { + "operationId": "BoardController_create", + "summary": "Create Board", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateBoardDTO" + } + } + } + }, + "responses": { + "201": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Board" + } + } + } + } + }, + "tags": [ + "Board" + ], + "security": [ + { + "bearer": [] + } + ] + }, + "get": { + "operationId": "BoardController_findAll", + "summary": "Get Boards", + "parameters": [ + { + "name": "page", + "required": false, + "in": "query", + "description": "This is the page number to return. Defaults to 1.", + "schema": { + "minimum": 1, + "type": "number" + } }, - "endOfTurnConfidenceThreshold": { - "type": "number", - "description": "This is the end of turn confidence threshold. The minimum confidence that the end of turn is detected.\n\n@min 0\n@max 1\n@default 0.7", - "minimum": 0, - "maximum": 1, - "example": 0.7 + { + "name": "sortOrder", + "required": false, + "in": "query", + "description": "This is the sort order for pagination. Defaults to 'DESC'.", + "schema": { + "enum": [ + "ASC", + "DESC" + ], + "type": "string" + } }, - "minEndOfTurnSilenceWhenConfident": { - "type": "number", - "description": "This is the minimum end of turn silence when confident in milliseconds.\n\n@default 160", - "minimum": 0, - "example": 160 + { + "name": "sortBy", + "required": false, + "in": "query", + "description": "This is the column to sort by. Defaults to 'createdAt'.", + "schema": { + "enum": [ + "createdAt", + "duration", + "cost" + ], + "type": "string" + } }, - "wordFinalizationMaxWaitTime": { - "type": "number", - "description": "This is the maximum wait time for word finalization in milliseconds.\n\n@default 160", - "minimum": 0, - "example": 160 + { + "name": "limit", + "required": false, + "in": "query", + "description": "This is the maximum number of items to return. Defaults to 100.", + "schema": { + "minimum": 0, + "maximum": 1000, + "type": "number" + } }, - "maxTurnSilence": { - "type": "number", - "description": "This is the maximum turn silence time in milliseconds.\n\n@default 400", - "minimum": 0, - "example": 400 + { + "name": "createdAtGt", + "required": false, + "in": "query", + "description": "This will return items where the createdAt is greater than the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } }, - "realtimeUrl": { - "type": "string", - "description": "The WebSocket URL that the transcriber connects to." + { + "name": "createdAtLt", + "required": false, + "in": "query", + "description": "This will return items where the createdAt is less than the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } }, - "wordBoost": { - "description": "Add up to 2500 characters of custom vocabulary.", - "type": "array", - "items": { - "type": "string", - "maxLength": 2500 + { + "name": "createdAtGe", + "required": false, + "in": "query", + "description": "This will return items where the createdAt is greater than or equal to the specified value.", + "schema": { + "format": "date-time", + "type": "string" } }, - "endUtteranceSilenceThreshold": { - "type": "number", - "description": "The duration of the end utterance silence threshold in milliseconds." + { + "name": "createdAtLe", + "required": false, + "in": "query", + "description": "This will return items where the createdAt is less than or equal to the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } }, - "disablePartialTranscripts": { - "type": "boolean", - "description": "Disable partial transcripts.\nSet to `true` to not receive partial transcripts. Defaults to `false`." + { + "name": "updatedAtGt", + "required": false, + "in": "query", + "description": "This will return items where the updatedAt is greater than the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } + }, + { + "name": "updatedAtLt", + "required": false, + "in": "query", + "description": "This will return items where the updatedAt is less than the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } + }, + { + "name": "updatedAtGe", + "required": false, + "in": "query", + "description": "This will return items where the updatedAt is greater than or equal to the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } + }, + { + "name": "updatedAtLe", + "required": false, + "in": "query", + "description": "This will return items where the updatedAt is less than or equal to the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BoardPaginatedResponse" + } + } + } } }, - "required": [ - "provider" + "tags": [ + "Board" + ], + "security": [ + { + "bearer": [] + } + ] + } + }, + "/reporting/board/default/metrics-overview": { + "get": { + "operationId": "BoardController_metricsOverviewEnsure", + "summary": "Get Default Metrics Overview Board", + "parameters": [], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Board" + } + } + } + } + }, + "tags": [ + "Board" + ], + "security": [ + { + "bearer": [] + } + ] + } + }, + "/reporting/board/{id}": { + "patch": { + "operationId": "BoardController_update", + "summary": "Update Board", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "description": "The unique identifier for the resource.", + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateBoardDTO" + } + } + } + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Board" + } + } + } + } + }, + "tags": [ + "Board" + ], + "security": [ + { + "bearer": [] + } ] }, - "FallbackAzureSpeechTranscriber": { - "type": "object", - "properties": { - "provider": { - "type": "string", - "description": "This is the transcription provider that will be used.", - "enum": [ - "azure" - ] - }, - "language": { - "type": "string", - "description": "This is the language that will be set for the transcription. The list of languages Azure supports can be found here: https://learn.microsoft.com/en-us/azure/ai-services/speech-service/language-support?tabs=stt", - "enum": [ - "af-ZA", - "am-ET", - "ar-AE", - "ar-BH", - "ar-DZ", - "ar-EG", - "ar-IL", - "ar-IQ", - "ar-JO", - "ar-KW", - "ar-LB", - "ar-LY", - "ar-MA", - "ar-OM", - "ar-PS", - "ar-QA", - "ar-SA", - "ar-SY", - "ar-TN", - "ar-YE", - "az-AZ", - "bg-BG", - "bn-IN", - "bs-BA", - "ca-ES", - "cs-CZ", - "cy-GB", - "da-DK", - "de-AT", - "de-CH", - "de-DE", - "el-GR", - "en-AU", - "en-CA", - "en-GB", - "en-GH", - "en-HK", - "en-IE", - "en-IN", - "en-KE", - "en-NG", - "en-NZ", - "en-PH", - "en-SG", - "en-TZ", - "en-US", - "en-ZA", - "es-AR", - "es-BO", - "es-CL", - "es-CO", - "es-CR", - "es-CU", - "es-DO", - "es-EC", - "es-ES", - "es-GQ", - "es-GT", - "es-HN", - "es-MX", - "es-NI", - "es-PA", - "es-PE", - "es-PR", - "es-PY", - "es-SV", - "es-US", - "es-UY", - "es-VE", - "et-EE", - "eu-ES", - "fa-IR", - "fi-FI", - "fil-PH", - "fr-BE", - "fr-CA", - "fr-CH", - "fr-FR", - "ga-IE", - "gl-ES", - "gu-IN", - "he-IL", - "hi-IN", - "hr-HR", - "hu-HU", - "hy-AM", - "id-ID", - "is-IS", - "it-CH", - "it-IT", - "ja-JP", - "jv-ID", - "ka-GE", - "kk-KZ", - "km-KH", - "kn-IN", - "ko-KR", - "lo-LA", - "lt-LT", - "lv-LV", - "mk-MK", - "ml-IN", - "mn-MN", - "mr-IN", - "ms-MY", - "mt-MT", - "my-MM", - "nb-NO", - "ne-NP", - "nl-BE", - "nl-NL", - "pa-IN", - "pl-PL", - "ps-AF", - "pt-BR", - "pt-PT", - "ro-RO", - "ru-RU", - "si-LK", - "sk-SK", - "sl-SI", - "so-SO", - "sq-AL", - "sr-RS", - "sv-SE", - "sw-KE", - "sw-TZ", - "ta-IN", - "te-IN", - "th-TH", - "tr-TR", - "uk-UA", - "ur-IN", - "uz-UZ", - "vi-VN", - "wuu-CN", - "yue-CN", - "zh-CN", - "zh-CN-shandong", - "zh-CN-sichuan", - "zh-HK", - "zh-TW", - "zu-ZA" - ] - }, - "segmentationStrategy": { - "type": "string", - "description": "Controls how phrase boundaries are detected, enabling either simple time/silence heuristics or more advanced semantic segmentation.", - "enum": [ - "Default", - "Time", - "Semantic" - ] - }, - "segmentationSilenceTimeoutMs": { - "type": "number", - "description": "Duration of detected silence after which the service finalizes a phrase. Configure to adjust sensitivity to pauses in speech.", - "minimum": 100, - "maximum": 5000 - }, - "segmentationMaximumTimeMs": { - "type": "number", - "description": "Maximum duration a segment can reach before being cut off when using time-based segmentation.", - "minimum": 20000, - "maximum": 70000 + "get": { + "operationId": "BoardController_findOne", + "summary": "Get Board", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "description": "The unique identifier for the resource.", + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Board" + } + } + } } }, - "required": [ - "provider" + "tags": [ + "Board" + ], + "security": [ + { + "bearer": [] + } ] }, - "FallbackCartesiaTranscriber": { - "type": "object", - "properties": { - "provider": { - "type": "string", - "enum": [ - "cartesia" - ] - }, - "model": { - "type": "string", - "enum": [ - "ink-whisper" - ] - }, - "language": { - "type": "string", - "enum": [ - "aa", - "ab", - "ae", - "af", - "ak", - "am", - "an", - "ar", - "as", - "av", - "ay", - "az", - "ba", - "be", - "bg", - "bh", - "bi", - "bm", - "bn", - "bo", - "br", - "bs", - "ca", - "ce", - "ch", - "co", - "cr", - "cs", - "cu", - "cv", - "cy", - "da", - "de", - "dv", - "dz", - "ee", - "el", - "en", - "eo", - "es", - "et", - "eu", - "fa", - "ff", - "fi", - "fj", - "fo", - "fr", - "fy", - "ga", - "gd", - "gl", - "gn", - "gu", - "gv", - "ha", - "he", - "hi", - "ho", - "hr", - "ht", - "hu", - "hy", - "hz", - "ia", - "id", - "ie", - "ig", - "ii", - "ik", - "io", - "is", - "it", - "iu", - "ja", - "jv", - "ka", - "kg", - "ki", - "kj", - "kk", - "kl", - "km", - "kn", - "ko", - "kr", - "ks", - "ku", - "kv", - "kw", - "ky", - "la", - "lb", - "lg", - "li", - "ln", - "lo", - "lt", - "lu", - "lv", - "mg", - "mh", - "mi", - "mk", - "ml", - "mn", - "mr", - "ms", - "mt", - "my", - "na", - "nb", - "nd", - "ne", - "ng", - "nl", - "nn", - "no", - "nr", - "nv", - "ny", - "oc", - "oj", - "om", - "or", - "os", - "pa", - "pi", - "pl", - "ps", - "pt", - "qu", - "rm", - "rn", - "ro", - "ru", - "rw", - "sa", - "sc", - "sd", - "se", - "sg", - "si", - "sk", - "sl", - "sm", - "sn", - "so", - "sq", - "sr", - "ss", - "st", - "su", - "sv", - "sw", - "ta", - "te", - "tg", - "th", - "ti", - "tk", - "tl", - "tn", - "to", - "tr", - "ts", - "tt", - "tw", - "ty", - "ug", - "uk", - "ur", - "uz", - "ve", - "vi", - "vo", - "wa", - "wo", - "xh", - "yi", - "yue", - "yo", - "za", - "zh", - "zu" - ] + "delete": { + "operationId": "BoardController_remove", + "summary": "Delete Board", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "description": "The unique identifier for the resource.", + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Board" + } + } + } } }, - "required": [ - "provider" + "tags": [ + "Board" + ], + "security": [ + { + "bearer": [] + } ] - }, - "FallbackCustomTranscriber": { - "type": "object", - "properties": { - "provider": { - "type": "string", - "description": "This is the transcription provider that will be used. Use `custom-transcriber` for providers that are not natively supported.", - "enum": [ - "custom-transcriber" - ] - }, - "server": { - "description": "This is where the transcription request will be sent.\n\nUsage:\n1. Vapi will initiate a websocket connection with `server.url`.\n\n2. Vapi will send an initial text frame with the sample rate. Format:\n```\n {\n \"type\": \"start\",\n \"encoding\": \"linear16\", // 16-bit raw PCM format\n \"container\": \"raw\",\n \"sampleRate\": {{sampleRate}},\n \"channels\": 2 // customer is channel 0, assistant is channel 1\n }\n```\n\n3. Vapi will send the audio data in 16-bit raw PCM format as binary frames.\n\n4. You can read the messages something like this:\n```\nws.on('message', (data, isBinary) => {\n if (isBinary) {\n pcmBuffer = Buffer.concat([pcmBuffer, data]);\n console.log(`Received PCM data, buffer size: ${pcmBuffer.length}`);\n } else {\n console.log('Received message:', JSON.parse(data.toString()));\n }\n});\n```\n\n5. You will respond with transcriptions as you have them. Format:\n```\n {\n \"type\": \"transcriber-response\",\n \"transcription\": \"Hello, world!\",\n \"channel\": \"customer\" | \"assistant\"\n }\n```", - "allOf": [ - { - "$ref": "#/components/schemas/Server" + } + }, + "/eval": { + "post": { + "operationId": "EvalController_create", + "summary": "Create Eval", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateEvalDTO" } - ] + } } }, - "required": [ - "provider", - "server" + "responses": { + "201": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Eval" + } + } + } + } + }, + "tags": [ + "Eval" + ], + "security": [ + { + "bearer": [] + } ] }, - "FallbackDeepgramTranscriber": { - "type": "object", - "properties": { - "provider": { - "type": "string", - "description": "This is the transcription provider that will be used.", - "enum": [ - "deepgram" - ] + "get": { + "operationId": "EvalController_getPaginated", + "summary": "List Evals", + "parameters": [ + { + "name": "id", + "required": false, + "in": "query", + "schema": { + "type": "string" + } }, - "model": { - "description": "This is the Deepgram model that will be used. A list of models can be found here: https://developers.deepgram.com/docs/models-languages-overview", - "oneOf": [ - { - "type": "string", - "enum": [ - "nova-3", - "nova-3-general", - "nova-3-medical", - "nova-2", - "nova-2-general", - "nova-2-meeting", - "nova-2-phonecall", - "nova-2-finance", - "nova-2-conversationalai", - "nova-2-voicemail", - "nova-2-video", - "nova-2-medical", - "nova-2-drivethru", - "nova-2-automotive", - "nova", - "nova-general", - "nova-phonecall", - "nova-medical", - "enhanced", - "enhanced-general", - "enhanced-meeting", - "enhanced-phonecall", - "enhanced-finance", - "base", - "base-general", - "base-meeting", - "base-phonecall", - "base-finance", - "base-conversationalai", - "base-voicemail", - "base-video", - "whisper" - ] - }, - { - "type": "string" - } - ] + { + "name": "page", + "required": false, + "in": "query", + "description": "This is the page number to return. Defaults to 1.", + "schema": { + "minimum": 1, + "type": "number" + } }, - "language": { - "type": "string", - "description": "This is the language that will be set for the transcription. The list of languages Deepgram supports can be found here: https://developers.deepgram.com/docs/models-languages-overview", - "enum": [ - "ar", - "az", - "ba", - "bg", - "br", - "ca", - "cs", - "da", - "da-DK", - "de", - "de-CH", - "el", - "en", - "en-AU", - "en-CA", - "en-GB", - "en-IE", - "en-IN", - "en-NZ", - "en-US", - "es", - "es-419", - "es-LATAM", - "et", - "eu", - "fi", - "fr", - "fr-CA", - "ha", - "haw", - "he", - "hi", - "hi-Latn", - "hu", - "id", - "is", - "it", - "ja", - "jw", - "kn", - "ko", - "ko-KR", - "ln", - "lt", - "lv", - "mk", - "ms", - "multi", - "nl", - "nl-BE", - "no", - "pl", - "pt", - "pt-BR", - "ro", - "ru", - "sk", - "sl", - "sn", - "so", - "sr", - "su", - "sv", - "sv-SE", - "ta", - "taq", - "th", - "th-TH", - "tr", - "tt", - "uk", - "ur", - "vi", - "yo", - "zh", - "zh-CN", - "zh-HK", - "zh-Hans", - "zh-Hant", - "zh-TW" - ] + { + "name": "sortOrder", + "required": false, + "in": "query", + "description": "This is the sort order for pagination. Defaults to 'DESC'.", + "schema": { + "enum": [ + "ASC", + "DESC" + ], + "type": "string" + } }, - "smartFormat": { - "type": "boolean", - "description": "This will be use smart format option provided by Deepgram. It's default disabled because it can sometimes format numbers as times but it's getting better.", - "example": false + { + "name": "sortBy", + "required": false, + "in": "query", + "description": "This is the column to sort by. Defaults to 'createdAt'.", + "schema": { + "enum": [ + "createdAt", + "duration", + "cost" + ], + "type": "string" + } }, - "mipOptOut": { - "type": "boolean", - "description": "If set to true, this will add mip_opt_out=true as a query parameter of all API requests. See https://developers.deepgram.com/docs/the-deepgram-model-improvement-partnership-program#want-to-opt-out\n\nThis will only be used if you are using your own Deepgram API key.\n\n@default false", - "example": false, - "default": false + { + "name": "limit", + "required": false, + "in": "query", + "description": "This is the maximum number of items to return. Defaults to 100.", + "schema": { + "minimum": 0, + "maximum": 1000, + "type": "number" + } }, - "numerals": { - "type": "boolean", - "description": "If set to true, this will cause deepgram to convert spoken numbers to literal numerals. For example, \"my phone number is nine-seven-two...\" would become \"my phone number is 972...\"\n\n@default false", - "example": false + { + "name": "createdAtGt", + "required": false, + "in": "query", + "description": "This will return items where the createdAt is greater than the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } }, - "confidenceThreshold": { - "type": "number", - "description": "Transcripts below this confidence threshold will be discarded.\n\n@default 0.4", - "minimum": 0, - "maximum": 1, - "example": 0.4 + { + "name": "createdAtLt", + "required": false, + "in": "query", + "description": "This will return items where the createdAt is less than the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } }, - "keywords": { - "description": "These keywords are passed to the transcription model to help it pick up use-case specific words. Anything that may not be a common word, like your company name, should be added here.", - "type": "array", - "items": { - "type": "string", - "pattern": "/^\\p{L}[\\p{L}\\d]*(?::[+-]?\\d+)?$/u" + { + "name": "createdAtGe", + "required": false, + "in": "query", + "description": "This will return items where the createdAt is greater than or equal to the specified value.", + "schema": { + "format": "date-time", + "type": "string" } }, - "keyterm": { - "description": "Keyterm Prompting allows you improve Keyword Recall Rate (KRR) for important keyterms or phrases up to 90%.", - "type": "array", - "items": { + { + "name": "createdAtLe", + "required": false, + "in": "query", + "description": "This will return items where the createdAt is less than or equal to the specified value.", + "schema": { + "format": "date-time", "type": "string" } }, - "endpointing": { - "type": "number", - "description": "This is the timeout after which Deepgram will send transcription on user silence. You can read in-depth documentation here: https://developers.deepgram.com/docs/endpointing.\n\nHere are the most important bits:\n- Defaults to 10. This is recommended for most use cases to optimize for latency.\n- 10 can cause some missing transcriptions since because of the shorter context. This mostly happens for one-word utterances. For those uses cases, it's recommended to try 300. It will add a bit of latency but the quality and reliability of the experience will be better.\n- If neither 10 nor 300 work, contact support@vapi.ai and we'll find another solution.\n\n@default 10", - "minimum": 10, - "maximum": 500 + { + "name": "updatedAtGt", + "required": false, + "in": "query", + "description": "This will return items where the updatedAt is greater than the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } + }, + { + "name": "updatedAtLt", + "required": false, + "in": "query", + "description": "This will return items where the updatedAt is less than the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } + }, + { + "name": "updatedAtGe", + "required": false, + "in": "query", + "description": "This will return items where the updatedAt is greater than or equal to the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } + }, + { + "name": "updatedAtLe", + "required": false, + "in": "query", + "description": "This will return items where the updatedAt is less than or equal to the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalPaginatedResponse" + } + } + } } }, - "required": [ - "provider" + "tags": [ + "Eval" + ], + "security": [ + { + "bearer": [] + } ] - }, - "FallbackElevenLabsTranscriber": { - "type": "object", - "properties": { - "provider": { - "type": "string", - "description": "This is the transcription provider that will be used.", - "enum": [ - "11labs" - ] - }, - "model": { - "type": "string", - "description": "This is the model that will be used for the transcription.", - "enum": [ - "scribe_v1" - ] - }, - "language": { - "type": "string", - "enum": [ - "aa", - "ab", - "ae", - "af", - "ak", - "am", - "an", - "ar", - "as", - "av", - "ay", - "az", - "ba", - "be", - "bg", - "bh", - "bi", - "bm", - "bn", - "bo", - "br", - "bs", - "ca", - "ce", - "ch", - "co", - "cr", - "cs", - "cu", - "cv", - "cy", - "da", - "de", - "dv", - "dz", - "ee", - "el", - "en", - "eo", - "es", - "et", - "eu", - "fa", - "ff", - "fi", - "fj", - "fo", - "fr", - "fy", - "ga", - "gd", - "gl", - "gn", - "gu", - "gv", - "ha", - "he", - "hi", - "ho", - "hr", - "ht", - "hu", - "hy", - "hz", - "ia", - "id", - "ie", - "ig", - "ii", - "ik", - "io", - "is", - "it", - "iu", - "ja", - "jv", - "ka", - "kg", - "ki", - "kj", - "kk", - "kl", - "km", - "kn", - "ko", - "kr", - "ks", - "ku", - "kv", - "kw", - "ky", - "la", - "lb", - "lg", - "li", - "ln", - "lo", - "lt", - "lu", - "lv", - "mg", - "mh", - "mi", - "mk", - "ml", - "mn", - "mr", - "ms", - "mt", - "my", - "na", - "nb", - "nd", - "ne", - "ng", - "nl", - "nn", - "no", - "nr", - "nv", - "ny", - "oc", - "oj", - "om", - "or", - "os", - "pa", - "pi", - "pl", - "ps", - "pt", - "qu", - "rm", - "rn", - "ro", - "ru", - "rw", - "sa", - "sc", - "sd", - "se", - "sg", - "si", - "sk", - "sl", - "sm", - "sn", - "so", - "sq", - "sr", - "ss", - "st", - "su", - "sv", - "sw", - "ta", - "te", - "tg", - "th", - "ti", - "tk", - "tl", - "tn", - "to", - "tr", - "ts", - "tt", - "tw", - "ty", - "ug", - "uk", - "ur", - "uz", - "ve", - "vi", - "vo", - "wa", - "wo", - "xh", - "yi", - "yue", - "yo", - "za", - "zh", - "zu" - ] + } + }, + "/eval/{id}": { + "patch": { + "operationId": "EvalController_update", + "summary": "Update Eval", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "description": "The unique identifier for the resource.", + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateEvalDTO" + } + } } }, - "required": [ - "provider" + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Eval" + } + } + } + } + }, + "tags": [ + "Eval" + ], + "security": [ + { + "bearer": [] + } ] }, - "GladiaVocabularyItemDTO": { - "type": "object", - "properties": { - "value": { - "type": "string", - "description": "The vocabulary word or phrase" - }, - "pronunciations": { - "description": "Alternative pronunciations for the vocabulary item", - "type": "array", - "items": { + "delete": { + "operationId": "EvalController_remove", + "summary": "Delete Eval", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "description": "The unique identifier for the resource.", + "schema": { + "format": "uuid", "type": "string" } - }, - "intensity": { - "type": "number", - "minimum": 0, - "maximum": 1, - "description": "Intensity for this specific vocabulary item (0.0 to 1.0)" - }, - "language": { - "type": "string", - "description": "Language code for this vocabulary item (ISO 639-1)" + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Eval" + } + } + } } }, - "required": [ - "value" + "tags": [ + "Eval" + ], + "security": [ + { + "bearer": [] + } ] }, - "FallbackGladiaTranscriber": { - "type": "object", - "properties": { - "provider": { - "type": "string", - "description": "This is the transcription provider that will be used.", - "enum": [ - "gladia" - ] - }, - "model": { - "description": "This is the Gladia model that will be used. Default is 'fast'", - "oneOf": [ - { - "enum": [ - "fast", - "accurate", - "solaria-1" - ] - } - ] - }, - "languageBehaviour": { - "description": "Defines how the transcription model detects the audio language. Default value is 'automatic single language'.", - "oneOf": [ - { - "type": "string", - "enum": [ - "manual", - "automatic single language", - "automatic multiple languages" - ] + "get": { + "operationId": "EvalController_get", + "summary": "Get Eval", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "description": "The unique identifier for the resource.", + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Eval" + } } - ] - }, - "language": { - "type": "string", - "description": "Defines the language to use for the transcription. Required when languageBehaviour is 'manual'.", - "enum": [ - "af", - "sq", - "am", - "ar", - "hy", - "as", - "az", - "ba", - "eu", - "be", - "bn", - "bs", - "br", - "bg", - "ca", - "zh", - "hr", - "cs", - "da", - "nl", - "en", - "et", - "fo", - "fi", - "fr", - "gl", - "ka", - "de", - "el", - "gu", - "ht", - "ha", - "haw", - "he", - "hi", - "hu", - "is", - "id", - "it", - "ja", - "jv", - "kn", - "kk", - "km", - "ko", - "lo", - "la", - "lv", - "ln", - "lt", - "lb", - "mk", - "mg", - "ms", - "ml", - "mt", - "mi", - "mr", - "mn", - "my", - "ne", - "no", - "nn", - "oc", - "ps", - "fa", - "pl", - "pt", - "pa", - "ro", - "ru", - "sa", - "sr", - "sn", - "sd", - "si", - "sk", - "sl", - "so", - "es", - "su", - "sw", - "sv", - "tl", - "tg", - "ta", - "tt", - "te", - "th", - "bo", - "tr", - "tk", - "uk", - "ur", - "uz", - "vi", - "cy", - "yi", - "yo" - ] - }, - "languages": { - "type": "string", - "description": "Defines the languages to use for the transcription. Required when languageBehaviour is 'manual'.", - "enum": [ - "af", - "sq", - "am", - "ar", - "hy", - "as", - "az", - "ba", - "eu", - "be", - "bn", - "bs", - "br", - "bg", - "ca", - "zh", - "hr", - "cs", - "da", - "nl", - "en", - "et", - "fo", - "fi", - "fr", - "gl", - "ka", - "de", - "el", - "gu", - "ht", - "ha", - "haw", - "he", - "hi", - "hu", - "is", - "id", - "it", - "ja", - "jv", - "kn", - "kk", - "km", - "ko", - "lo", - "la", - "lv", - "ln", - "lt", - "lb", - "mk", - "mg", - "ms", - "ml", - "mt", - "mi", - "mr", - "mn", - "my", - "ne", - "no", - "nn", - "oc", - "ps", - "fa", - "pl", - "pt", - "pa", - "ro", - "ru", - "sa", - "sr", - "sn", - "sd", - "si", - "sk", - "sl", - "so", - "es", - "su", - "sw", - "sv", - "tl", - "tg", - "ta", - "tt", - "te", - "th", - "bo", - "tr", - "tk", - "uk", - "ur", - "uz", - "vi", - "cy", - "yi", - "yo" - ] - }, - "transcriptionHint": { - "type": "string", - "description": "Provides a custom vocabulary to the model to improve accuracy of transcribing context specific words, technical terms, names, etc. If empty, this argument is ignored.\n⚠️ Warning ⚠️: Please be aware that the transcription_hint field has a character limit of 600. If you provide a transcription_hint longer than 600 characters, it will be automatically truncated to meet this limit.", - "maxLength": 600, - "example": "custom vocabulary" - }, - "prosody": { - "type": "boolean", - "description": "If prosody is true, you will get a transcription that can contain prosodies i.e. (laugh) (giggles) (malefic laugh) (toss) (music)… Default value is false.", - "example": false - }, - "audioEnhancer": { - "type": "boolean", - "description": "If true, audio will be pre-processed to improve accuracy but latency will increase. Default value is false.", - "example": false - }, - "confidenceThreshold": { - "type": "number", - "description": "Transcripts below this confidence threshold will be discarded.\n\n@default 0.4", - "minimum": 0, - "maximum": 1, - "example": 0.4 - }, - "endpointing": { - "type": "number", - "minimum": 0.01, - "maximum": 10, - "example": 0.05, - "description": "Endpointing time in seconds - time to wait before considering speech ended" - }, - "speechThreshold": { - "type": "number", - "minimum": 0, - "maximum": 1, - "example": 0.6, - "description": "Speech threshold - sensitivity configuration for speech detection (0.0 to 1.0)" - }, - "customVocabularyEnabled": { - "type": "boolean", - "example": false, - "description": "Enable custom vocabulary for improved accuracy" - }, - "customVocabularyConfig": { - "description": "Custom vocabulary configuration", - "allOf": [ - { - "$ref": "#/components/schemas/GladiaCustomVocabularyConfigDTO" + } + } + }, + "tags": [ + "Eval" + ], + "security": [ + { + "bearer": [] + } + ] + } + }, + "/eval/run/{id}": { + "delete": { + "operationId": "EvalController_removeRun", + "summary": "Delete Eval Run", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "description": "The unique identifier for the resource.", + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalRun" + } } - ] + } } }, - "required": [ - "provider" + "tags": [ + "Eval" + ], + "security": [ + { + "bearer": [] + } ] }, - "FallbackSpeechmaticsTranscriber": { - "type": "object", - "properties": { - "provider": { - "type": "string", - "description": "This is the transcription provider that will be used.", - "enum": [ - "speechmatics" - ] - }, - "model": { - "type": "string", - "description": "This is the model that will be used for the transcription.", - "enum": [ - "default" - ] + "get": { + "operationId": "EvalController_getRun", + "summary": "Get Eval Run", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "description": "The unique identifier for the resource.", + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalRun" + } + } + } + } + }, + "tags": [ + "Eval" + ], + "security": [ + { + "bearer": [] + } + ] + } + }, + "/eval/run": { + "post": { + "operationId": "EvalController_run", + "summary": "Create Eval Run", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateEvalRunDTO" + } + } + } + }, + "responses": { + "200": { + "description": "" }, - "language": { - "type": "string", - "enum": [ - "auto", - "ar", - "ba", - "eu", - "be", - "bn", - "bg", - "yue", - "ca", - "hr", - "cs", - "da", - "nl", - "en", - "eo", - "et", - "fi", - "fr", - "gl", - "de", - "el", - "he", - "hi", - "hu", - "id", - "ia", - "ga", - "it", - "ja", - "ko", - "lv", - "lt", - "ms", - "mt", - "cmn", - "mr", - "mn", - "no", - "fa", - "pl", - "pt", - "ro", - "ru", - "sk", - "sl", - "es", - "sw", - "sv", - "ta", - "th", - "tr", - "uk", - "ur", - "ug", - "vi", - "cy" - ] + "201": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object" + } + } + } } }, - "required": [ - "provider" + "tags": [ + "Eval" + ], + "security": [ + { + "bearer": [] + } ] }, - "FallbackTalkscriberTranscriber": { - "type": "object", - "properties": { - "provider": { - "type": "string", - "description": "This is the transcription provider that will be used.", - "enum": [ - "talkscriber" - ] + "get": { + "operationId": "EvalController_getRunsPaginated", + "summary": "List Eval Runs", + "parameters": [ + { + "name": "id", + "required": false, + "in": "query", + "schema": { + "type": "string" + } }, - "model": { - "type": "string", - "description": "This is the model that will be used for the transcription.", - "enum": [ - "whisper" - ] + { + "name": "page", + "required": false, + "in": "query", + "description": "This is the page number to return. Defaults to 1.", + "schema": { + "minimum": 1, + "type": "number" + } }, - "language": { - "type": "string", - "description": "This is the language that will be set for the transcription. The list of languages Whisper supports can be found here: https://github.com/openai/whisper/blob/main/whisper/tokenizer.py", - "enum": [ - "en", - "zh", - "de", - "es", - "ru", - "ko", - "fr", - "ja", - "pt", - "tr", - "pl", - "ca", - "nl", - "ar", - "sv", - "it", - "id", - "hi", - "fi", - "vi", - "he", - "uk", - "el", - "ms", - "cs", - "ro", - "da", - "hu", - "ta", - "no", - "th", - "ur", - "hr", - "bg", - "lt", - "la", - "mi", - "ml", - "cy", - "sk", - "te", - "fa", - "lv", - "bn", - "sr", - "az", - "sl", - "kn", - "et", - "mk", - "br", - "eu", - "is", - "hy", - "ne", - "mn", - "bs", - "kk", - "sq", - "sw", - "gl", - "mr", - "pa", - "si", - "km", - "sn", - "yo", - "so", - "af", - "oc", - "ka", - "be", - "tg", - "sd", - "gu", - "am", - "yi", - "lo", - "uz", - "fo", - "ht", - "ps", - "tk", - "nn", - "mt", - "sa", - "lb", - "my", - "bo", - "tl", - "mg", - "as", - "tt", - "haw", - "ln", - "ha", - "ba", - "jw", - "su", - "yue" - ] + { + "name": "sortOrder", + "required": false, + "in": "query", + "description": "This is the sort order for pagination. Defaults to 'DESC'.", + "schema": { + "enum": [ + "ASC", + "DESC" + ], + "type": "string" + } + }, + { + "name": "sortBy", + "required": false, + "in": "query", + "description": "This is the column to sort by. Defaults to 'createdAt'.", + "schema": { + "enum": [ + "createdAt", + "duration", + "cost" + ], + "type": "string" + } + }, + { + "name": "limit", + "required": false, + "in": "query", + "description": "This is the maximum number of items to return. Defaults to 100.", + "schema": { + "minimum": 0, + "maximum": 1000, + "type": "number" + } + }, + { + "name": "createdAtGt", + "required": false, + "in": "query", + "description": "This will return items where the createdAt is greater than the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } + }, + { + "name": "createdAtLt", + "required": false, + "in": "query", + "description": "This will return items where the createdAt is less than the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } + }, + { + "name": "createdAtGe", + "required": false, + "in": "query", + "description": "This will return items where the createdAt is greater than or equal to the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } + }, + { + "name": "createdAtLe", + "required": false, + "in": "query", + "description": "This will return items where the createdAt is less than or equal to the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } + }, + { + "name": "updatedAtGt", + "required": false, + "in": "query", + "description": "This will return items where the updatedAt is greater than the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } + }, + { + "name": "updatedAtLt", + "required": false, + "in": "query", + "description": "This will return items where the updatedAt is less than the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } + }, + { + "name": "updatedAtGe", + "required": false, + "in": "query", + "description": "This will return items where the updatedAt is greater than or equal to the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } + }, + { + "name": "updatedAtLe", + "required": false, + "in": "query", + "description": "This will return items where the updatedAt is less than or equal to the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EvalRunPaginatedResponse" + } + } + } } }, - "required": [ - "provider" + "tags": [ + "Eval" + ], + "security": [ + { + "bearer": [] + } ] - }, - "FallbackGoogleTranscriber": { - "type": "object", - "properties": { - "provider": { - "type": "string", - "description": "This is the transcription provider that will be used.", - "enum": [ - "google" - ] - }, - "model": { - "type": "string", - "description": "This is the model that will be used for the transcription.", - "enum": [ - "gemini-2.5-pro", - "gemini-2.5-flash", - "gemini-2.5-flash-lite", - "gemini-2.0-flash-thinking-exp", - "gemini-2.0-pro-exp-02-05", - "gemini-2.0-flash", - "gemini-2.0-flash-lite", - "gemini-2.0-flash-exp", - "gemini-2.0-flash-realtime-exp", - "gemini-1.5-flash", - "gemini-1.5-flash-002", - "gemini-1.5-pro", - "gemini-1.5-pro-002", - "gemini-1.0-pro" - ] - }, - "language": { - "type": "string", - "description": "This is the language that will be set for the transcription.", - "enum": [ - "Multilingual", - "Arabic", - "Bengali", - "Bulgarian", - "Chinese", - "Croatian", - "Czech", - "Danish", - "Dutch", - "English", - "Estonian", - "Finnish", - "French", - "German", - "Greek", - "Hebrew", - "Hindi", - "Hungarian", - "Indonesian", - "Italian", - "Japanese", - "Korean", - "Latvian", - "Lithuanian", - "Norwegian", - "Polish", - "Portuguese", - "Romanian", - "Russian", - "Serbian", - "Slovak", - "Slovenian", - "Spanish", - "Swahili", - "Swedish", - "Thai", - "Turkish", - "Ukrainian", - "Vietnamese" - ] + } + }, + "/observability/scorecard/{id}": { + "get": { + "operationId": "ScorecardController_get", + "summary": "Get Scorecard", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Scorecard" + } + } + } } }, - "required": [ - "provider" + "tags": [ + "Observability/Scorecard" + ], + "security": [ + { + "bearer": [] + } ] }, - "FallbackOpenAITranscriber": { - "type": "object", - "properties": { - "provider": { - "type": "string", - "description": "This is the transcription provider that will be used.", - "enum": [ - "openai" - ] - }, - "model": { - "type": "string", - "description": "This is the model that will be used for the transcription.", - "enum": [ - "gpt-4o-transcribe", - "gpt-4o-mini-transcribe" - ] - }, - "language": { - "type": "string", - "description": "This is the language that will be set for the transcription.", - "enum": [ - "af", - "ar", - "hy", - "az", - "be", - "bs", - "bg", - "ca", - "zh", - "hr", - "cs", - "da", - "nl", - "en", - "et", - "fi", - "fr", - "gl", - "de", - "el", - "he", - "hi", - "hu", - "is", - "id", - "it", - "ja", - "kn", - "kk", - "ko", - "lv", - "lt", - "mk", - "ms", - "mr", - "mi", - "ne", - "no", - "fa", - "pl", - "pt", - "ro", - "ru", - "sr", - "sk", - "sl", - "es", - "sw", - "sv", - "tl", - "ta", - "th", - "tr", - "uk", - "ur", - "vi", - "cy" - ] + "patch": { + "operationId": "ScorecardController_update", + "summary": "Update Scorecard", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateScorecardDTO" + } + } } }, - "required": [ - "provider", - "model" + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Scorecard" + } + } + } + } + }, + "tags": [ + "Observability/Scorecard" + ], + "security": [ + { + "bearer": [] + } ] }, - "LangfuseObservabilityPlan": { - "type": "object", - "properties": { - "provider": { - "type": "string", - "enum": [ - "langfuse" - ] - }, - "tags": { - "description": "This is an array of tags to be added to the Langfuse trace. Tags allow you to categorize and filter traces. https://langfuse.com/docs/tracing-features/tags", - "type": "array", - "items": { + "delete": { + "operationId": "ScorecardController_remove", + "summary": "Delete Scorecard", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { "type": "string" } - }, - "metadata": { - "type": "object", - "description": "This is a JSON object that will be added to the Langfuse trace. Traces can be enriched with metadata to better understand your users, application, and experiments. https://langfuse.com/docs/tracing-features/metadata\nBy default it includes the call metadata, assistant metadata, and assistant overrides." + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Scorecard" + } + } + } } }, - "required": [ - "provider", - "tags" + "tags": [ + "Observability/Scorecard" + ], + "security": [ + { + "bearer": [] + } ] - }, - "TextContent": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "text" - ] - }, - "text": { - "type": "string" - }, - "language": { - "type": "string", - "enum": [ - "aa", - "ab", - "ae", - "af", - "ak", - "am", - "an", - "ar", - "as", - "av", - "ay", - "az", - "ba", - "be", - "bg", - "bh", - "bi", - "bm", - "bn", - "bo", - "br", - "bs", - "ca", - "ce", - "ch", - "co", - "cr", - "cs", - "cu", - "cv", - "cy", - "da", - "de", - "dv", - "dz", - "ee", - "el", - "en", - "eo", - "es", - "et", - "eu", - "fa", - "ff", - "fi", - "fj", - "fo", - "fr", - "fy", - "ga", - "gd", - "gl", - "gn", - "gu", - "gv", - "ha", - "he", - "hi", - "ho", - "hr", - "ht", - "hu", - "hy", - "hz", - "ia", - "id", - "ie", - "ig", - "ii", - "ik", - "io", - "is", - "it", - "iu", - "ja", - "jv", - "ka", - "kg", - "ki", - "kj", - "kk", - "kl", - "km", - "kn", - "ko", - "kr", - "ks", - "ku", - "kv", - "kw", - "ky", - "la", - "lb", - "lg", - "li", - "ln", - "lo", - "lt", - "lu", - "lv", - "mg", - "mh", - "mi", - "mk", - "ml", - "mn", - "mr", - "ms", - "mt", - "my", - "na", - "nb", - "nd", - "ne", - "ng", - "nl", - "nn", - "no", - "nr", - "nv", - "ny", - "oc", - "oj", - "om", - "or", - "os", - "pa", - "pi", - "pl", - "ps", - "pt", - "qu", - "rm", - "rn", - "ro", - "ru", - "rw", - "sa", - "sc", - "sd", - "se", - "sg", - "si", - "sk", - "sl", - "sm", - "sn", - "so", - "sq", - "sr", - "ss", - "st", - "su", - "sv", - "sw", - "ta", - "te", - "tg", - "th", - "ti", - "tk", - "tl", - "tn", - "to", - "tr", - "ts", - "tt", - "tw", - "ty", - "ug", - "uk", - "ur", - "uz", - "ve", - "vi", - "vo", - "wa", - "wo", - "xh", - "yi", - "yue", - "yo", - "za", - "zh", - "zu" - ] - } - }, - "required": [ - "type", - "text", - "language" - ] - }, - "Condition": { - "type": "object", - "properties": { - "operator": { - "type": "string", - "description": "This is the operator you want to use to compare the parameter and value.", - "enum": [ - "eq", - "neq", - "gt", - "gte", - "lt", - "lte" - ] + } + }, + "/observability/scorecard": { + "get": { + "operationId": "ScorecardController_getPaginated", + "summary": "List Scorecards", + "parameters": [ + { + "name": "id", + "required": false, + "in": "query", + "schema": { + "type": "string" + } }, - "param": { - "type": "string", - "description": "This is the name of the parameter that you want to check.", - "maxLength": 1000 + { + "name": "page", + "required": false, + "in": "query", + "description": "This is the page number to return. Defaults to 1.", + "schema": { + "minimum": 1, + "type": "number" + } }, - "value": { - "type": "string", - "description": "This is the value you want to compare against the parameter.", - "maxLength": 1000 - } - }, - "required": [ - "operator", - "param", - "value" - ] - }, - "ToolMessageStart": { - "type": "object", - "properties": { - "contents": { - "type": "array", - "description": "This is an alternative to the `content` property. It allows to specify variants of the same content, one per language.\n\nUsage:\n- If your assistants are multilingual, you can provide content for each language.\n- If you don't provide content for a language, the first item in the array will be automatically translated to the active language at that moment.\n\nThis will override the `content` property.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/TextContent", - "title": "Text" - } - ] + { + "name": "sortOrder", + "required": false, + "in": "query", + "description": "This is the sort order for pagination. Defaults to 'DESC'.", + "schema": { + "enum": [ + "ASC", + "DESC" + ], + "type": "string" } }, - "type": { - "type": "string", - "enum": [ - "request-start" - ], - "description": "This message is triggered when the tool call starts.\n\nThis message is never triggered for async tools.\n\nIf this message is not provided, one of the default filler messages \"Hold on a sec\", \"One moment\", \"Just a sec\", \"Give me a moment\" or \"This'll just take a sec\" will be used." + { + "name": "sortBy", + "required": false, + "in": "query", + "description": "This is the column to sort by. Defaults to 'createdAt'.", + "schema": { + "enum": [ + "createdAt", + "duration", + "cost" + ], + "type": "string" + } }, - "blocking": { - "type": "boolean", - "description": "This is an optional boolean that if true, the tool call will only trigger after the message is spoken. Default is false.\n\n@default false", - "example": false, - "default": false + { + "name": "limit", + "required": false, + "in": "query", + "description": "This is the maximum number of items to return. Defaults to 100.", + "schema": { + "minimum": 0, + "maximum": 1000, + "type": "number" + } }, - "content": { - "type": "string", - "description": "This is the content that the assistant says when this message is triggered.", - "maxLength": 1000 + { + "name": "createdAtGt", + "required": false, + "in": "query", + "description": "This will return items where the createdAt is greater than the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } }, - "conditions": { - "description": "This is an optional array of conditions that the tool call arguments must meet in order for this message to be triggered.", - "type": "array", - "items": { - "$ref": "#/components/schemas/Condition" + { + "name": "createdAtLt", + "required": false, + "in": "query", + "description": "This will return items where the createdAt is less than the specified value.", + "schema": { + "format": "date-time", + "type": "string" } - } - }, - "required": [ - "type" - ] - }, - "ToolMessageComplete": { - "type": "object", - "properties": { - "contents": { - "type": "array", - "description": "This is an alternative to the `content` property. It allows to specify variants of the same content, one per language.\n\nUsage:\n- If your assistants are multilingual, you can provide content for each language.\n- If you don't provide content for a language, the first item in the array will be automatically translated to the active language at that moment.\n\nThis will override the `content` property.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/TextContent", - "title": "Text" - } - ] + }, + { + "name": "createdAtGe", + "required": false, + "in": "query", + "description": "This will return items where the createdAt is greater than or equal to the specified value.", + "schema": { + "format": "date-time", + "type": "string" } }, - "type": { - "type": "string", - "description": "This message is triggered when the tool call is complete.\n\nThis message is triggered immediately without waiting for your server to respond for async tool calls.\n\nIf this message is not provided, the model will be requested to respond.\n\nIf this message is provided, only this message will be spoken and the model will not be requested to come up with a response. It's an exclusive OR.", - "enum": [ - "request-complete" - ] + { + "name": "createdAtLe", + "required": false, + "in": "query", + "description": "This will return items where the createdAt is less than or equal to the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } }, - "role": { - "type": "string", - "description": "This is optional and defaults to \"assistant\".\n\nWhen role=assistant, `content` is said out loud.\n\nWhen role=system, `content` is passed to the model in a system message. Example:\n system: default one\n assistant:\n user:\n assistant:\n user:\n assistant:\n user:\n assistant: tool called\n tool: your server response\n <--- system prompt as hint\n ---> model generates response which is spoken\nThis is useful when you want to provide a hint to the model about what to say next.", - "enum": [ - "assistant", - "system" - ] + { + "name": "updatedAtGt", + "required": false, + "in": "query", + "description": "This will return items where the updatedAt is greater than the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } }, - "endCallAfterSpokenEnabled": { - "type": "boolean", - "description": "This is an optional boolean that if true, the call will end after the message is spoken. Default is false.\n\nThis is ignored if `role` is set to `system`.\n\n@default false", - "example": false + { + "name": "updatedAtLt", + "required": false, + "in": "query", + "description": "This will return items where the updatedAt is less than the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } }, - "content": { - "type": "string", - "description": "This is the content that the assistant says when this message is triggered.", - "maxLength": 1000 + { + "name": "updatedAtGe", + "required": false, + "in": "query", + "description": "This will return items where the updatedAt is greater than or equal to the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } }, - "conditions": { - "description": "This is an optional array of conditions that the tool call arguments must meet in order for this message to be triggered.", - "type": "array", - "items": { - "$ref": "#/components/schemas/Condition" + { + "name": "updatedAtLe", + "required": false, + "in": "query", + "description": "This will return items where the updatedAt is less than or equal to the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ScorecardPaginatedResponse" + } + } } } }, - "required": [ - "type" + "tags": [ + "Observability/Scorecard" + ], + "security": [ + { + "bearer": [] + } ] }, - "ToolMessageFailed": { - "type": "object", - "properties": { - "contents": { - "type": "array", - "description": "This is an alternative to the `content` property. It allows to specify variants of the same content, one per language.\n\nUsage:\n- If your assistants are multilingual, you can provide content for each language.\n- If you don't provide content for a language, the first item in the array will be automatically translated to the active language at that moment.\n\nThis will override the `content` property.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/TextContent", - "title": "Text" - } - ] - } - }, - "type": { - "type": "string", - "description": "This message is triggered when the tool call fails.\n\nThis message is never triggered for async tool calls.\n\nIf this message is not provided, the model will be requested to respond.\n\nIf this message is provided, only this message will be spoken and the model will not be requested to come up with a response. It's an exclusive OR.", - "enum": [ - "request-failed" - ] - }, - "endCallAfterSpokenEnabled": { - "type": "boolean", - "description": "This is an optional boolean that if true, the call will end after the message is spoken. Default is false.\n\n@default false", - "example": false - }, + "post": { + "operationId": "ScorecardController_create", + "summary": "Create Scorecard", + "parameters": [], + "requestBody": { + "required": true, "content": { - "type": "string", - "description": "This is the content that the assistant says when this message is triggered.", - "maxLength": 1000 - }, - "conditions": { - "description": "This is an optional array of conditions that the tool call arguments must meet in order for this message to be triggered.", - "type": "array", - "items": { - "$ref": "#/components/schemas/Condition" + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateScorecardDTO" + } } } }, - "required": [ - "type" - ] - }, - "ToolMessageDelayed": { - "type": "object", - "properties": { - "contents": { - "type": "array", - "description": "This is an alternative to the `content` property. It allows to specify variants of the same content, one per language.\n\nUsage:\n- If your assistants are multilingual, you can provide content for each language.\n- If you don't provide content for a language, the first item in the array will be automatically translated to the active language at that moment.\n\nThis will override the `content` property.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/TextContent", - "title": "Text" + "responses": { + "201": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Scorecard" } - ] + } } - }, - "type": { - "type": "string", - "description": "This message is triggered when the tool call is delayed.\n\nThere are the two things that can trigger this message:\n1. The user talks with the assistant while your server is processing the request. Default is \"Sorry, a few more seconds.\"\n2. The server doesn't respond within `timingMilliseconds`.\n\nThis message is never triggered for async tool calls.", - "enum": [ - "request-response-delayed" - ] - }, - "timingMilliseconds": { - "type": "number", - "minimum": 100, - "maximum": 120000, - "example": 1000, - "description": "The number of milliseconds to wait for the server response before saying this message." - }, - "content": { - "type": "string", - "description": "This is the content that the assistant says when this message is triggered.", - "maxLength": 1000 - }, - "conditions": { - "description": "This is an optional array of conditions that the tool call arguments must meet in order for this message to be triggered.", - "type": "array", - "items": { - "$ref": "#/components/schemas/Condition" - } - } - }, - "required": [ - "type" - ] - }, - "MessageTarget": { - "type": "object", - "properties": { - "role": { - "type": "string", - "description": "This is the role of the message to target.\n\nIf not specified, will find the position in the message history ignoring role (effectively `any`).", - "example": "user", - "enum": [ - "user", - "assistant" - ] - }, - "position": { - "type": "number", - "description": "This is the position of the message to target.\n- Negative numbers: Count from end (-1 = most recent, -2 = second most recent)\n- 0: First/oldest message in history\n- Positive numbers: Specific position (0-indexed from start)\n\n@default -1 (most recent message)", - "example": -1 - } - } - }, - "RegexCondition": { - "type": "object", - "properties": { - "type": { - "type": "string", - "description": "This is the type discriminator for regex condition", - "example": "regex", - "enum": [ - "regex" - ] - }, - "regex": { - "type": "string", - "description": "This is the regular expression pattern to match against message content.\n\nNote:\n- This works by using the RegExp.test method in Node.JS. Eg. /hello/.test(\"hello there\") will return true.\n\nHot tips:\n- In JavaScript, escape \\ when sending the regex pattern. Eg. \"hello\\sthere\" will be sent over the wire as \"hellosthere\". Send \"hello\\\\sthere\" instead.\n- RegExp.test does substring matching, so /cat/.test(\"I love cats\") will return true. To do full string matching, use anchors: /^cat$/ will only match exactly \"cat\".\n- Word boundaries \\b are useful for matching whole words: /\\bcat\\b/ matches \"cat\" but not \"cats\" or \"category\".\n- Use inline flags for portability: (?i) for case insensitive, (?m) for multiline", - "examples": [ - "\\\\b(cancel|stop|wait)\\\\b - Matches whole words", - "^yes$ - Matches exactly yes (full string match)", - "(?i)hello - Case insensitive match" - ] - }, - "target": { - "description": "This is the target for messages to check against.\nIf not specified, the condition will run on the last message (position: -1).\nIf role is not specified, it will look at the last message regardless of role.\n@default { position: -1 }", - "allOf": [ - { - "$ref": "#/components/schemas/MessageTarget" - } - ] - }, - "negate": { - "type": "boolean", - "description": "This is the flag that when true, the condition matches if the pattern does NOT match.\nUseful for ensuring certain words/phrases are absent.\n\n@default false", - "example": "true - Reject if user hasn\"t said goodbye: { regex: \"\\\\b(bye|goodbye)\\\\b\", negate: true }" } }, - "required": [ - "type", - "regex" - ] - }, - "LiquidCondition": { - "type": "object", - "properties": { - "type": { - "type": "string", - "description": "This is the type discriminator for liquid condition", - "example": "liquid", - "enum": [ - "liquid" - ] - }, - "liquid": { - "type": "string", - "description": "This is the Liquid template that must return exactly \"true\" or \"false\" as a string.\nThe template is evaluated and the entire output must be either \"true\" or \"false\" - nothing else.\n\nAvailable variables:\n- `messages`: Array of recent messages in OpenAI chat completions format (ChatCompletionMessageParam[])\n Each message has properties like: role ('user', 'assistant', 'system'), content (string), etc.\n- `now`: Current timestamp in milliseconds (built-in Liquid variable)\n- Any assistant variable values (e.g., `userName`, `accountStatus`)\n\nUseful Liquid filters for messages:\n- `messages | last: 5` - Get the 5 most recent messages\n- `messages | where: 'role', 'user'` - Filter to only user messages\n- `messages | reverse` - Reverse the order of messages", - "examples": [ - "{% if messages.last.content contains goodbye %}true{% else %}false{% endif %}", - "{% assign userMessages = messages | where: role, user %}{% if userMessages.size > 3 %}true{% else %}false{% endif %}" - ] + "tags": [ + "Observability/Scorecard" + ], + "security": [ + { + "bearer": [] } - }, - "required": [ - "type", - "liquid" ] - }, - "GroupCondition": { - "type": "object", - "properties": { - "type": { - "type": "string", - "description": "This is the type discriminator for group condition", - "example": "group", - "enum": [ - "group" - ] - }, - "operator": { - "type": "string", - "description": "This is the logical operator for combining conditions in this group", - "examples": [ - "AND", - "OR" - ], - "enum": [ - "AND", - "OR" - ] + } + }, + "/provider/{provider}/{resourceName}": { + "post": { + "operationId": "ProviderResourceController_createProviderResource", + "summary": "Create Provider Resource", + "parameters": [ + { + "name": "content-type", + "required": true, + "in": "header", + "schema": { + "type": "string" + } }, - "conditions": { - "type": "array", - "description": "This is the list of nested conditions to evaluate.\nSupports recursive nesting of groups for complex logic.", - "examples": [ - "[{ type: \"regex\", regex: \"(?i)stop\", target: { role: \"user\" } }]", - "[{ type: \"group\", operator: \"AND\", conditions: [...] }]" - ], - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/RegexCondition", - "title": "RegexCondition" - }, - { - "$ref": "#/components/schemas/LiquidCondition", - "title": "LiquidCondition" - }, - { - "$ref": "#/components/schemas/GroupCondition", - "title": "GroupCondition", - "description": "This is the GroupCondition object but Swagger does not display nested schemas correctly." - } - ] + { + "name": "provider", + "required": true, + "in": "path", + "description": "The provider (e.g., 11labs)", + "schema": { + "enum": [ + "cartesia", + "11labs" + ], + "type": "string" } - } - }, - "required": [ - "type", - "operator", - "conditions" - ] - }, - "ToolRejectionPlan": { - "type": "object", - "properties": { - "conditions": { - "type": "array", - "description": "This is the list of conditions that must be evaluated.\n\nUsage:\n- If all conditions match (AND logic), the tool call is rejected.\n- For OR logic at the top level, use a single 'group' condition with operator: 'OR'.\n\n@default [] - Empty array means tool always executes", - "examples": [ - "[{ type: \"regex\", regex: \"(?i)\\\\b(cancel|stop)\\\\b\", target: { role: \"user\" } }]", - "[{ type: \"group\", operator: \"OR\", conditions: [...] }]" - ], - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/RegexCondition", - "title": "RegexCondition" - }, - { - "$ref": "#/components/schemas/LiquidCondition", - "title": "LiquidCondition" - }, - { - "$ref": "#/components/schemas/GroupCondition", - "title": "GroupCondition", - "description": "This is the GroupCondition object but Swagger does not display nested schemas correctly." - } - ] + }, + { + "name": "resourceName", + "required": true, + "in": "path", + "description": "The resource name (e.g., pronunciation-dictionary)", + "schema": { + "enum": [ + "pronunciation-dictionary" + ], + "type": "string" } } - } - }, - "CreateDtmfToolDTO": { - "type": "object", - "properties": { - "messages": { - "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" + ], + "responses": { + "201": { + "description": "Successfully created provider resource", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProviderResource" } - ] - } - }, - "type": { - "type": "string", - "enum": [ - "dtmf" - ], - "description": "The type of tool. \"dtmf\" for DTMF tool." - }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", - "allOf": [ - { - "$ref": "#/components/schemas/ToolRejectionPlan" } - ] + } } }, - "required": [ - "type" + "tags": [ + "Provider Resources" + ], + "security": [ + { + "bearer": [] + } ] }, - "CreateEndCallToolDTO": { - "type": "object", - "properties": { - "messages": { - "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" - } - ] + "get": { + "operationId": "ProviderResourceController_getProviderResourcesPaginated", + "summary": "List Provider Resources", + "parameters": [ + { + "name": "provider", + "required": true, + "in": "path", + "description": "The provider (e.g., 11labs)", + "schema": { + "enum": [ + "cartesia", + "11labs" + ], + "type": "string" } }, - "type": { - "type": "string", - "enum": [ - "endCall" - ], - "description": "The type of tool. \"endCall\" for End Call tool." - }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", - "allOf": [ - { - "$ref": "#/components/schemas/ToolRejectionPlan" - } - ] - } - }, - "required": [ - "type" - ] - }, - "CreateVoicemailToolDTO": { - "type": "object", - "properties": { - "messages": { - "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" - } - ] + { + "name": "resourceName", + "required": true, + "in": "path", + "description": "The resource name (e.g., pronunciation-dictionary)", + "schema": { + "enum": [ + "pronunciation-dictionary" + ], + "type": "string" } }, - "type": { - "type": "string", - "description": "The type of tool. \"voicemail\" for Voicemail tool.", - "enum": [ - "voicemail" - ] + { + "name": "id", + "required": false, + "in": "query", + "schema": { + "type": "string" + } }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", - "allOf": [ - { - "$ref": "#/components/schemas/ToolRejectionPlan" - } - ] - } - }, - "required": [ - "type" - ] - }, - "JsonSchema": { - "type": "object", - "properties": { - "type": { - "type": "string", - "description": "This is the type of output you'd like.\n\n`string`, `number`, `integer`, `boolean` are the primitive types and should be obvious.\n\n`array` and `object` are more interesting and quite powerful. They allow you to define nested structures.\n\nFor `array`, you can define the schema of the items in the array using the `items` property.\n\nFor `object`, you can define the properties of the object using the `properties` property.", - "enum": [ - "string", - "number", - "integer", - "boolean", - "array", - "object" - ] + { + "name": "resourceId", + "required": false, + "in": "query", + "schema": { + "type": "string" + } }, - "items": { - "type": "object", - "description": "This is required if the type is \"array\". This is the schema of the items in the array.\n\nThis is of type JsonSchema. However, Swagger doesn't support circular references." + { + "name": "page", + "required": false, + "in": "query", + "description": "This is the page number to return. Defaults to 1.", + "schema": { + "minimum": 1, + "type": "number" + } }, - "properties": { - "type": "object", - "description": "This is required if the type is \"object\". This specifies the properties of the object.\n\nThis is a map of string to JsonSchema. However, Swagger doesn't support circular references." + { + "name": "sortOrder", + "required": false, + "in": "query", + "description": "This is the sort order for pagination. Defaults to 'DESC'.", + "schema": { + "enum": [ + "ASC", + "DESC" + ], + "type": "string" + } }, - "description": { - "type": "string", - "description": "This is the description to help the model understand what it needs to output." + { + "name": "sortBy", + "required": false, + "in": "query", + "description": "This is the column to sort by. Defaults to 'createdAt'.", + "schema": { + "enum": [ + "createdAt", + "duration", + "cost" + ], + "type": "string" + } }, - "pattern": { - "type": "string", - "description": "This is the pattern of the string. This is a regex that will be used to validate the data in question. To use a common format, use the `format` property instead.\n\nOpenAI documentation: https://platform.openai.com/docs/guides/structured-outputs#supported-properties" + { + "name": "limit", + "required": false, + "in": "query", + "description": "This is the maximum number of items to return. Defaults to 100.", + "schema": { + "minimum": 0, + "maximum": 1000, + "type": "number" + } }, - "format": { - "type": "string", - "description": "This is the format of the string. To pass a regex, use the `pattern` property instead.\n\nOpenAI documentation: https://platform.openai.com/docs/guides/structured-outputs?api-mode=chat&type-restrictions=string-restrictions", - "enum": [ - "date-time", - "time", - "date", - "duration", - "email", - "hostname", - "ipv4", - "ipv6", - "uuid" - ] + { + "name": "createdAtGt", + "required": false, + "in": "query", + "description": "This will return items where the createdAt is greater than the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } }, - "required": { - "description": "This is a list of properties that are required.\n\nThis only makes sense if the type is \"object\".", - "type": "array", - "items": { + { + "name": "createdAtLt", + "required": false, + "in": "query", + "description": "This will return items where the createdAt is less than the specified value.", + "schema": { + "format": "date-time", "type": "string" } }, - "enum": { - "description": "This array specifies the allowed values that can be used to restrict the output of the model.", - "type": "array", - "items": { + { + "name": "createdAtGe", + "required": false, + "in": "query", + "description": "This will return items where the createdAt is greater than or equal to the specified value.", + "schema": { + "format": "date-time", "type": "string" } }, - "title": { - "type": "string", - "description": "This is the title of the schema." + { + "name": "createdAtLe", + "required": false, + "in": "query", + "description": "This will return items where the createdAt is less than or equal to the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } + }, + { + "name": "updatedAtGt", + "required": false, + "in": "query", + "description": "This will return items where the updatedAt is greater than the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } + }, + { + "name": "updatedAtLt", + "required": false, + "in": "query", + "description": "This will return items where the updatedAt is less than the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } + }, + { + "name": "updatedAtGe", + "required": false, + "in": "query", + "description": "This will return items where the updatedAt is greater than or equal to the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } + }, + { + "name": "updatedAtLe", + "required": false, + "in": "query", + "description": "This will return items where the updatedAt is less than or equal to the specified value.", + "schema": { + "format": "date-time", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "List of provider resources", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProviderResourcePaginatedResponse" + } + } + } } }, - "required": [ - "type" + "tags": [ + "Provider Resources" + ], + "security": [ + { + "bearer": [] + } ] - }, - "OpenAIFunctionParameters": { - "type": "object", - "properties": { - "type": { - "type": "string", - "description": "This must be set to 'object'. It instructs the model to return a JSON object containing the function call properties.", - "enum": [ - "object" - ] + } + }, + "/provider/{provider}/{resourceName}/{id}": { + "get": { + "operationId": "ProviderResourceController_getProviderResource", + "summary": "Get Provider Resource", + "parameters": [ + { + "name": "provider", + "required": true, + "in": "path", + "description": "The provider (e.g., 11labs)", + "schema": { + "enum": [ + "cartesia", + "11labs" + ], + "type": "string" + } }, - "properties": { - "type": "object", - "description": "This provides a description of the properties required by the function.\nJSON Schema can be used to specify expectations for each property.\nRefer to [this doc](https://ajv.js.org/json-schema.html#json-data-type) for a comprehensive guide on JSON Schema.", - "additionalProperties": { - "$ref": "#/components/schemas/JsonSchema" + { + "name": "resourceName", + "required": true, + "in": "path", + "description": "The resource name (e.g., pronunciation-dictionary)", + "schema": { + "enum": [ + "pronunciation-dictionary" + ], + "type": "string" } }, - "required": { - "description": "This specifies the properties that are required by the function.", - "type": "array", - "items": { + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "format": "uuid", "type": "string" } } + ], + "responses": { + "200": { + "description": "Successfully retrieved provider resource", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProviderResource" + } + } + } + }, + "404": { + "description": "Provider resource not found" + } }, - "required": [ - "type", - "properties" + "tags": [ + "Provider Resources" + ], + "security": [ + { + "bearer": [] + } ] }, - "OpenAIFunction": { - "type": "object", - "properties": { - "strict": { - "type": "boolean", - "description": "This is a boolean that controls whether to enable strict schema adherence when generating the function call. If set to true, the model will follow the exact schema defined in the parameters field. Only a subset of JSON Schema is supported when strict is true. Learn more about Structured Outputs in the [OpenAI guide](https://openai.com/index/introducing-structured-outputs-in-the-api/).\n\n@default false", - "default": false - }, - "name": { - "type": "string", - "description": "This is the the name of the function to be called.\n\nMust be a-z, A-Z, 0-9, or contain underscores and dashes, with a maximum length of 64.", - "maxLength": 64, - "pattern": "/^[a-zA-Z0-9_-]{1,64}$/" + "delete": { + "operationId": "ProviderResourceController_deleteProviderResource", + "summary": "Delete Provider Resource", + "parameters": [ + { + "name": "provider", + "required": true, + "in": "path", + "description": "The provider (e.g., 11labs)", + "schema": { + "enum": [ + "cartesia", + "11labs" + ], + "type": "string" + } }, - "description": { - "type": "string", - "description": "This is the description of what the function does, used by the AI to choose when and how to call the function.", - "maxLength": 1000 + { + "name": "resourceName", + "required": true, + "in": "path", + "description": "The resource name (e.g., pronunciation-dictionary)", + "schema": { + "enum": [ + "pronunciation-dictionary" + ], + "type": "string" + } }, - "parameters": { - "description": "These are the parameters the functions accepts, described as a JSON Schema object.\n\nSee the [OpenAI guide](https://platform.openai.com/docs/guides/function-calling) for examples, and the [JSON Schema reference](https://json-schema.org/understanding-json-schema) for documentation about the format.\n\nOmitting parameters defines a function with an empty parameter list.", - "allOf": [ - { - "$ref": "#/components/schemas/OpenAIFunctionParameters" + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProviderResource" + } } - ] + } + }, + "404": { + "description": "Provider resource not found" } }, - "required": [ - "name" + "tags": [ + "Provider Resources" + ], + "security": [ + { + "bearer": [] + } ] }, - "CreateFunctionToolDTO": { - "type": "object", - "properties": { - "messages": { - "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" - } - ] + "patch": { + "operationId": "ProviderResourceController_updateProviderResource", + "summary": "Update Provider Resource", + "parameters": [ + { + "name": "provider", + "required": true, + "in": "path", + "description": "The provider (e.g., 11labs)", + "schema": { + "enum": [ + "cartesia", + "11labs" + ], + "type": "string" } }, - "type": { - "type": "string", - "enum": [ - "function" - ], - "description": "The type of tool. \"function\" for Function tool." - }, - "async": { - "type": "boolean", - "example": false, - "description": "This determines if the tool is async.\n\n If async, the assistant will move forward without waiting for your server to respond. This is useful if you just want to trigger something on your server.\n\n If sync, the assistant will wait for your server to respond. This is useful if want assistant to respond with the result from your server.\n\n Defaults to synchronous (`false`)." - }, - "server": { - "description": "\n This is the server where a `tool-calls` webhook will be sent.\n\n Notes:\n - Webhook is sent to this server when a tool call is made.\n - Webhook contains the call, assistant, and phone number objects.\n - Webhook contains the variables set on the assistant.\n - Webhook is sent to the first available URL in this order: {{tool.server.url}}, {{assistant.server.url}}, {{phoneNumber.server.url}}, {{org.server.url}}.\n - Webhook expects a response with tool call result.", - "allOf": [ - { - "$ref": "#/components/schemas/Server" - } - ] + { + "name": "resourceName", + "required": true, + "in": "path", + "description": "The resource name (e.g., pronunciation-dictionary)", + "schema": { + "enum": [ + "pronunciation-dictionary" + ], + "type": "string" + } }, - "function": { - "description": "This is the function definition of the tool.", - "allOf": [ - { - "$ref": "#/components/schemas/OpenAIFunction" + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "format": "uuid", + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProviderResource" + } } - ] + } }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", - "allOf": [ - { - "$ref": "#/components/schemas/ToolRejectionPlan" - } - ] + "404": { + "description": "Provider resource not found" } }, - "required": [ - "type" + "tags": [ + "Provider Resources" + ], + "security": [ + { + "bearer": [] + } ] - }, - "GhlToolMetadata": { - "type": "object", - "properties": { - "workflowId": { - "type": "string" + } + }, + "/analytics": { + "post": { + "operationId": "AnalyticsController_query", + "summary": "Create Analytics Queries", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AnalyticsQueryDTO" + } + } + } + }, + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/AnalyticsQueryResult" + } + } + } + } }, - "locationId": { - "type": "string" + "201": { + "description": "" } - } - }, - "CreateGhlToolDTO": { + }, + "tags": [ + "Analytics" + ], + "security": [ + { + "bearer": [] + } + ] + } + } + }, + "info": { + "title": "Vapi API", + "description": "Voice AI for developers.", + "version": "1.0", + "contact": {} + }, + "tags": [], + "servers": [ + { + "url": "https://api.vapi.ai" + } + ], + "components": { + "securitySchemes": { + "bearer": { + "scheme": "bearer", + "bearerFormat": "Bearer", + "type": "http", + "description": "Retrieve your API Key from [Dashboard](dashboard.vapi.ai)." + } + }, + "schemas": { + "FallbackTranscriberPlan": { "type": "object", "properties": { - "messages": { + "transcribers": { "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", "items": { "oneOf": [ { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" + "$ref": "#/components/schemas/FallbackAssemblyAITranscriber", + "title": "AssemblyAI" }, { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" + "$ref": "#/components/schemas/FallbackAzureSpeechTranscriber", + "title": "Azure" }, { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" + "$ref": "#/components/schemas/FallbackCustomTranscriber", + "title": "Custom" }, { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" + "$ref": "#/components/schemas/FallbackDeepgramTranscriber", + "title": "Deepgram" + }, + { + "$ref": "#/components/schemas/FallbackElevenLabsTranscriber", + "title": "ElevenLabs" + }, + { + "$ref": "#/components/schemas/FallbackGladiaTranscriber", + "title": "Gladia" + }, + { + "$ref": "#/components/schemas/FallbackGoogleTranscriber", + "title": "Google" + }, + { + "$ref": "#/components/schemas/FallbackTalkscriberTranscriber", + "title": "Talkscriber" + }, + { + "$ref": "#/components/schemas/FallbackSpeechmaticsTranscriber", + "title": "Speechmatics" + }, + { + "$ref": "#/components/schemas/FallbackOpenAITranscriber", + "title": "OpenAI" + }, + { + "$ref": "#/components/schemas/FallbackCartesiaTranscriber", + "title": "Cartesia" + }, + { + "$ref": "#/components/schemas/FallbackSonioxTranscriber", + "title": "Soniox" + }, + { + "$ref": "#/components/schemas/FallbackXaiTranscriber", + "title": "xAI" } ] } - }, - "type": { - "type": "string", - "enum": [ - "ghl" - ], - "description": "The type of tool. \"ghl\" for GHL tool." - }, - "metadata": { - "$ref": "#/components/schemas/GhlToolMetadata" - }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", - "allOf": [ - { - "$ref": "#/components/schemas/ToolRejectionPlan" - } - ] - } - }, - "required": [ - "type", - "metadata" - ] - }, - "MakeToolMetadata": { - "type": "object", - "properties": { - "scenarioId": { - "type": "number" - }, - "triggerHookId": { - "type": "number" } } }, - "CreateMakeToolDTO": { + "AssemblyAITranscriber": { "type": "object", "properties": { - "messages": { - "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" - } - ] - } - }, - "type": { + "provider": { "type": "string", + "description": "This is the transcription provider that will be used.", "enum": [ - "make" - ], - "description": "The type of tool. \"make\" for Make tool." - }, - "metadata": { - "$ref": "#/components/schemas/MakeToolMetadata" - }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", - "allOf": [ - { - "$ref": "#/components/schemas/ToolRejectionPlan" - } + "assembly-ai" ] - } - }, - "required": [ - "type", - "metadata" - ] - }, - "CustomMessage": { - "type": "object", - "properties": { - "contents": { - "type": "array", - "description": "This is an alternative to the `content` property. It allows to specify variants of the same content, one per language.\n\nUsage:\n- If your assistants are multilingual, you can provide content for each language.\n- If you don't provide content for a language, the first item in the array will be automatically translated to the active language at that moment.\n\nThis will override the `content` property.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/TextContent", - "title": "Text" - } - ] - } }, - "type": { + "language": { "type": "string", - "description": "This is a custom message.", + "description": "This is the language that will be set for the transcription.", "enum": [ - "custom-message" + "multi", + "en" ] }, - "content": { - "type": "string", - "description": "This is the content that the assistant will say when this message is triggered.", - "maxLength": 1000 - } - }, - "required": [ - "type" - ] - }, - "TransferDestinationAssistant": { - "type": "object", - "properties": { - "message": { - "description": "This is spoken to the customer before connecting them to the destination.\n\nUsage:\n- If this is not provided and transfer tool messages is not provided, default is \"Transferring the call now\".\n- If set to \"\", nothing is spoken. This is useful when you want to silently transfer. This is especially useful when transferring between assistants in a squad. In this scenario, you likely also want to set `assistant.firstMessageMode=assistant-speaks-first-with-model-generated-message` for the destination assistant.\n\nThis accepts a string or a ToolMessageStart class. Latter is useful if you want to specify multiple messages for different languages through the `contents` field.", - "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/components/schemas/CustomMessage" - } - ] + "confidenceThreshold": { + "type": "number", + "description": "Transcripts below this confidence threshold will be discarded.\n\n@default 0.4", + "minimum": 0, + "maximum": 1, + "example": 0.4 }, - "type": { - "type": "string", - "enum": [ - "assistant" - ] + "formatTurns": { + "type": "boolean", + "description": "This enables formatting of transcripts.\n\n@default true", + "example": true }, - "transferMode": { - "type": "string", - "description": "This is the mode to use for the transfer. Defaults to `rolling-history`.\n\n- `rolling-history`: This is the default mode. It keeps the entire conversation history and appends the new assistant's system message on transfer.\n\n Example:\n\n Pre-transfer:\n system: assistant1 system message\n assistant: assistant1 first message\n user: hey, good morning\n assistant: how can i help?\n user: i need help with my account\n assistant: (destination.message)\n\n Post-transfer:\n system: assistant1 system message\n assistant: assistant1 first message\n user: hey, good morning\n assistant: how can i help?\n user: i need help with my account\n assistant: (destination.message)\n system: assistant2 system message\n assistant: assistant2 first message (or model generated if firstMessageMode is set to `assistant-speaks-first-with-model-generated-message`)\n\n- `swap-system-message-in-history`: This replaces the original system message with the new assistant's system message on transfer.\n\n Example:\n\n Pre-transfer:\n system: assistant1 system message\n assistant: assistant1 first message\n user: hey, good morning\n assistant: how can i help?\n user: i need help with my account\n assistant: (destination.message)\n\n Post-transfer:\n system: assistant2 system message\n assistant: assistant1 first message\n user: hey, good morning\n assistant: how can i help?\n user: i need help with my account\n assistant: (destination.message)\n assistant: assistant2 first message (or model generated if firstMessageMode is set to `assistant-speaks-first-with-model-generated-message`)\n\n- `delete-history`: This deletes the entire conversation history on transfer.\n\n Example:\n\n Pre-transfer:\n system: assistant1 system message\n assistant: assistant1 first message\n user: hey, good morning\n assistant: how can i help?\n user: i need help with my account\n assistant: (destination.message)\n\n Post-transfer:\n system: assistant2 system message\n assistant: assistant2 first message\n user: Yes, please\n assistant: how can i help?\n user: i need help with my account\n\n- `swap-system-message-in-history-and-remove-transfer-tool-messages`: This replaces the original system message with the new assistant's system message on transfer and removes transfer tool messages from conversation history sent to the LLM.\n\n Example:\n\n Pre-transfer:\n system: assistant1 system message\n assistant: assistant1 first message\n user: hey, good morning\n assistant: how can i help?\n user: i need help with my account\n transfer-tool\n transfer-tool-result\n assistant: (destination.message)\n\n Post-transfer:\n system: assistant2 system message\n assistant: assistant1 first message\n user: hey, good morning\n assistant: how can i help?\n user: i need help with my account\n assistant: (destination.message)\n assistant: assistant2 first message (or model generated if firstMessageMode is set to `assistant-speaks-first-with-model-generated-message`)\n\n@default 'rolling-history'", - "enum": [ - "rolling-history", - "swap-system-message-in-history", - "swap-system-message-in-history-and-remove-transfer-tool-messages", - "delete-history" - ] + "endOfTurnConfidenceThreshold": { + "type": "number", + "description": "This is the end of turn confidence threshold. The minimum confidence that the end of turn is detected.\nNote: Only used if startSpeakingPlan.smartEndpointingPlan is not set.\n@min 0\n@max 1\n@default 0.7", + "minimum": 0, + "maximum": 1, + "example": 0.7 }, - "assistantName": { - "type": "string", - "description": "This is the assistant to transfer the call to." + "minEndOfTurnSilenceWhenConfident": { + "type": "number", + "description": "This is the minimum end of turn silence when confident in milliseconds.\nNote: Only used if startSpeakingPlan.smartEndpointingPlan is not set.\n@default 160", + "minimum": 0, + "example": 160 }, - "description": { - "type": "string", - "description": "This is the description of the destination, used by the AI to choose when and how to transfer the call." - } - }, - "required": [ - "type", - "assistantName" - ] - }, - "TransferFallbackPlan": { - "type": "object", - "properties": { - "message": { - "description": "This is the message the assistant will deliver to the customer if the transfer fails.", - "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/components/schemas/CustomMessage" - } - ] + "wordFinalizationMaxWaitTime": { + "type": "number", + "deprecated": true, + "minimum": 0, + "example": 160 }, - "endCallEnabled": { + "maxTurnSilence": { + "type": "number", + "description": "This is the maximum turn silence time in milliseconds.\nNote: Only used if startSpeakingPlan.smartEndpointingPlan is not set.\n@default 400", + "minimum": 0, + "example": 400 + }, + "vadAssistedEndpointingEnabled": { "type": "boolean", - "description": "This controls what happens after delivering the failure message to the customer.\n- true: End the call after delivering the failure message (default)\n- false: Keep the assistant on the call to continue handling the customer's request\n\n@default true", - "default": true - } - }, - "required": [ - "message" - ] - }, - "TransferAssistantModel": { - "type": "object", - "properties": { - "provider": { + "description": "Use VAD to assist with endpointing decisions from the transcriber.\nWhen enabled, transcriber endpointing will be buffered if VAD detects the user is still speaking, preventing premature turn-taking.\nWhen disabled, transcriber endpointing will be used immediately regardless of VAD state, allowing for quicker but more aggressive turn-taking.\nNote: Only used if startSpeakingPlan.smartEndpointingPlan is not set.\n\n@default true", + "example": true + }, + "mode": { "type": "string", - "description": "The model provider for the transfer assistant", + "description": "This is the transcription mode used by the `universal-3-5-pro` speech model. Only applies to the `universal-3-5-pro` speech model.\n\n@default 'balanced'", "enum": [ - "openai", - "anthropic", - "google", - "custom-llm" + "max_accuracy", + "min_latency", + "balanced" ] }, - "model": { - "type": "string", - "description": "The model name - must be compatible with the selected provider", - "example": "gpt-4o" - }, - "messages": { - "type": "array", - "description": "These are the messages used to configure the transfer assistant.\n\n@default: ```\n[\n {\n role: 'system',\n content: 'You are a transfer assistant designed to facilitate call transfers. Your core responsibility is to manage the transfer process efficiently.\\n\\n## Core Responsibility\\n- Facilitate the transfer process by using transferSuccessful or transferCancel tools appropriately\\n\\n## When to Respond\\n- Answer questions about the transfer process or provide summaries when specifically asked by the operator\\n- Respond to direct questions about the current transfer situation\\n\\n## What to Avoid\\n- Do not discuss topics unrelated to the transfer\\n- Do not engage in general conversation\\n- Keep all interactions focused on facilitating the transfer\\n\\n## Transfer Tools\\n- Use transferSuccessful when the transfer should proceed\\n- Use transferCancel when the transfer cannot be completed\\n\\nStay focused on your core responsibility of facilitating transfers.'\n }\n]```\n\n**Default Behavior:** If you don't provide any messages or don't include a system message as the first message, the default system message above will be automatically added.\n\n**Override Default:** To replace the default system message, provide your own system message as the first message in the array.\n\n**Add Context:** You can provide additional messages (user, assistant, etc.) to add context while keeping the default system message, or combine them with your custom system message." - }, - "tools": { - "type": "array", - "description": "Tools available to the transfer assistant during warm-transfer-experimental.\n\n**Default Behavior:** The transfer assistant will ALWAYS have both `transferSuccessful` and `transferCancel` tools automatically added, regardless of what you provide here.\n\n**Default Tools:**\n- `transferSuccessful`: \"Call this function to confirm the transfer is successful and connect the customer. Use this when you detect a human has answered and is ready to take the call.\"\n- `transferCancel`: \"Call this function to cancel the transfer when no human answers or transfer should not proceed. Use this when you detect voicemail, busy signal, or no answer.\"\n\n**Customization:** You can override the default tools by providing `transferSuccessful` and/or `transferCancel` tools with custom `function` or `messages` configurations.\n\n**Additional Tools:** You can also provide other tools, but the two transfer tools will always be present and available to the assistant." - } - }, - "required": [ - "provider", - "model" - ] - }, - "TransferAssistant": { - "type": "object", - "properties": { - "name": { + "prompt": { "type": "string", - "description": "Optional name for the transfer assistant", - "maxLength": 100, - "default": "transfer-assistant", - "example": "Sales Transfer Assistant" - }, - "model": { - "description": "Model configuration for the transfer assistant", - "allOf": [ - { - "$ref": "#/components/schemas/TransferAssistantModel" - } - ] + "description": "This is a prompt that provides additional context to the transcription model. Only applies to the `universal-3-5-pro` speech model.", + "maxLength": 1750 }, - "firstMessage": { + "agentContext": { "type": "string", - "description": "This is the first message that the transfer assistant will say.\nThis can also be a URL to a custom audio file.\n\nIf unspecified, assistant will wait for user to speak and use the model to respond once they speak.", - "example": "Hello! I understand you need to be transferred. Let me connect you." + "description": "This is context about the voice agent that guides the transcription model. Only applies to the `universal-3-5-pro` speech model.", + "maxLength": 1750 }, - "firstMessageMode": { - "type": "string", - "description": "This is the mode for the first message. Default is 'assistant-speaks-first'.\n\nUse:\n- 'assistant-speaks-first' to have the assistant speak first.\n- 'assistant-waits-for-user' to have the assistant wait for the user to speak first.\n- 'assistant-speaks-first-with-model-generated-message' to have the assistant speak first with a message generated by the model based on the conversation state.\n\n@default 'assistant-speaks-first'", + "languageCodes": { + "type": "array", + "description": "These are language codes used to steer automatic language detection. Only applies to the `universal-3-5-pro` speech model.", "enum": [ - "assistant-speaks-first", - "assistant-speaks-first-with-model-generated-message", - "assistant-waits-for-user" + "en", + "es", + "fr", + "de", + "it", + "pt", + "tr", + "nl", + "sv", + "no", + "da", + "fi", + "hi", + "vi", + "ar", + "he", + "ja", + "zh" ], - "example": "assistant-speaks-first" - }, - "maxDurationSeconds": { - "type": "number", - "description": "This is the maximum duration in seconds for the transfer assistant conversation.\nAfter this time, the transfer will be cancelled automatically.\n@default 120", - "minimum": 10, - "maximum": 43200, - "example": 120 - } - }, - "required": [ - "model" - ] - }, - "TransferCancelToolUserEditable": { - "type": "object", - "properties": { - "messages": { - "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" - } + "type": "string", + "enum": [ + "en", + "es", + "fr", + "de", + "it", + "pt", + "tr", + "nl", + "sv", + "no", + "da", + "fi", + "hi", + "vi", + "ar", + "he", + "ja", + "zh" ] } }, - "type": { + "speechModel": { "type": "string", + "description": "This is the speech model used for the streaming session.\nKeyterms prompting is supported on universal-streaming-english and universal-3-5-pro.\nuniversal-3-5-pro is AssemblyAI's most accurate voice-agent model.\n@default 'universal-streaming-english'", "enum": [ - "transferCancel" - ], - "description": "The type of tool. \"transferCancel\" for Transfer Cancel tool. This tool can only be used during warm-transfer-experimental by the transfer assistant to cancel an ongoing transfer and return the call back to the original assistant when the transfer cannot be completed." - }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", - "allOf": [ - { - "$ref": "#/components/schemas/ToolRejectionPlan" - } + "universal-streaming-english", + "universal-streaming-multilingual", + "universal-3-5-pro" ] - } - }, - "required": [ - "type" - ] - }, - "TransferSuccessfulToolUserEditable": { - "type": "object", - "properties": { - "messages": { - "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" - } - ] - } }, - "type": { + "realtimeUrl": { "type": "string", - "enum": [ - "transferSuccessful" - ], - "description": "The type of tool. \"transferSuccessful\" for Transfer Successful tool. This tool can only be used during warm-transfer-experimental by the transfer assistant to confirm that the transfer should proceed and finalize the handoff to the destination." + "description": "The WebSocket URL that the transcriber connects to." }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", - "allOf": [ - { - "$ref": "#/components/schemas/ToolRejectionPlan" - } - ] - } - }, - "required": [ - "type" - ] - }, - "SummaryPlan": { - "type": "object", - "properties": { - "messages": { - "description": "These are the messages used to generate the summary.\n\n@default: ```\n[\n {\n \"role\": \"system\",\n \"content\": \"You are an expert note-taker. You will be given a transcript of a call. Summarize the call in 2-3 sentences. DO NOT return anything except the summary.\"\n },\n {\n \"role\": \"user\",\n \"content\": \"Here is the transcript:\\n\\n{{transcript}}\\n\\n. Here is the ended reason of the call:\\n\\n{{endedReason}}\\n\\n\"\n }\n]```\n\nYou can customize by providing any messages you want.\n\nHere are the template variables available:\n- {{transcript}}: The transcript of the call from `call.artifact.transcript` \n- {{systemPrompt}}: The system prompt of the call from `assistant.model.messages[type=system].content` \n- {{messages}}: The messages of the call from `assistant.model.messages` \n- {{endedReason}}: The ended reason of the call from `call.endedReason`", + "wordBoost": { + "description": "Add up to 2500 characters of custom vocabulary.", "type": "array", "items": { - "type": "object" + "type": "string", + "maxLength": 2500 } }, - "enabled": { - "type": "boolean", - "description": "This determines whether a summary is generated and stored in `call.analysis.summary`. Defaults to true.\n\nUsage:\n- If you want to disable the summary, set this to false.\n\n@default true" - }, - "timeoutSeconds": { - "type": "number", - "description": "This is how long the request is tried before giving up. When request times out, `call.analysis.summary` will be empty.\n\nUsage:\n- To guarantee the summary is generated, set this value high. Note, this will delay the end of call report in cases where model is slow to respond.\n\n@default 5 seconds", - "minimum": 1, - "maximum": 60 - } - } - }, - "TransferPlan": { - "type": "object", - "properties": { - "mode": { - "type": "string", - "description": "This configures how transfer is executed and the experience of the destination party receiving the call.\n\nUsage:\n- `blind-transfer`: The assistant forwards the call to the destination without any message or summary.\n- `blind-transfer-add-summary-to-sip-header`: The assistant forwards the call to the destination and adds a SIP header X-Transfer-Summary to the call to include the summary.\n- `warm-transfer-say-message`: The assistant dials the destination, delivers the `message` to the destination party, connects the customer, and leaves the call.\n- `warm-transfer-say-summary`: The assistant dials the destination, provides a summary of the call to the destination party, connects the customer, and leaves the call.\n- `warm-transfer-wait-for-operator-to-speak-first-and-then-say-message`: The assistant dials the destination, waits for the operator to speak, delivers the `message` to the destination party, and then connects the customer.\n- `warm-transfer-wait-for-operator-to-speak-first-and-then-say-summary`: The assistant dials the destination, waits for the operator to speak, provides a summary of the call to the destination party, and then connects the customer.\n- `warm-transfer-twiml`: The assistant dials the destination, executes the twiml instructions on the destination call leg, connects the customer, and leaves the call.\n- `warm-transfer-experimental`: The assistant puts the customer on hold, dials the destination, and if the destination answers (and is human), delivers a message or summary before connecting the customer. If the destination is unreachable or not human (e.g., with voicemail detection), the assistant delivers the `fallbackMessage` to the customer and optionally ends the call.\n\n@default 'blind-transfer'", - "enum": [ - "blind-transfer", - "blind-transfer-add-summary-to-sip-header", - "warm-transfer-say-message", - "warm-transfer-say-summary", - "warm-transfer-twiml", - "warm-transfer-wait-for-operator-to-speak-first-and-then-say-message", - "warm-transfer-wait-for-operator-to-speak-first-and-then-say-summary", - "warm-transfer-experimental" - ] - }, - "message": { - "description": "This is the message the assistant will deliver to the destination party before connecting the customer.\n\nUsage:\n- Used only when `mode` is `blind-transfer-add-summary-to-sip-header`, `warm-transfer-say-message`, `warm-transfer-wait-for-operator-to-speak-first-and-then-say-message`, or `warm-transfer-experimental`.", - "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/components/schemas/CustomMessage" - } - ] + "keytermsPrompt": { + "description": "Keyterms prompting improves recognition accuracy for specific words and phrases.\nCan include up to 100 keyterms, each up to 50 characters.\nCosts an additional $0.04/hour on universal-streaming-english and is included at no extra cost on universal-3-5-pro.", + "type": "array", + "items": { + "type": "string", + "maxLength": 50 + } }, - "timeout": { + "endUtteranceSilenceThreshold": { "type": "number", - "description": "This is the timeout in seconds for the warm-transfer-wait-for-operator-to-speak-first-and-then-say-message/summary\n\n@default 60", - "minimum": 1, - "maximum": 600, - "default": 60 - }, - "sipVerb": { - "type": "object", - "description": "This specifies the SIP verb to use while transferring the call.\n- 'refer': Uses SIP REFER to transfer the call (default)\n- 'bye': Ends current call with SIP BYE\n- 'dial': Uses SIP DIAL to transfer the call", - "default": "refer", - "enum": [ - "refer", - "bye", - "dial" - ] - }, - "holdAudioUrl": { - "type": "string", - "description": "This is the URL to an audio file played while the customer is on hold during transfer.\n\nUsage:\n- Used only when `mode` is `warm-transfer-experimental`.\n- Used when transferring calls to play hold audio for the customer.\n- Must be a publicly accessible URL to an audio file.\n- Supported formats: MP3 and WAV.\n- If not provided, the default hold audio will be used." - }, - "transferCompleteAudioUrl": { - "type": "string", - "description": "This is the URL to an audio file played after the warm transfer message or summary is delivered to the destination party.\nIt can be used to play a custom sound like 'beep' to notify that the transfer is complete.\n\nUsage:\n- Used only when `mode` is `warm-transfer-experimental`.\n- Used when transferring calls to play hold audio for the destination party.\n- Must be a publicly accessible URL to an audio file.\n- Supported formats: MP3 and WAV." - }, - "twiml": { - "type": "string", - "description": "This is the TwiML instructions to execute on the destination call leg before connecting the customer.\n\nUsage:\n- Used only when `mode` is `warm-transfer-twiml`.\n- Supports only `Play`, `Say`, `Gather`, `Hangup` and `Pause` verbs.\n- Maximum length is 4096 characters.\n\nExample:\n```\nHello, transferring a customer to you.\n\nThey called about billing questions.\n```", - "maxLength": 4096 - }, - "summaryPlan": { - "description": "This is the plan for generating a summary of the call to present to the destination party.\n\nUsage:\n- Used only when `mode` is `blind-transfer-add-summary-to-sip-header` or `warm-transfer-say-summary` or `warm-transfer-wait-for-operator-to-speak-first-and-then-say-summary` or `warm-transfer-experimental`.", - "allOf": [ - { - "$ref": "#/components/schemas/SummaryPlan" - } - ] + "description": "The duration of the end utterance silence threshold in milliseconds." }, - "sipHeadersInReferToEnabled": { + "disablePartialTranscripts": { "type": "boolean", - "description": "This flag includes the sipHeaders from above in the refer to sip uri as url encoded query params.\n\n@default false" + "description": "Disable partial transcripts.\nSet to `true` to not receive partial transcripts. Defaults to `false`." }, "fallbackPlan": { - "description": "This configures the fallback plan when the transfer fails (destination unreachable, busy, or not human).\n\nUsage:\n- Used only when `mode` is `warm-transfer-experimental`.\n- If not provided when using `warm-transfer-experimental`, a default message will be used.", + "description": "This is the plan for transcriber provider fallbacks in the event that the primary transcriber provider fails.", "allOf": [ { - "$ref": "#/components/schemas/TransferFallbackPlan" + "$ref": "#/components/schemas/FallbackTranscriberPlan" } ] } }, "required": [ - "mode" + "provider" ] }, - "TransferDestinationNumber": { + "AzureSpeechTranscriber": { "type": "object", "properties": { - "message": { - "description": "This is spoken to the customer before connecting them to the destination.\n\nUsage:\n- If this is not provided and transfer tool messages is not provided, default is \"Transferring the call now\".\n- If set to \"\", nothing is spoken. This is useful when you want to silently transfer. This is especially useful when transferring between assistants in a squad. In this scenario, you likely also want to set `assistant.firstMessageMode=assistant-speaks-first-with-model-generated-message` for the destination assistant.\n\nThis accepts a string or a ToolMessageStart class. Latter is useful if you want to specify multiple messages for different languages through the `contents` field.", - "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/components/schemas/CustomMessage" - } - ] - }, - "type": { + "provider": { "type": "string", + "description": "This is the transcription provider that will be used.", "enum": [ - "number" - ] - }, - "numberE164CheckEnabled": { - "type": "boolean", - "description": "This is the flag to toggle the E164 check for the `number` field. This is an advanced property which should be used if you know your use case requires it.\n\nUse cases:\n- `false`: To allow non-E164 numbers like `+001234567890`, `1234`, or `abc`. This is useful for dialing out to non-E164 numbers on your SIP trunks.\n- `true` (default): To allow only E164 numbers like `+14155551234`. This is standard for PSTN calls.\n\nIf `false`, the `number` is still required to only contain alphanumeric characters (regex: `/^\\+?[a-zA-Z0-9]+$/`).\n\n@default true (E164 check is enabled)", - "default": true - }, - "number": { - "type": "string", - "description": "This is the phone number to transfer the call to.", - "minLength": 3, - "maxLength": 40 - }, - "extension": { - "type": "string", - "description": "This is the extension to dial after transferring the call to the `number`.", - "minLength": 1, - "maxLength": 10 - }, - "callerId": { - "type": "string", - "description": "This is the caller ID to use when transferring the call to the `number`.\n\nUsage:\n- If not provided, the caller ID will be the number the call is coming from. Example, +14151111111 calls in to and the assistant transfers out to +16470000000. +16470000000 will see +14151111111 as the caller.\n- To change this behavior, provide a `callerId`.\n- Set to '{{customer.number}}' to always use the customer's number as the caller ID.\n- Set to '{{phoneNumber.number}}' to always use the phone number of the assistant as the caller ID.\n- Set to any E164 number to always use that number as the caller ID. This needs to be a number that is owned or verified by your Transport provider like Twilio.\n\nFor Twilio, you can read up more here: https://www.twilio.com/docs/voice/twiml/dial#callerid", - "maxLength": 40 - }, - "transferPlan": { - "description": "This configures how transfer is executed and the experience of the destination party receiving the call. Defaults to `blind-transfer`.\n\n@default `transferPlan.mode='blind-transfer'`", - "allOf": [ - { - "$ref": "#/components/schemas/TransferPlan" - } - ] - }, - "description": { - "type": "string", - "description": "This is the description of the destination, used by the AI to choose when and how to transfer the call." - } - }, - "required": [ - "type", - "number" - ] - }, - "TransferDestinationSip": { - "type": "object", - "properties": { - "message": { - "description": "This is spoken to the customer before connecting them to the destination.\n\nUsage:\n- If this is not provided and transfer tool messages is not provided, default is \"Transferring the call now\".\n- If set to \"\", nothing is spoken. This is useful when you want to silently transfer. This is especially useful when transferring between assistants in a squad. In this scenario, you likely also want to set `assistant.firstMessageMode=assistant-speaks-first-with-model-generated-message` for the destination assistant.\n\nThis accepts a string or a ToolMessageStart class. Latter is useful if you want to specify multiple messages for different languages through the `contents` field.", - "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/components/schemas/CustomMessage" - } + "azure" ] }, - "type": { + "language": { "type": "string", + "description": "This is the language that will be set for the transcription. The list of languages Azure supports can be found here: https://learn.microsoft.com/en-us/azure/ai-services/speech-service/language-support?tabs=stt", "enum": [ - "sip" + "af-ZA", + "am-ET", + "ar-AE", + "ar-BH", + "ar-DZ", + "ar-EG", + "ar-IL", + "ar-IQ", + "ar-JO", + "ar-KW", + "ar-LB", + "ar-LY", + "ar-MA", + "ar-OM", + "ar-PS", + "ar-QA", + "ar-SA", + "ar-SY", + "ar-TN", + "ar-YE", + "az-AZ", + "bg-BG", + "bn-IN", + "bs-BA", + "ca-ES", + "cs-CZ", + "cy-GB", + "da-DK", + "de-AT", + "de-CH", + "de-DE", + "el-GR", + "en-AU", + "en-CA", + "en-GB", + "en-GH", + "en-HK", + "en-IE", + "en-IN", + "en-KE", + "en-NG", + "en-NZ", + "en-PH", + "en-SG", + "en-TZ", + "en-US", + "en-ZA", + "es-AR", + "es-BO", + "es-CL", + "es-CO", + "es-CR", + "es-CU", + "es-DO", + "es-EC", + "es-ES", + "es-GQ", + "es-GT", + "es-HN", + "es-MX", + "es-NI", + "es-PA", + "es-PE", + "es-PR", + "es-PY", + "es-SV", + "es-US", + "es-UY", + "es-VE", + "et-EE", + "eu-ES", + "fa-IR", + "fi-FI", + "fil-PH", + "fr-BE", + "fr-CA", + "fr-CH", + "fr-FR", + "ga-IE", + "gl-ES", + "gu-IN", + "he-IL", + "hi-IN", + "hr-HR", + "hu-HU", + "hy-AM", + "id-ID", + "is-IS", + "it-CH", + "it-IT", + "ja-JP", + "jv-ID", + "ka-GE", + "kk-KZ", + "km-KH", + "kn-IN", + "ko-KR", + "lo-LA", + "lt-LT", + "lv-LV", + "mk-MK", + "ml-IN", + "mn-MN", + "mr-IN", + "ms-MY", + "mt-MT", + "my-MM", + "nb-NO", + "ne-NP", + "nl-BE", + "nl-NL", + "pa-IN", + "pl-PL", + "ps-AF", + "pt-BR", + "pt-PT", + "ro-RO", + "ru-RU", + "si-LK", + "sk-SK", + "sl-SI", + "so-SO", + "sq-AL", + "sr-RS", + "sv-SE", + "sw-KE", + "sw-TZ", + "ta-IN", + "te-IN", + "th-TH", + "tr-TR", + "uk-UA", + "ur-IN", + "uz-UZ", + "vi-VN", + "wuu-CN", + "yue-CN", + "zh-CN", + "zh-CN-shandong", + "zh-CN-sichuan", + "zh-HK", + "zh-TW", + "zu-ZA" ] }, - "sipUri": { + "segmentationStrategy": { "type": "string", - "description": "This is the SIP URI to transfer the call to." + "description": "Controls how phrase boundaries are detected, enabling either simple time/silence heuristics or more advanced semantic segmentation.", + "enum": [ + "Default", + "Time", + "Semantic" + ] }, - "transferPlan": { - "description": "This configures how transfer is executed and the experience of the destination party receiving the call. Defaults to `blind-transfer`.\n\n@default `transferPlan.mode='blind-transfer'`", + "segmentationSilenceTimeoutMs": { + "type": "number", + "description": "Duration of detected silence after which the service finalizes a phrase. Configure to adjust sensitivity to pauses in speech.", + "minimum": 100, + "maximum": 5000 + }, + "segmentationMaximumTimeMs": { + "type": "number", + "description": "Maximum duration a segment can reach before being cut off when using time-based segmentation.", + "minimum": 20000, + "maximum": 70000 + }, + "fallbackPlan": { + "description": "This is the plan for transcriber provider fallbacks in the event that the primary transcriber provider fails.", "allOf": [ { - "$ref": "#/components/schemas/TransferPlan" + "$ref": "#/components/schemas/FallbackTranscriberPlan" } ] - }, - "sipHeaders": { - "type": "object", - "description": "These are custom headers to be added to SIP refer during transfer call." - }, - "description": { - "type": "string", - "description": "This is the description of the destination, used by the AI to choose when and how to transfer the call." } }, "required": [ - "type", - "sipUri" + "provider" ] }, - "CreateTransferCallToolDTO": { + "CartesiaTranscriber": { "type": "object", "properties": { - "messages": { - "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" - } - ] - } + "provider": { + "type": "string", + "enum": [ + "cartesia" + ] }, - "type": { + "model": { "type": "string", "enum": [ - "transferCall" + "ink-whisper", + "ink-2" ] }, - "destinations": { - "type": "array", - "description": "These are the destinations that the call can be transferred to. If no destinations are provided, server.url will be used to get the transfer destination once the tool is called.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/TransferDestinationAssistant", - "title": "Assistant" - }, - { - "$ref": "#/components/schemas/TransferDestinationNumber", - "title": "Number" - }, - { - "$ref": "#/components/schemas/TransferDestinationSip", - "title": "Sip" - } - ] - } + "language": { + "type": "string", + "enum": [ + "aa", + "ab", + "ae", + "af", + "ak", + "am", + "an", + "ar", + "as", + "av", + "ay", + "az", + "ba", + "be", + "bg", + "bh", + "bi", + "bm", + "bn", + "bo", + "br", + "bs", + "ca", + "ce", + "ch", + "co", + "cr", + "cs", + "cu", + "cv", + "cy", + "da", + "de", + "dv", + "dz", + "ee", + "el", + "en", + "eo", + "es", + "et", + "eu", + "fa", + "ff", + "fi", + "fj", + "fo", + "fr", + "fy", + "ga", + "gd", + "gl", + "gn", + "gu", + "gv", + "ha", + "he", + "hi", + "ho", + "hr", + "ht", + "hu", + "hy", + "hz", + "ia", + "id", + "ie", + "ig", + "ii", + "ik", + "io", + "is", + "it", + "iu", + "ja", + "jv", + "ka", + "kg", + "ki", + "kj", + "kk", + "kl", + "km", + "kn", + "ko", + "kr", + "ks", + "ku", + "kv", + "kw", + "ky", + "la", + "lb", + "lg", + "li", + "ln", + "lo", + "lt", + "lu", + "lv", + "mg", + "mh", + "mi", + "mk", + "ml", + "mn", + "mr", + "ms", + "mt", + "my", + "na", + "nb", + "nd", + "ne", + "ng", + "nl", + "nn", + "no", + "nr", + "nv", + "ny", + "oc", + "oj", + "om", + "or", + "os", + "pa", + "pi", + "pl", + "ps", + "pt", + "qu", + "rm", + "rn", + "ro", + "ru", + "rw", + "sa", + "sc", + "sd", + "se", + "sg", + "si", + "sk", + "sl", + "sm", + "sn", + "so", + "sq", + "sr", + "ss", + "st", + "su", + "sv", + "sw", + "ta", + "te", + "tg", + "th", + "ti", + "tk", + "tl", + "tn", + "to", + "tr", + "ts", + "tt", + "tw", + "ty", + "ug", + "uk", + "ur", + "uz", + "ve", + "vi", + "vo", + "wa", + "wo", + "xh", + "yi", + "yue", + "yo", + "za", + "zh", + "zu" + ] }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "fallbackPlan": { + "description": "This is the plan for transcriber provider fallbacks in the event that the primary transcriber provider fails.", "allOf": [ { - "$ref": "#/components/schemas/ToolRejectionPlan" + "$ref": "#/components/schemas/FallbackTranscriberPlan" } ] } }, "required": [ - "type" + "provider" ] }, - "ContextEngineeringPlanLastNMessages": { + "BackoffPlan": { "type": "object", "properties": { "type": { - "type": "string", + "type": "object", + "description": "This is the type of backoff plan to use. Defaults to fixed.\n\n@default fixed", "enum": [ - "lastNMessages" - ] + "fixed", + "exponential" + ], + "example": "fixed" }, - "maxMessages": { + "maxRetries": { "type": "number", - "description": "This is the maximum number of messages to include in the context engineering plan.", - "minimum": 0 + "description": "This is the maximum number of retries to attempt if the request fails. Defaults to 0 (no retries).\n\n@default 0", + "minimum": 0, + "maximum": 10, + "example": 0 + }, + "baseDelaySeconds": { + "type": "number", + "description": "This is the base delay in seconds. For linear backoff, this is the delay between each retry. For exponential backoff, this is the initial delay.", + "minimum": 0, + "maximum": 10, + "example": 1 + }, + "excludedStatusCodes": { + "description": "This is the excluded status codes. If the response status code is in this list, the request will not be retried.\nBy default, the request will be retried for any non-2xx status code.", + "example": [ + 400, + 401, + 403, + 404 + ], + "type": "array", + "items": { + "type": "object" + } } }, "required": [ "type", - "maxMessages" + "maxRetries", + "baseDelaySeconds" ] }, - "ContextEngineeringPlanNone": { + "Server": { "type": "object", "properties": { - "type": { + "timeoutSeconds": { + "type": "number", + "description": "This is the timeout in seconds for the request. Defaults to 20 seconds.\n\n@default 20", + "minimum": 1, + "maximum": 300, + "example": 20 + }, + "credentialId": { "type": "string", - "enum": [ - "none" + "description": "The credential ID for server authentication", + "example": "550e8400-e29b-41d4-a716-446655440000" + }, + "staticIpAddressesEnabled": { + "type": "boolean", + "description": "If enabled, requests will originate from a static set of IPs owned and managed by Vapi.\n\n@default false", + "example": false + }, + "encryptedPaths": { + "type": "array", + "description": "This is the paths to encrypt in the request body if credentialId and encryptionPlan are defined.", + "items": { + "type": "string" + } + }, + "url": { + "type": "string", + "description": "This is where the request will be sent." + }, + "headers": { + "type": "object", + "description": "These are the headers to include in the request.\n\nEach key-value pair represents a header name and its value.\n\nNote: Specifying an Authorization header here will override the authorization provided by the `credentialId` (if provided). This is an anti-pattern and should be avoided outside of edge case scenarios." + }, + "backoffPlan": { + "description": "This is the backoff plan if the request fails. Defaults to undefined (the request will not be retried).\n\n@default undefined (the request will not be retried)", + "allOf": [ + { + "$ref": "#/components/schemas/BackoffPlan" + } ] } - }, - "required": [ - "type" - ] + } }, - "ContextEngineeringPlanAll": { + "CustomTranscriber": { "type": "object", "properties": { - "type": { + "provider": { "type": "string", + "description": "This is the transcription provider that will be used. Use `custom-transcriber` for providers that are not natively supported.", "enum": [ - "all" + "custom-transcriber" ] - } - }, - "required": [ - "type" - ] - }, - "VariableExtractionAlias": { - "type": "object", - "properties": { - "key": { - "type": "string", - "description": "This is the key of the variable.\n\nThis variable will be accessible during the call as `{{key}}` and stored in `call.artifact.variableValues` after the call.\n\nRules:\n- Must start with a letter (a-z, A-Z).\n- Subsequent characters can be letters, numbers, or underscores.\n- Minimum length of 1 and maximum length of 40.", - "minLength": 1, - "maxLength": 40, - "pattern": "/^[a-zA-Z][a-zA-Z0-9_]*$/" - }, - "value": { - "type": "string", - "description": "This is the value of the variable.\n\nThis can reference existing variables, use filters, and perform transformations.\n\nExamples: \"{{name}}\", \"{{customer.email}}\", \"Hello {{name | upcase}}\"", - "maxLength": 10000 - } - }, - "required": [ - "key", - "value" - ] - }, - "VariableExtractionPlan": { - "type": "object", - "properties": { - "schema": { - "description": "This is the schema to extract.\n\nExamples:\n1. To extract object properties, you can use the following schema:\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n },\n \"age\": {\n \"type\": \"number\"\n }\n }\n}\n```\n\nThese will be extracted as `{{ name }}` and `{{ age }}` respectively. To emphasize, object properties are extracted as direct global variables.\n\n2. To extract nested properties, you can use the following schema:\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"object\",\n \"properties\": {\n \"first\": {\n \"type\": \"string\"\n },\n \"last\": {\n \"type\": \"string\"\n }\n }\n }\n }\n}\n```\n\nThese will be extracted as `{{ name }}`. And, `{{ name.first }}` and `{{ name.last }}` will be accessible.\n\n3. To extract array items, you can use the following schema:\n```json\n{\n \"type\": \"array\",\n \"title\": \"zipCodes\",\n \"items\": {\n \"type\": \"string\"\n }\n}\n```\n\nThis will be extracted as `{{ zipCodes }}`. To access the array items, you can use `{{ zipCodes[0] }}` and `{{ zipCodes[1] }}`.\n\n4. To extract array of objects, you can use the following schema:\n\n```json\n{\n \"type\": \"array\",\n \"name\": \"people\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n },\n \"age\": {\n \"type\": \"number\"\n },\n \"zipCodes\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n }\n }\n}\n```\n\nThis will be extracted as `{{ people }}`. To access the array items, you can use `{{ people[n].name }}`, `{{ people[n].age }}`, `{{ people[n].zipCodes }}`, `{{ people[n].zipCodes[0] }}` and `{{ people[n].zipCodes[1] }}`.", - "allOf": [ - { - "$ref": "#/components/schemas/JsonSchema" - } - ] - }, - "aliases": { - "description": "These are additional variables to create.\n\nThese will be accessible during the call as `{{key}}` and stored in `call.artifact.variableValues` after the call.\n\nExample:\n```json\n{\n \"aliases\": [\n {\n \"key\": \"customerName\",\n \"value\": \"{{name}}\"\n },\n {\n \"key\": \"fullName\",\n \"value\": \"{{firstName}} {{lastName}}\"\n },\n {\n \"key\": \"greeting\",\n \"value\": \"Hello {{name}}, welcome to {{company}}!\"\n },\n {\n \"key\": \"customerCity\",\n \"value\": \"{{addresses[0].city}}\"\n },\n {\n \"key\": \"something\",\n \"value\": \"{{any liquid}}\"\n }\n ]\n}\n```\n\nThis will create variables `customerName`, `fullName`, `greeting`, `customerCity`, and `something`. To access these variables, you can reference them as `{{customerName}}`, `{{fullName}}`, `{{greeting}}`, `{{customerCity}}`, and `{{something}}`.", - "type": "array", - "items": { - "$ref": "#/components/schemas/VariableExtractionAlias" - } - } - } - }, - "HandoffDestinationAssistant": { - "type": "object", - "properties": { - "type": { - "type": "string", - "enum": [ - "assistant" - ] - }, - "contextEngineeringPlan": { - "description": "This is the plan for manipulating the message context before handing off the call to the next assistant.", - "oneOf": [ - { - "$ref": "#/components/schemas/ContextEngineeringPlanLastNMessages", - "title": "Last N Messages" - }, - { - "$ref": "#/components/schemas/ContextEngineeringPlanNone", - "title": "None" - }, - { - "$ref": "#/components/schemas/ContextEngineeringPlanAll", - "title": "All" - } - ] - }, - "assistantName": { - "type": "string", - "description": "This is the assistant to transfer the call to. You must provide either assistantName or assistantId." - }, - "assistantId": { - "type": "string", - "description": "This is the assistant id to transfer the call to. You must provide either assistantName or assistantId." }, - "assistant": { - "description": "This is a transient assistant to transfer the call to. You may provide a transient assistant in the response `handoff-destination-request` in a dynamic handoff.", + "server": { + "description": "This is where the transcription request will be sent.\n\nUsage:\n1. Vapi will initiate a websocket connection with `server.url`.\n\n2. Vapi will send an initial text frame with the sample rate. Format:\n```\n {\n \"type\": \"start\",\n \"encoding\": \"linear16\", // 16-bit raw PCM format\n \"container\": \"raw\",\n \"sampleRate\": {{sampleRate}},\n \"channels\": 2 // customer is channel 0, assistant is channel 1\n }\n```\n\n3. Vapi will send the audio data in 16-bit raw PCM format as binary frames.\n\n4. You can read the messages something like this:\n```\nws.on('message', (data, isBinary) => {\n if (isBinary) {\n pcmBuffer = Buffer.concat([pcmBuffer, data]);\n console.log(`Received PCM data, buffer size: ${pcmBuffer.length}`);\n } else {\n console.log('Received message:', JSON.parse(data.toString()));\n }\n});\n```\n\n5. You will respond with transcriptions as you have them. Format:\n```\n {\n \"type\": \"transcriber-response\",\n \"transcription\": \"Hello, world!\",\n \"channel\": \"customer\" | \"assistant\"\n }\n```", "allOf": [ { - "$ref": "#/components/schemas/CreateAssistantDTO" + "$ref": "#/components/schemas/Server" } ] }, - "variableExtractionPlan": { - "description": "This is the variable extraction plan for the handoff tool.", + "fallbackPlan": { + "description": "This is the plan for transcriber provider fallbacks in the event that the primary transcriber provider fails.", "allOf": [ { - "$ref": "#/components/schemas/VariableExtractionPlan" + "$ref": "#/components/schemas/FallbackTranscriberPlan" } ] - }, - "description": { - "type": "string", - "description": "This is the description of the destination, used by the AI to choose when and how to transfer the call." } }, "required": [ - "type" + "provider", + "server" ] }, - "HandoffDestinationDynamic": { + "DeepgramTranscriber": { "type": "object", "properties": { - "type": { + "provider": { "type": "string", + "description": "This is the transcription provider that will be used.", "enum": [ - "dynamic" + "deepgram" ] }, - "server": { - "description": "This is where Vapi will send the handoff-destination-request webhook in a dynamic handoff.\n\nThe order of precedence is:\n\n1. tool.server.url\n2. assistant.server.url\n3. phoneNumber.server.url\n4. org.server.url", - "allOf": [ + "model": { + "description": "This is the Deepgram model that will be used. A list of models can be found here: https://developers.deepgram.com/docs/models-languages-overview", + "oneOf": [ { - "$ref": "#/components/schemas/Server" + "type": "string", + "enum": [ + "nova-3", + "nova-3-general", + "nova-3-medical", + "nova-2", + "nova-2-general", + "nova-2-meeting", + "nova-2-phonecall", + "nova-2-finance", + "nova-2-conversationalai", + "nova-2-voicemail", + "nova-2-video", + "nova-2-medical", + "nova-2-drivethru", + "nova-2-automotive", + "nova", + "nova-general", + "nova-phonecall", + "nova-medical", + "enhanced", + "enhanced-general", + "enhanced-meeting", + "enhanced-phonecall", + "enhanced-finance", + "base", + "base-general", + "base-meeting", + "base-phonecall", + "base-finance", + "base-conversationalai", + "base-voicemail", + "base-video", + "whisper", + "flux-general-en", + "flux-general-multi" + ] + }, + { + "type": "string" } ] }, - "description": { - "type": "string", - "description": "This is the description of the destination, used by the AI to choose when and how to transfer the call." - } - }, - "required": [ - "type" - ] - }, - "CreateHandoffToolDTO": { - "type": "object", - "properties": { - "messages": { - "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" - } - ] - } - }, - "type": { + "language": { "type": "string", - "description": "This is the type of the tool.\nWhen you're using handoff tool, we recommend adding this to your system prompt\n---\n# System context\n\nYou are part of a multi-agent system designed to make agent coordination and execution easy. Agents uses two primary abstraction: **Agents** and **Handoffs**. An agent encompasses instructions and tools and can hand off a conversation to another agent when appropriate. Handoffs are achieved by calling a handoff function, generally named `handoff_to_`. Handoffs between agents are handled seamlessly in the background; do not mention or draw attention to these handoffs in your conversation with the user.\n\n# Agent context\n\n{put your agent system prompt here}\n---", + "description": "This is the language that will be set for the transcription. The list of languages Deepgram supports can be found here: https://developers.deepgram.com/docs/models-languages-overview", "enum": [ - "handoff" + "ar", + "az", + "ba", + "be", + "bg", + "bn", + "br", + "bs", + "ca", + "cs", + "da", + "da-DK", + "de", + "de-CH", + "el", + "en", + "en-AU", + "en-CA", + "en-GB", + "en-IE", + "en-IN", + "en-NZ", + "en-US", + "es", + "es-419", + "es-LATAM", + "et", + "eu", + "fa", + "fi", + "fr", + "fr-CA", + "ha", + "haw", + "he", + "hi", + "hi-Latn", + "hr", + "hu", + "id", + "is", + "it", + "ja", + "jw", + "kn", + "ko", + "ko-KR", + "ln", + "lt", + "lv", + "mk", + "mr", + "ms", + "multi", + "nl", + "nl-BE", + "no", + "pl", + "pt", + "pt-BR", + "pt-PT", + "ro", + "ru", + "sk", + "sl", + "sn", + "so", + "sr", + "su", + "sv", + "sv-SE", + "ta", + "taq", + "te", + "th", + "th-TH", + "tl", + "tr", + "tt", + "uk", + "ur", + "vi", + "yo", + "zh", + "zh-CN", + "zh-HK", + "zh-Hans", + "zh-Hant", + "zh-TW" ] }, - "destinations": { - "type": "array", - "description": "These are the destinations that the call can be handed off to.\n\nUsage:\n1. Single destination\n\nUse `assistantId` to handoff the call to a saved assistant, or `assistantName` to handoff the call to an assistant in the same squad.\n\n```json\n{\n \"tools\": [\n {\n \"type\": \"handoff\",\n \"destinations\": [\n {\n \"type\": \"assistant\",\n \"assistantId\": \"assistant-123\", // or \"assistantName\": \"Assistant123\"\n \"description\": \"customer wants to be handed off to assistant-123\",\n \"contextEngineeringPlan\": {\n \"type\": \"all\"\n }\n }\n ],\n }\n ]\n}\n```\n\n2. Multiple destinations\n\n2.1. Multiple Tools, Each With One Destination (OpenAI recommended)\n\n```json\n{\n \"tools\": [\n {\n \"type\": \"handoff\",\n \"destinations\": [\n {\n \"type\": \"assistant\",\n \"assistantId\": \"assistant-123\",\n \"description\": \"customer wants to be handed off to assistant-123\",\n \"contextEngineeringPlan\": {\n \"type\": \"all\"\n }\n },\n ],\n },\n {\n \"type\": \"handoff\",\n \"destinations\": [\n {\n \"type\": \"assistant\",\n \"assistantId\": \"assistant-456\",\n \"description\": \"customer wants to be handed off to assistant-456\",\n \"contextEngineeringPlan\": {\n \"type\": \"all\"\n }\n }\n ],\n }\n ]\n}\n```\n\n2.2. One Tool, Multiple Destinations (Anthropic recommended)\n\n```json\n{\n \"tools\": [\n {\n \"type\": \"handoff\",\n \"destinations\": [\n {\n \"type\": \"assistant\",\n \"assistantId\": \"assistant-123\",\n \"description\": \"customer wants to be handed off to assistant-123\",\n \"contextEngineeringPlan\": {\n \"type\": \"all\"\n }\n },\n {\n \"type\": \"assistant\",\n \"assistantId\": \"assistant-456\",\n \"description\": \"customer wants to be handed off to assistant-456\",\n \"contextEngineeringPlan\": {\n \"type\": \"all\"\n }\n }\n ],\n }\n ]\n}\n```\n\n3. Dynamic destination\n\n3.1 To determine the destination dynamically, supply a `dynamic` handoff destination type and a `server` object.\n VAPI will send a handoff-destination-request webhook to the `server.url`.\n The response from the server will be used as the destination (if valid).\n\n```json\n{\n \"tools\": [\n {\n \"type\": \"handoff\",\n \"destinations\": [\n {\n \"type\": \"dynamic\",\n \"server\": {\n \"url\": \"https://example.com\"\n }\n }\n ],\n }\n ]\n}\n```\n\n3.2. To pass custom parameters to the server, you can use the `function` object.\n\n```json\n{\n \"tools\": [\n {\n \"type\": \"handoff\",\n \"destinations\": [\n {\n \"type\": \"dynamic\",\n \"server\": {\n \"url\": \"https://example.com\"\n },\n }\n ],\n \"function\": {\n \"name\": \"handoff\",\n \"description\": \"Call this function when the customer is ready to be handed off to the next assistant\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"destination\": {\n \"type\": \"string\",\n \"description\": \"Use dynamic when customer is ready to be handed off to the next assistant\",\n \"enum\": [\"dynamic\"]\n },\n \"customerAreaCode\": {\n \"type\": \"number\",\n \"description\": \"Area code of the customer\"\n },\n \"customerIntent\": {\n \"type\": \"string\",\n \"enum\": [\"new-customer\", \"existing-customer\"],\n \"description\": \"Use new-customer when customer is a new customer, existing-customer when customer is an existing customer\"\n },\n \"customerSentiment\": {\n \"type\": \"string\",\n \"enum\": [\"positive\", \"negative\", \"neutral\"],\n \"description\": \"Use positive when customer is happy, negative when customer is unhappy, neutral when customer is neutral\"\n }\n }\n }\n }\n }\n ]\n}\n```\n\nThe properties `customerAreaCode`, `customerIntent`, and `customerSentiment` will be passed to the server in the webhook request body.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/HandoffDestinationAssistant", - "title": "Assistant" - }, - { - "$ref": "#/components/schemas/HandoffDestinationDynamic", - "title": "Dynamic" - } - ] - } + "smartFormat": { + "type": "boolean", + "description": "This will be use smart format option provided by Deepgram. It's default disabled because it can sometimes format numbers as times but it's getting better.", + "example": false }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", - "allOf": [ - { - "$ref": "#/components/schemas/ToolRejectionPlan" - } - ] - } - }, - "required": [ - "type" - ] - }, - "CreateCustomKnowledgeBaseDTO": { - "type": "object", - "properties": { - "provider": { - "type": "string", - "description": "This knowledge base is bring your own knowledge base implementation.", - "enum": [ - "custom-knowledge-base" - ] + "mipOptOut": { + "type": "boolean", + "description": "If set to true, this will add mip_opt_out=true as a query parameter of all API requests. See https://developers.deepgram.com/docs/the-deepgram-model-improvement-partnership-program#want-to-opt-out\n\nThis will only be used if you are using your own Deepgram API key.\n\n@default false", + "example": false, + "default": false }, - "server": { - "description": "This is where the knowledge base request will be sent.\n\nRequest Example:\n\nPOST https://{server.url}\nContent-Type: application/json\n\n{\n \"messsage\": {\n \"type\": \"knowledge-base-request\",\n \"messages\": [\n {\n \"role\": \"user\",\n \"content\": \"Why is ocean blue?\"\n }\n ],\n ...other metadata about the call...\n }\n}\n\nResponse Expected:\n```\n{\n \"message\": {\n \"role\": \"assistant\",\n \"content\": \"The ocean is blue because water absorbs everything but blue.\",\n }, // YOU CAN RETURN THE EXACT RESPONSE TO SPEAK\n \"documents\": [\n {\n \"content\": \"The ocean is blue primarily because water absorbs colors in the red part of the light spectrum and scatters the blue light, making it more visible to our eyes.\",\n \"similarity\": 1\n },\n {\n \"content\": \"Blue light is scattered more by the water molecules than other colors, enhancing the blue appearance of the ocean.\",\n \"similarity\": .5\n }\n ] // OR, YOU CAN RETURN AN ARRAY OF DOCUMENTS THAT WILL BE SENT TO THE MODEL\n}\n```", - "allOf": [ - { - "$ref": "#/components/schemas/Server" - } - ] - } - }, - "required": [ - "provider", - "server" - ] - }, - "KnowledgeBase": { - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "The name of the knowledge base", - "example": "My Knowledge Base" + "numerals": { + "type": "boolean", + "description": "If set to true, this will cause deepgram to convert spoken numbers to literal numerals. For example, \"my phone number is nine-seven-two...\" would become \"my phone number is 972...\"\n\n@default false", + "example": false }, - "provider": { - "type": "string", - "description": "The provider of the knowledge base", + "profanityFilter": { + "type": "boolean", + "description": "If set to true, Deepgram will replace profanity in transcripts with surrounding asterisks, e.g. \"f***\".\n\n@default false", + "example": false + }, + "redaction": { + "type": "array", + "description": "Enables redaction of sensitive information from transcripts.\n\nOptions include:\n- \"pci\": Redacts credit card numbers, expiration dates, and CVV.\n- \"pii\": Redacts personally identifiable information (names, locations, identifying numbers, etc.).\n- \"phi\": Redacts protected health information (medical conditions, drugs, injuries, etc.).\n- \"numbers\": Redacts numerical and identifying entities (dates, account numbers, SSNs, etc.).\n\nMultiple values can be provided to redact different categories simultaneously.\nRedacted content is replaced with entity labels like [CREDIT_CARD_1], [SSN_1], etc.\n\nSee https://developers.deepgram.com/docs/redaction for details.", "enum": [ - "google" + "pci", + "pii", + "phi", + "numbers" ], - "example": "google" + "example": [ + "pci", + "phi" + ], + "items": { + "type": "string", + "enum": [ + "pci", + "pii", + "phi", + "numbers" + ] + } }, - "model": { - "type": "string", - "description": "The model to use for the knowledge base", - "enum": [ - "gemini-2.5-pro", - "gemini-2.5-flash", - "gemini-2.5-flash-lite", - "gemini-2.0-flash-thinking-exp", - "gemini-2.0-pro-exp-02-05", - "gemini-2.0-flash", - "gemini-2.0-flash-lite", - "gemini-2.0-flash-exp", - "gemini-2.0-flash-realtime-exp", - "gemini-1.5-flash", - "gemini-1.5-flash-002", - "gemini-1.5-pro", - "gemini-1.5-pro-002", - "gemini-1.0-pro" - ] + "confidenceThreshold": { + "type": "number", + "description": "Transcripts below this confidence threshold will be discarded.\n\n@default 0.4", + "minimum": 0, + "maximum": 1, + "example": 0.4 }, - "description": { - "type": "string", - "description": "A description of the knowledge base" + "eotThreshold": { + "type": "number", + "description": "End-of-turn confidence required to finish a turn. Only used with Flux models.\n\n@default 0.7", + "minimum": 0.5, + "maximum": 0.9, + "example": 0.7 }, - "fileIds": { - "description": "The file IDs associated with this knowledge base", + "eotTimeoutMs": { + "type": "number", + "description": "A turn will be finished when this much time has passed after speech, regardless of EOT confidence. Only used with Flux models.\n\n@default 5000", + "minimum": 500, + "maximum": 10000, + "example": 5000 + }, + "languages": { + "description": "Language hints to bias Flux Multilingual (`flux-general-multi`) toward specific languages.\nProvide BCP-47 language codes (e.g. \"en\", \"es\", \"fr\"). Multiple hints can be given for\nmultilingual or code-switching scenarios. Omit for auto-detection. Only used with `flux-general-multi`.", + "example": [ + "en", + "es" + ], "type": "array", "items": { "type": "string" } - } - }, - "required": [ - "name", - "provider", - "description", - "fileIds" - ] - }, - "CreateQueryToolDTO": { - "type": "object", - "properties": { - "messages": { + }, + "keywords": { + "description": "These keywords are passed to the transcription model to help it pick up use-case specific words. Anything that may not be a common word, like your company name, should be added here.", "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" - } - ] + "type": "string", + "pattern": "/^\\p{L}[\\p{L}\\d]*(?::[+-]?\\d+)?$/u" } }, - "type": { - "type": "string", - "enum": [ - "query" - ], - "description": "The type of tool. \"query\" for Query tool." - }, - "knowledgeBases": { - "description": "The knowledge bases to query", + "keyterm": { + "description": "Keyterm Prompting allows you improve Keyword Recall Rate (KRR) for important keyterms or phrases up to 90%.", "type": "array", "items": { - "$ref": "#/components/schemas/KnowledgeBase" + "type": "string" } }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "endpointing": { + "type": "number", + "description": "This is the timeout after which Deepgram will send transcription on user silence. You can read in-depth documentation here: https://developers.deepgram.com/docs/endpointing.\n\nHere are the most important bits:\n- Defaults to 10. This is recommended for most use cases to optimize for latency.\n- 10 can cause some missing transcriptions since because of the shorter context. This mostly happens for one-word utterances. For those uses cases, it's recommended to try 300. It will add a bit of latency but the quality and reliability of the experience will be better.\n- If neither 10 nor 300 work, contact support@vapi.ai and we'll find another solution.\n\n@default 10", + "minimum": 10, + "maximum": 500 + }, + "fallbackPlan": { + "description": "This is the plan for transcriber provider fallbacks in the event that the primary transcriber provider fails.", "allOf": [ { - "$ref": "#/components/schemas/ToolRejectionPlan" + "$ref": "#/components/schemas/FallbackTranscriberPlan" } ] } }, "required": [ - "type" + "provider" ] }, - "CreateGoogleCalendarCreateEventToolDTO": { + "ElevenLabsTranscriber": { "type": "object", "properties": { - "messages": { - "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" - } - ] - } - }, - "type": { + "provider": { "type": "string", + "description": "This is the transcription provider that will be used.", "enum": [ - "google.calendar.event.create" - ], - "description": "The type of tool. \"google.calendar.event.create\" for Google Calendar Create Event tool." + "11labs" + ] }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", - "allOf": [ + "model": { + "description": "This is the model that will be used for the transcription.", + "oneOf": [ { - "$ref": "#/components/schemas/ToolRejectionPlan" + "type": "string", + "enum": [ + "scribe_v1", + "scribe_v2", + "scribe_v2_realtime" + ] } ] - } - }, - "required": [ - "type" - ] - }, - "CreateGoogleSheetsRowAppendToolDTO": { - "type": "object", - "properties": { - "messages": { - "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" - } - ] - } }, - "type": { + "language": { "type": "string", + "description": "This is the language that will be used for the transcription.", "enum": [ - "google.sheets.row.append" - ], - "description": "The type of tool. \"google.sheets.row.append\" for Google Sheets Row Append tool." + "aa", + "ab", + "ae", + "af", + "ak", + "am", + "an", + "ar", + "as", + "av", + "ay", + "az", + "ba", + "be", + "bg", + "bh", + "bi", + "bm", + "bn", + "bo", + "br", + "bs", + "ca", + "ce", + "ch", + "co", + "cr", + "cs", + "cu", + "cv", + "cy", + "da", + "de", + "dv", + "dz", + "ee", + "el", + "en", + "eo", + "es", + "et", + "eu", + "fa", + "ff", + "fi", + "fj", + "fo", + "fr", + "fy", + "ga", + "gd", + "gl", + "gn", + "gu", + "gv", + "ha", + "he", + "hi", + "ho", + "hr", + "ht", + "hu", + "hy", + "hz", + "ia", + "id", + "ie", + "ig", + "ii", + "ik", + "io", + "is", + "it", + "iu", + "ja", + "jv", + "ka", + "kg", + "ki", + "kj", + "kk", + "kl", + "km", + "kn", + "ko", + "kr", + "ks", + "ku", + "kv", + "kw", + "ky", + "la", + "lb", + "lg", + "li", + "ln", + "lo", + "lt", + "lu", + "lv", + "mg", + "mh", + "mi", + "mk", + "ml", + "mn", + "mr", + "ms", + "mt", + "my", + "na", + "nb", + "nd", + "ne", + "ng", + "nl", + "nn", + "no", + "nr", + "nv", + "ny", + "oc", + "oj", + "om", + "or", + "os", + "pa", + "pi", + "pl", + "ps", + "pt", + "qu", + "rm", + "rn", + "ro", + "ru", + "rw", + "sa", + "sc", + "sd", + "se", + "sg", + "si", + "sk", + "sl", + "sm", + "sn", + "so", + "sq", + "sr", + "ss", + "st", + "su", + "sv", + "sw", + "ta", + "te", + "tg", + "th", + "ti", + "tk", + "tl", + "tn", + "to", + "tr", + "ts", + "tt", + "tw", + "ty", + "ug", + "uk", + "ur", + "uz", + "ve", + "vi", + "vo", + "wa", + "wo", + "xh", + "yi", + "yue", + "yo", + "za", + "zh", + "zu" + ] }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "silenceThresholdSeconds": { + "type": "number", + "description": "This is the number of seconds of silence before VAD commits (0.3-3.0).", + "minimum": 0.3, + "maximum": 3, + "example": 1.5 + }, + "confidenceThreshold": { + "type": "number", + "description": "This is the VAD sensitivity (0.1-0.9, lower indicates more sensitive).", + "minimum": 0.1, + "maximum": 0.9, + "example": 0.4 + }, + "minSpeechDurationMs": { + "type": "number", + "description": "This is the minimum speech duration for VAD (50-2000ms).", + "minimum": 50, + "maximum": 2000, + "example": 100 + }, + "minSilenceDurationMs": { + "type": "number", + "description": "This is the minimum silence duration for VAD (50-2000ms).", + "minimum": 50, + "maximum": 2000, + "example": 100 + }, + "fallbackPlan": { + "description": "This is the plan for transcriber provider fallbacks in the event that the primary transcriber provider fails.", "allOf": [ { - "$ref": "#/components/schemas/ToolRejectionPlan" + "$ref": "#/components/schemas/FallbackTranscriberPlan" } ] } }, "required": [ - "type" + "provider" ] }, - "CreateGoogleCalendarCheckAvailabilityToolDTO": { + "GladiaCustomVocabularyConfigDTO": { "type": "object", "properties": { - "messages": { + "vocabulary": { "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", + "description": "Array of vocabulary items (strings or objects with value, pronunciations, intensity, language)", "items": { "oneOf": [ { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" + "type": "string" }, { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" + "$ref": "#/components/schemas/GladiaVocabularyItemDTO" } ] } }, - "type": { - "type": "string", - "enum": [ - "google.calendar.availability.check" - ], - "description": "The type of tool. \"google.calendar.availability.check\" for Google Calendar Check Availability tool." - }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", - "allOf": [ - { - "$ref": "#/components/schemas/ToolRejectionPlan" - } - ] + "defaultIntensity": { + "type": "number", + "minimum": 0, + "maximum": 1, + "description": "Default intensity for vocabulary items (0.0 to 1.0)", + "default": 0.5 } }, "required": [ - "type" + "vocabulary" ] }, - "CreateSlackSendMessageToolDTO": { + "GladiaTranscriber": { "type": "object", "properties": { - "messages": { + "provider": { + "type": "string", + "description": "This is the transcription provider that will be used.", + "enum": [ + "gladia" + ] + }, + "model": { + "description": "This is the Gladia model that will be used. Default is 'fast'", + "oneOf": [ + { + "type": "string", + "enum": [ + "fast", + "accurate", + "solaria-1" + ] + } + ] + }, + "languageBehaviour": { + "description": "Defines how the transcription model detects the audio language. Default value is 'automatic single language'.", + "oneOf": [ + { + "type": "string", + "enum": [ + "manual", + "automatic single language", + "automatic multiple languages" + ] + } + ] + }, + "language": { + "type": "string", + "description": "Defines the language to use for the transcription. Required when languageBehaviour is 'manual'.", + "enum": [ + "af", + "sq", + "am", + "ar", + "hy", + "as", + "az", + "ba", + "eu", + "be", + "bn", + "bs", + "br", + "bg", + "ca", + "zh", + "hr", + "cs", + "da", + "nl", + "en", + "et", + "fo", + "fi", + "fr", + "gl", + "ka", + "de", + "el", + "gu", + "ht", + "ha", + "haw", + "he", + "hi", + "hu", + "is", + "id", + "it", + "ja", + "jv", + "kn", + "kk", + "km", + "ko", + "lo", + "la", + "lv", + "ln", + "lt", + "lb", + "mk", + "mg", + "ms", + "ml", + "mt", + "mi", + "mr", + "mn", + "my", + "ne", + "no", + "nn", + "oc", + "ps", + "fa", + "pl", + "pt", + "pa", + "ro", + "ru", + "sa", + "sr", + "sn", + "sd", + "si", + "sk", + "sl", + "so", + "es", + "su", + "sw", + "sv", + "tl", + "tg", + "ta", + "tt", + "te", + "th", + "bo", + "tr", + "tk", + "uk", + "ur", + "uz", + "vi", + "cy", + "yi", + "yo" + ] + }, + "languages": { "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", + "description": "Defines the languages to use for the transcription. Required when languageBehaviour is 'manual'.", "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" - } + "type": "string", + "enum": [ + "af", + "sq", + "am", + "ar", + "hy", + "as", + "az", + "ba", + "eu", + "be", + "bn", + "bs", + "br", + "bg", + "ca", + "zh", + "hr", + "cs", + "da", + "nl", + "en", + "et", + "fo", + "fi", + "fr", + "gl", + "ka", + "de", + "el", + "gu", + "ht", + "ha", + "haw", + "he", + "hi", + "hu", + "is", + "id", + "it", + "ja", + "jv", + "kn", + "kk", + "km", + "ko", + "lo", + "la", + "lv", + "ln", + "lt", + "lb", + "mk", + "mg", + "ms", + "ml", + "mt", + "mi", + "mr", + "mn", + "my", + "ne", + "no", + "nn", + "oc", + "ps", + "fa", + "pl", + "pt", + "pa", + "ro", + "ru", + "sa", + "sr", + "sn", + "sd", + "si", + "sk", + "sl", + "so", + "es", + "su", + "sw", + "sv", + "tl", + "tg", + "ta", + "tt", + "te", + "th", + "bo", + "tr", + "tk", + "uk", + "ur", + "uz", + "vi", + "cy", + "yi", + "yo" ] } }, - "type": { + "transcriptionHint": { + "type": "string", + "description": "Provides a custom vocabulary to the model to improve accuracy of transcribing context specific words, technical terms, names, etc. If empty, this argument is ignored.\n⚠️ Warning ⚠️: Please be aware that the transcription_hint field has a character limit of 600. If you provide a transcription_hint longer than 600 characters, it will be automatically truncated to meet this limit.", + "maxLength": 600, + "example": "custom vocabulary" + }, + "prosody": { + "type": "boolean", + "description": "If prosody is true, you will get a transcription that can contain prosodies i.e. (laugh) (giggles) (malefic laugh) (toss) (music)… Default value is false.", + "example": false + }, + "audioEnhancer": { + "type": "boolean", + "description": "If true, audio will be pre-processed to improve accuracy but latency will increase. Default value is false.", + "example": false + }, + "confidenceThreshold": { + "type": "number", + "description": "Transcripts below this confidence threshold will be discarded.\n\n@default 0.4", + "minimum": 0, + "maximum": 1, + "example": 0.4 + }, + "endpointing": { + "type": "number", + "minimum": 0.01, + "maximum": 10, + "example": 0.05, + "description": "Endpointing time in seconds - time to wait before considering speech ended" + }, + "speechThreshold": { + "type": "number", + "minimum": 0, + "maximum": 1, + "example": 0.6, + "description": "Speech threshold - sensitivity configuration for speech detection (0.0 to 1.0)" + }, + "customVocabularyEnabled": { + "type": "boolean", + "example": false, + "description": "Enable custom vocabulary for improved accuracy" + }, + "customVocabularyConfig": { + "description": "Custom vocabulary configuration", + "allOf": [ + { + "$ref": "#/components/schemas/GladiaCustomVocabularyConfigDTO" + } + ] + }, + "region": { "type": "string", "enum": [ - "slack.message.send" + "us-west", + "eu-west" ], - "description": "The type of tool. \"slack.message.send\" for Slack Send Message tool." + "description": "Region for processing audio (us-west or eu-west)", + "example": "us-west" }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "receivePartialTranscripts": { + "type": "boolean", + "example": false, + "description": "Enable partial transcripts for low-latency streaming transcription" + }, + "fallbackPlan": { + "description": "This is the plan for transcriber provider fallbacks in the event that the primary transcriber provider fails.", "allOf": [ { - "$ref": "#/components/schemas/ToolRejectionPlan" + "$ref": "#/components/schemas/FallbackTranscriberPlan" } ] } }, "required": [ - "type" + "provider" ] }, - "McpToolMetadata": { + "SonioxContextGeneralItem": { "type": "object", "properties": { - "protocol": { + "key": { "type": "string", - "enum": [ - "sse", - "shttp" - ], - "description": "This is the protocol used for MCP communication. Defaults to Streamable HTTP." + "description": "The key describing the type of context (e.g., \"domain\", \"topic\", \"doctor\", \"organization\").", + "minLength": 1, + "example": "domain" + }, + "value": { + "type": "string", + "description": "The value for the context key (e.g., \"Healthcare\", \"Diabetes management consultation\").", + "minLength": 1, + "example": "Healthcare" } - } + }, + "required": [ + "key", + "value" + ] }, - "CreateMcpToolDTO": { + "SonioxTranscriber": { "type": "object", "properties": { - "messages": { + "provider": { + "type": "string", + "enum": [ + "soniox" + ] + }, + "model": { + "type": "string", + "enum": [ + "stt-rt-v4", + "stt-rt-v5" + ], + "description": "The Soniox model to use for transcription." + }, + "language": { + "type": "string", + "enum": [ + "aa", + "ab", + "ae", + "af", + "ak", + "am", + "an", + "ar", + "as", + "av", + "ay", + "az", + "ba", + "be", + "bg", + "bh", + "bi", + "bm", + "bn", + "bo", + "br", + "bs", + "ca", + "ce", + "ch", + "co", + "cr", + "cs", + "cu", + "cv", + "cy", + "da", + "de", + "dv", + "dz", + "ee", + "el", + "en", + "eo", + "es", + "et", + "eu", + "fa", + "ff", + "fi", + "fj", + "fo", + "fr", + "fy", + "ga", + "gd", + "gl", + "gn", + "gu", + "gv", + "ha", + "he", + "hi", + "ho", + "hr", + "ht", + "hu", + "hy", + "hz", + "ia", + "id", + "ie", + "ig", + "ii", + "ik", + "io", + "is", + "it", + "iu", + "ja", + "jv", + "ka", + "kg", + "ki", + "kj", + "kk", + "kl", + "km", + "kn", + "ko", + "kr", + "ks", + "ku", + "kv", + "kw", + "ky", + "la", + "lb", + "lg", + "li", + "ln", + "lo", + "lt", + "lu", + "lv", + "mg", + "mh", + "mi", + "mk", + "ml", + "mn", + "mr", + "ms", + "mt", + "my", + "na", + "nb", + "nd", + "ne", + "ng", + "nl", + "nn", + "no", + "nr", + "nv", + "ny", + "oc", + "oj", + "om", + "or", + "os", + "pa", + "pi", + "pl", + "ps", + "pt", + "qu", + "rm", + "rn", + "ro", + "ru", + "rw", + "sa", + "sc", + "sd", + "se", + "sg", + "si", + "sk", + "sl", + "sm", + "sn", + "so", + "sq", + "sr", + "ss", + "st", + "su", + "sv", + "sw", + "ta", + "te", + "tg", + "th", + "ti", + "tk", + "tl", + "tn", + "to", + "tr", + "ts", + "tt", + "tw", + "ty", + "ug", + "uk", + "ur", + "uz", + "ve", + "vi", + "vo", + "wa", + "wo", + "xh", + "yi", + "yue", + "yo", + "za", + "zh", + "zu" + ], + "description": "Single language for transcription as an ISO 639-1 code (e.g., `en`, `es`). For multi-language hints or to enable Soniox auto-detect, use `languages` instead — when `languages` is set (including to an empty array), this field is ignored when building the Soniox request. Defaults to `en` if neither this nor `languages` is set." + }, + "languages": { "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", + "description": "Language hints sent to Soniox as `language_hints`. Provide `[lang1, lang2, ...]` (ISO 639-1 codes) to bias recognition toward specific languages, or provide an explicit empty array `[]` to enable Soniox auto-detect across all 60+ supported languages. When set (including the empty array), this field takes precedence over the singular `language` field. When omitted, falls back to the singular `language` (which defaults to `en` if also unset). Best accuracy is achieved with a single language.", "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" - } + "type": "string", + "enum": [ + "aa", + "ab", + "ae", + "af", + "ak", + "am", + "an", + "ar", + "as", + "av", + "ay", + "az", + "ba", + "be", + "bg", + "bh", + "bi", + "bm", + "bn", + "bo", + "br", + "bs", + "ca", + "ce", + "ch", + "co", + "cr", + "cs", + "cu", + "cv", + "cy", + "da", + "de", + "dv", + "dz", + "ee", + "el", + "en", + "eo", + "es", + "et", + "eu", + "fa", + "ff", + "fi", + "fj", + "fo", + "fr", + "fy", + "ga", + "gd", + "gl", + "gn", + "gu", + "gv", + "ha", + "he", + "hi", + "ho", + "hr", + "ht", + "hu", + "hy", + "hz", + "ia", + "id", + "ie", + "ig", + "ii", + "ik", + "io", + "is", + "it", + "iu", + "ja", + "jv", + "ka", + "kg", + "ki", + "kj", + "kk", + "kl", + "km", + "kn", + "ko", + "kr", + "ks", + "ku", + "kv", + "kw", + "ky", + "la", + "lb", + "lg", + "li", + "ln", + "lo", + "lt", + "lu", + "lv", + "mg", + "mh", + "mi", + "mk", + "ml", + "mn", + "mr", + "ms", + "mt", + "my", + "na", + "nb", + "nd", + "ne", + "ng", + "nl", + "nn", + "no", + "nr", + "nv", + "ny", + "oc", + "oj", + "om", + "or", + "os", + "pa", + "pi", + "pl", + "ps", + "pt", + "qu", + "rm", + "rn", + "ro", + "ru", + "rw", + "sa", + "sc", + "sd", + "se", + "sg", + "si", + "sk", + "sl", + "sm", + "sn", + "so", + "sq", + "sr", + "ss", + "st", + "su", + "sv", + "sw", + "ta", + "te", + "tg", + "th", + "ti", + "tk", + "tl", + "tn", + "to", + "tr", + "ts", + "tt", + "tw", + "ty", + "ug", + "uk", + "ur", + "uz", + "ve", + "vi", + "vo", + "wa", + "wo", + "xh", + "yi", + "yue", + "yo", + "za", + "zh", + "zu" ] } }, - "type": { - "type": "string", - "enum": [ - "mcp" - ], - "description": "The type of tool. \"mcp\" for MCP tool." + "languageHintsStrict": { + "type": "boolean", + "description": "When `true`, Soniox strictly restricts transcription to the languages in `languages` (or the singular `language` if `languages` is unset). When `false`, Soniox biases toward those languages but still allows transcription in other languages. Has no effect when no language hints are sent (e.g., `languages: []` for auto-detect). Defaults to `true` (strict mode)." }, - "server": { - "description": "\n This is the server where a `tool-calls` webhook will be sent.\n\n Notes:\n - Webhook is sent to this server when a tool call is made.\n - Webhook contains the call, assistant, and phone number objects.\n - Webhook contains the variables set on the assistant.\n - Webhook is sent to the first available URL in this order: {{tool.server.url}}, {{assistant.server.url}}, {{phoneNumber.server.url}}, {{org.server.url}}.\n - Webhook expects a response with tool call result.", - "allOf": [ + "maxEndpointDelayMs": { + "type": "number", + "minimum": 500, + "maximum": 3000, + "description": "Maximum delay in milliseconds between when the speaker stops and when the endpoint is detected. Lower values mean faster turn-taking but more false endpoints. Range: 500-3000. Default: 500." + }, + "endpointSensitivity": { + "type": "number", + "description": "How likely Soniox is to emit an endpoint (end the caller turn). Higher values make endpoints more likely for faster turn-taking; negative values make them less likely, which helps when callers pause mid-sentence (e.g. reading numbers group by group). Range: -1.0 to 1.0. Default: 0.3 (the platform low-latency voice profile; Soniox's own default is 0.0). Supported by stt-rt-v5; omitted from the Soniox request on explicit stt-rt-v4. Soniox recommends tuning endpointLatencyAdjustmentLevel first, and advises against negative sensitivity while the level is above 0 (the settings work against each other).", + "minimum": -1, + "maximum": 1, + "example": 0.3 + }, + "endpointLatencyAdjustmentLevel": { + "type": "number", + "description": "How aggressively Soniox reduces endpoint latency. 0 is Soniox's default semantic endpointing; 3 is the most aggressive. Higher levels return endpoints sooner but may split speech into more segments and slightly reduce accuracy. Integer. Range: 0-3. Default: 2 (the platform low-latency voice profile; Soniox's own default is 0). Supported by stt-rt-v5; omitted from the Soniox request on explicit stt-rt-v4.", + "minimum": 0, + "maximum": 3, + "example": 2 + }, + "customVocabulary": { + "description": "Custom vocabulary terms to boost recognition accuracy. Useful for brand names, product names, and domain-specific terminology. Maps to Soniox context.terms.", + "type": "array", + "items": { + "type": "string" + } + }, + "contextGeneral": { + "description": "General context key-value pairs that guide the AI model during transcription. Helps adapt vocabulary to the correct domain, improving accuracy. Recommended: 10 or fewer pairs. Maps to Soniox context.general.", + "example": [ { - "$ref": "#/components/schemas/Server" + "key": "domain", + "value": "Healthcare" + }, + { + "key": "topic", + "value": "Diabetes management consultation" } - ] - }, - "metadata": { - "$ref": "#/components/schemas/McpToolMetadata" + ], + "type": "array", + "items": { + "$ref": "#/components/schemas/SonioxContextGeneralItem" + } }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "fallbackPlan": { + "description": "This is the plan for transcriber provider fallbacks in the event that the primary transcriber provider fails.", "allOf": [ { - "$ref": "#/components/schemas/ToolRejectionPlan" + "$ref": "#/components/schemas/FallbackTranscriberPlan" } ] } }, "required": [ - "type" + "provider" ] }, - "CreateGoHighLevelCalendarAvailabilityToolDTO": { + "SpeechmaticsCustomVocabularyItem": { "type": "object", "properties": { - "messages": { + "content": { + "type": "string", + "description": "The word or phrase to add to the custom vocabulary.", + "minLength": 1, + "example": "Speechmatics" + }, + "soundsLike": { + "description": "Alternative phonetic representations of how the word might sound. This helps recognition when the word might be pronounced differently.", + "example": [ + "speech mattix" + ], "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" - } - ] + "type": "string" } - }, - "type": { - "type": "string", - "enum": [ - "gohighlevel.calendar.availability.check" - ], - "description": "The type of tool. \"gohighlevel.calendar.availability.check\" for GoHighLevel Calendar Availability Check tool." - }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", - "allOf": [ - { - "$ref": "#/components/schemas/ToolRejectionPlan" - } - ] } }, "required": [ - "type" + "content" ] }, - "CreateGoHighLevelCalendarEventCreateToolDTO": { + "SpeechmaticsTranscriber": { "type": "object", "properties": { - "messages": { - "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" - } - ] - } + "provider": { + "type": "string", + "description": "This is the transcription provider that will be used.", + "enum": [ + "speechmatics" + ] }, - "type": { + "model": { "type": "string", + "description": "This is the model that will be used for the transcription.", "enum": [ - "gohighlevel.calendar.event.create" + "default" + ] + }, + "language": { + "type": "string", + "enum": [ + "auto", + "ar", + "ar_en", + "ba", + "eu", + "be", + "bn", + "bg", + "yue", + "ca", + "hr", + "cs", + "da", + "nl", + "en", + "eo", + "et", + "fi", + "fr", + "gl", + "de", + "el", + "he", + "hi", + "hu", + "id", + "ia", + "ga", + "it", + "ja", + "ko", + "lv", + "lt", + "ms", + "en_ms", + "mt", + "cmn", + "cmn_en", + "mr", + "mn", + "no", + "fa", + "pl", + "pt", + "ro", + "ru", + "sk", + "sl", + "es", + "en_es", + "sw", + "sv", + "tl", + "ta", + "en_ta", + "th", + "tr", + "uk", + "ur", + "ug", + "vi", + "cy" + ] + }, + "operatingPoint": { + "type": "string", + "description": "This is the operating point for the transcription. Choose between `standard` for faster turnaround with strong accuracy or `enhanced` for highest accuracy when precision is critical.\n\n@default 'enhanced'", + "example": "enhanced", + "enum": [ + "standard", + "enhanced" ], - "description": "The type of tool. \"gohighlevel.calendar.event.create\" for GoHighLevel Calendar Event Create tool." + "default": "enhanced" }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", - "allOf": [ + "region": { + "type": "string", + "description": "This is the region for the Speechmatics API. Choose between EU (Europe) and US (United States) regions for lower latency and data sovereignty compliance.\n\n@default 'eu'", + "example": "us", + "enum": [ + "eu", + "us" + ], + "default": "eu" + }, + "enableDiarization": { + "type": "boolean", + "description": "This enables speaker diarization, which identifies and separates speakers in the transcription. Essential for multi-speaker conversations and conference calls.\n\n@default false", + "example": true, + "default": false + }, + "maxDelay": { + "type": "number", + "description": "This sets the maximum delay in milliseconds for partial transcripts. Balances latency and accuracy.\n\n@default 3000", + "example": 1500, + "minimum": 500, + "maximum": 10000, + "default": 3000 + }, + "customVocabulary": { + "example": [ { - "$ref": "#/components/schemas/ToolRejectionPlan" + "content": "Speechmatics", + "soundsLike": [ + "speech mattix" + ] } - ] - } - }, - "required": [ - "type" - ] - }, - "CreateGoHighLevelContactCreateToolDTO": { - "type": "object", - "properties": { - "messages": { + ], "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" - } - ] + "$ref": "#/components/schemas/SpeechmaticsCustomVocabularyItem" } }, - "type": { + "numeralStyle": { "type": "string", + "description": "This controls how numbers, dates, currencies, and other entities are formatted in the transcription output.\n\n@default 'written'", + "example": "spoken", "enum": [ - "gohighlevel.contact.create" + "written", + "spoken" ], - "description": "The type of tool. \"gohighlevel.contact.create\" for GoHighLevel Contact Create tool." + "default": "written" }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "endOfTurnSensitivity": { + "type": "number", + "description": "This is the sensitivity level for end-of-turn detection, which determines when a speaker has finished talking. Higher values are more sensitive.\n\n@default 0.5", + "example": 0.8, + "minimum": 0, + "maximum": 1, + "default": 0.5 + }, + "removeDisfluencies": { + "type": "boolean", + "description": "This enables removal of disfluencies (um, uh) from the transcript to create cleaner, more professional output.\n\nThis is only supported for the English language transcriber.\n\n@default false", + "example": true, + "default": false + }, + "minimumSpeechDuration": { + "type": "number", + "description": "This is the minimum duration in seconds for speech segments. Shorter segments will be filtered out. Helps remove noise and improve accuracy.\n\n@default 0.0", + "example": 0.2, + "minimum": 0, + "maximum": 5, + "default": 0 + }, + "fallbackPlan": { + "description": "This is the plan for transcriber provider fallbacks in the event that the primary transcriber provider fails.", "allOf": [ { - "$ref": "#/components/schemas/ToolRejectionPlan" + "$ref": "#/components/schemas/FallbackTranscriberPlan" } ] } }, "required": [ - "type" + "provider", + "customVocabulary" ] }, - "CreateGoHighLevelContactGetToolDTO": { + "TalkscriberTranscriber": { "type": "object", "properties": { - "messages": { - "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" - } - ] - } + "provider": { + "type": "string", + "description": "This is the transcription provider that will be used.", + "enum": [ + "talkscriber" + ] }, - "type": { + "model": { "type": "string", + "description": "This is the model that will be used for the transcription.", "enum": [ - "gohighlevel.contact.get" - ], - "description": "The type of tool. \"gohighlevel.contact.get\" for GoHighLevel Contact Get tool." + "whisper" + ] }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "language": { + "type": "string", + "description": "This is the language that will be set for the transcription. The list of languages Whisper supports can be found here: https://github.com/openai/whisper/blob/main/whisper/tokenizer.py", + "enum": [ + "en", + "zh", + "de", + "es", + "ru", + "ko", + "fr", + "ja", + "pt", + "tr", + "pl", + "ca", + "nl", + "ar", + "sv", + "it", + "id", + "hi", + "fi", + "vi", + "he", + "uk", + "el", + "ms", + "cs", + "ro", + "da", + "hu", + "ta", + "no", + "th", + "ur", + "hr", + "bg", + "lt", + "la", + "mi", + "ml", + "cy", + "sk", + "te", + "fa", + "lv", + "bn", + "sr", + "az", + "sl", + "kn", + "et", + "mk", + "br", + "eu", + "is", + "hy", + "ne", + "mn", + "bs", + "kk", + "sq", + "sw", + "gl", + "mr", + "pa", + "si", + "km", + "sn", + "yo", + "so", + "af", + "oc", + "ka", + "be", + "tg", + "sd", + "gu", + "am", + "yi", + "lo", + "uz", + "fo", + "ht", + "ps", + "tk", + "nn", + "mt", + "sa", + "lb", + "my", + "bo", + "tl", + "mg", + "as", + "tt", + "haw", + "ln", + "ha", + "ba", + "jw", + "su", + "yue" + ] + }, + "fallbackPlan": { + "description": "This is the plan for transcriber provider fallbacks in the event that the primary transcriber provider fails.", "allOf": [ { - "$ref": "#/components/schemas/ToolRejectionPlan" + "$ref": "#/components/schemas/FallbackTranscriberPlan" } ] } }, "required": [ - "type" + "provider" ] }, - "AnyscaleModel": { + "GoogleTranscriber": { "type": "object", "properties": { - "messages": { - "description": "This is the starting state for the conversation.", - "type": "array", - "items": { - "$ref": "#/components/schemas/OpenAIMessage" - } + "provider": { + "type": "string", + "description": "This is the transcription provider that will be used.", + "enum": [ + "google" + ] }, - "tools": { - "type": "array", - "description": "These are the tools that the assistant can use during the call. To use existing tools, use `toolIds`.\n\nBoth `tools` and `toolIds` can be used together.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/CreateApiRequestToolDTO", - "title": "ApiRequestTool" - }, - { - "$ref": "#/components/schemas/CreateBashToolDTO", - "title": "BashTool" - }, - { - "$ref": "#/components/schemas/CreateComputerToolDTO", - "title": "ComputerTool" - }, - { - "$ref": "#/components/schemas/CreateDtmfToolDTO", - "title": "DtmfTool" - }, - { - "$ref": "#/components/schemas/CreateEndCallToolDTO", - "title": "EndCallTool" - }, - { - "$ref": "#/components/schemas/CreateFunctionToolDTO", - "title": "FunctionTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelCalendarAvailabilityToolDTO", - "title": "GoHighLevelCalendarAvailabilityTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelCalendarEventCreateToolDTO", - "title": "GoHighLevelCalendarEventCreateTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelContactCreateToolDTO", - "title": "GoHighLevelContactCreateTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelContactGetToolDTO", - "title": "GoHighLevelContactGetTool" - }, - { - "$ref": "#/components/schemas/CreateGoogleCalendarCheckAvailabilityToolDTO", - "title": "GoogleCalendarCheckAvailabilityTool" - }, - { - "$ref": "#/components/schemas/CreateGoogleCalendarCreateEventToolDTO", - "title": "GoogleCalendarCreateEventTool" - }, - { - "$ref": "#/components/schemas/CreateGoogleSheetsRowAppendToolDTO", - "title": "GoogleSheetsRowAppendTool" - }, - { - "$ref": "#/components/schemas/CreateHandoffToolDTO", - "title": "HandoffTool" - }, - { - "$ref": "#/components/schemas/CreateMcpToolDTO", - "title": "McpTool" - }, - { - "$ref": "#/components/schemas/CreateQueryToolDTO", - "title": "QueryTool" - }, - { - "$ref": "#/components/schemas/CreateSlackSendMessageToolDTO", - "title": "SlackSendMessageTool" - }, - { - "$ref": "#/components/schemas/CreateSmsToolDTO", - "title": "SmsTool" - }, - { - "$ref": "#/components/schemas/CreateTextEditorToolDTO", - "title": "TextEditorTool" - }, - { - "$ref": "#/components/schemas/CreateTransferCallToolDTO", - "title": "TransferCallTool" - } - ] - } + "model": { + "type": "string", + "description": "This is the model that will be used for the transcription.", + "enum": [ + "gemini-3.5-flash", + "gemini-3.1-flash-lite", + "gemini-3-flash-preview", + "gemini-2.5-pro", + "gemini-2.5-flash", + "gemini-2.5-flash-lite", + "gemini-2.0-flash-thinking-exp", + "gemini-2.0-pro-exp-02-05", + "gemini-2.0-flash", + "gemini-2.0-flash-lite", + "gemini-2.0-flash-exp", + "gemini-2.0-flash-realtime-exp", + "gemini-1.5-flash", + "gemini-1.5-flash-002", + "gemini-1.5-pro", + "gemini-1.5-pro-002", + "gemini-1.0-pro" + ] }, - "toolIds": { - "description": "These are the tools that the assistant can use during the call. To use transient tools, use `tools`.\n\nBoth `tools` and `toolIds` can be used together.", - "type": "array", - "items": { - "type": "string" - } + "language": { + "type": "string", + "description": "This is the language that will be set for the transcription.", + "enum": [ + "Multilingual", + "Arabic", + "Bengali", + "Bulgarian", + "Chinese", + "Croatian", + "Czech", + "Danish", + "Dutch", + "English", + "Estonian", + "Finnish", + "French", + "German", + "Greek", + "Hebrew", + "Hindi", + "Hungarian", + "Indonesian", + "Italian", + "Japanese", + "Korean", + "Latvian", + "Lithuanian", + "Norwegian", + "Polish", + "Portuguese", + "Romanian", + "Russian", + "Serbian", + "Slovak", + "Slovenian", + "Spanish", + "Swahili", + "Swedish", + "Thai", + "Turkish", + "Ukrainian", + "Vietnamese" + ] }, - "knowledgeBase": { - "description": "These are the options for the knowledge base.", - "oneOf": [ + "fallbackPlan": { + "description": "This is the plan for transcriber provider fallbacks in the event that the primary transcriber provider fails.", + "allOf": [ { - "$ref": "#/components/schemas/CreateCustomKnowledgeBaseDTO", - "title": "Custom" + "$ref": "#/components/schemas/FallbackTranscriberPlan" } ] - }, - "knowledgeBaseId": { - "type": "string", - "description": "This is the ID of the knowledge base the model will use." - }, + } + }, + "required": [ + "provider" + ] + }, + "OpenAITranscriber": { + "type": "object", + "properties": { "provider": { "type": "string", + "description": "This is the transcription provider that will be used.", "enum": [ - "anyscale" + "openai" ] }, "model": { "type": "string", - "description": "This is the name of the model. Ex. cognitivecomputations/dolphin-mixtral-8x7b" - }, - "temperature": { - "type": "number", - "description": "This is the temperature that will be used for calls. Default is 0 to leverage caching for lower latency.", - "minimum": 0, - "maximum": 2 - }, - "maxTokens": { - "type": "number", - "description": "This is the max number of tokens that the assistant will be allowed to generate in each turn of the conversation. Default is 250.", - "minimum": 50, - "maximum": 10000 + "description": "This is the model that will be used for the transcription.", + "enum": [ + "gpt-4o-transcribe", + "gpt-4o-mini-transcribe" + ] }, - "emotionRecognitionEnabled": { - "type": "boolean", - "description": "This determines whether we detect user's emotion while they speak and send it as an additional info to model.\n\nDefault `false` because the model is usually are good at understanding the user's emotion from text.\n\n@default false" + "language": { + "type": "string", + "description": "This is the language that will be set for the transcription.", + "enum": [ + "af", + "ar", + "hy", + "az", + "be", + "bs", + "bg", + "ca", + "zh", + "hr", + "cs", + "da", + "nl", + "en", + "et", + "fi", + "fr", + "gl", + "de", + "el", + "he", + "hi", + "hu", + "is", + "id", + "it", + "ja", + "kn", + "kk", + "ko", + "lv", + "lt", + "mk", + "ms", + "mr", + "mi", + "ne", + "no", + "fa", + "pl", + "pt", + "ro", + "ru", + "sr", + "sk", + "sl", + "es", + "sw", + "sv", + "tl", + "ta", + "th", + "tr", + "uk", + "ur", + "vi", + "cy" + ] }, - "numFastTurns": { - "type": "number", - "description": "This sets how many turns at the start of the conversation to use a smaller, faster model from the same provider before switching to the primary model. Example, gpt-3.5-turbo if provider is openai.\n\nDefault is 0.\n\n@default 0", - "minimum": 0 + "fallbackPlan": { + "description": "This is the plan for transcriber provider fallbacks in the event that the primary transcriber provider fails.", + "allOf": [ + { + "$ref": "#/components/schemas/FallbackTranscriberPlan" + } + ] } }, "required": [ @@ -12773,2365 +12758,3027 @@ "model" ] }, - "AnthropicThinkingConfig": { + "XaiTranscriber": { "type": "object", "properties": { - "type": { + "provider": { "type": "string", "enum": [ - "enabled" + "xai" ] }, - "budgetTokens": { - "type": "number", - "description": "The maximum number of tokens to allocate for thinking.\nMust be between 1024 and 100000 tokens.", - "minimum": 1024, - "maximum": 100000 + "model": { + "type": "string", + "description": "The xAI speech-to-text model to use. xAI currently exposes a single STT model — placeholder for future model selection.", + "enum": [ + "default" + ] + }, + "language": { + "type": "string", + "description": "Single language for transcription as an ISO 639-1 code (e.g., `en`, `es`). Defaults to `en` if not set. xAI auto-detects when omitted via the API but Vapi defaults to English for deterministic behavior.", + "enum": [ + "ar", + "cs", + "da", + "nl", + "en", + "fil", + "fr", + "de", + "hi", + "id", + "it", + "ja", + "ko", + "mk", + "ms", + "fa", + "pl", + "pt", + "ro", + "ru", + "es", + "sv", + "th", + "tr", + "vi" + ] + }, + "fallbackPlan": { + "description": "This is the plan for transcriber provider fallbacks in the event that the primary transcriber provider fails.", + "allOf": [ + { + "$ref": "#/components/schemas/FallbackTranscriberPlan" + } + ] } }, "required": [ - "type", - "budgetTokens" + "provider" ] }, - "AnthropicModel": { + "VapiTranscriber": { "type": "object", "properties": { - "messages": { - "description": "This is the starting state for the conversation.", - "type": "array", - "items": { - "$ref": "#/components/schemas/OpenAIMessage" - } + "provider": { + "type": "string", + "enum": [ + "vapi" + ] }, - "tools": { - "type": "array", - "description": "These are the tools that the assistant can use during the call. To use existing tools, use `toolIds`.\n\nBoth `tools` and `toolIds` can be used together.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/CreateApiRequestToolDTO", - "title": "ApiRequestTool" - }, - { - "$ref": "#/components/schemas/CreateBashToolDTO", - "title": "BashTool" - }, - { - "$ref": "#/components/schemas/CreateComputerToolDTO", - "title": "ComputerTool" - }, - { - "$ref": "#/components/schemas/CreateDtmfToolDTO", - "title": "DtmfTool" - }, - { - "$ref": "#/components/schemas/CreateEndCallToolDTO", - "title": "EndCallTool" - }, - { - "$ref": "#/components/schemas/CreateFunctionToolDTO", - "title": "FunctionTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelCalendarAvailabilityToolDTO", - "title": "GoHighLevelCalendarAvailabilityTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelCalendarEventCreateToolDTO", - "title": "GoHighLevelCalendarEventCreateTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelContactCreateToolDTO", - "title": "GoHighLevelContactCreateTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelContactGetToolDTO", - "title": "GoHighLevelContactGetTool" - }, - { - "$ref": "#/components/schemas/CreateGoogleCalendarCheckAvailabilityToolDTO", - "title": "GoogleCalendarCheckAvailabilityTool" - }, - { - "$ref": "#/components/schemas/CreateGoogleCalendarCreateEventToolDTO", - "title": "GoogleCalendarCreateEventTool" - }, - { - "$ref": "#/components/schemas/CreateGoogleSheetsRowAppendToolDTO", - "title": "GoogleSheetsRowAppendTool" - }, - { - "$ref": "#/components/schemas/CreateHandoffToolDTO", - "title": "HandoffTool" - }, - { - "$ref": "#/components/schemas/CreateMcpToolDTO", - "title": "McpTool" - }, - { - "$ref": "#/components/schemas/CreateQueryToolDTO", - "title": "QueryTool" - }, - { - "$ref": "#/components/schemas/CreateSlackSendMessageToolDTO", - "title": "SlackSendMessageTool" - }, - { - "$ref": "#/components/schemas/CreateSmsToolDTO", - "title": "SmsTool" - }, - { - "$ref": "#/components/schemas/CreateTextEditorToolDTO", - "title": "TextEditorTool" - }, - { - "$ref": "#/components/schemas/CreateTransferCallToolDTO", - "title": "TransferCallTool" - } + "version": { + "type": "string", + "description": "This is the version of the Vapi transcriber. Vapi manages the underlying\nmodel and routing. When omitted, the latest version is used.\n\nManaged version params are additive-only and `'latest'` is an auto-update\nchannel — see the param-evolution INVARIANT in `vapiManaged/types.ts`.", + "enum": [ + "latest", + "1" + ] + }, + "language": { + "type": "string", + "description": "This is the language for transcription as an ISO 639-1 code (e.g. `en`).\nSelecting a language locks transcription to it. For multiple languages,\nuse `languages` instead. When neither `language` nor `languages` is set,\nthe transcriber auto-detects the spoken language.", + "enum": [ + "aa", + "ab", + "ae", + "af", + "ak", + "am", + "an", + "ar", + "as", + "av", + "ay", + "az", + "ba", + "be", + "bg", + "bh", + "bi", + "bm", + "bn", + "bo", + "br", + "bs", + "ca", + "ce", + "ch", + "co", + "cr", + "cs", + "cu", + "cv", + "cy", + "da", + "de", + "dv", + "dz", + "ee", + "el", + "en", + "eo", + "es", + "et", + "eu", + "fa", + "ff", + "fi", + "fj", + "fo", + "fr", + "fy", + "ga", + "gd", + "gl", + "gn", + "gu", + "gv", + "ha", + "he", + "hi", + "ho", + "hr", + "ht", + "hu", + "hy", + "hz", + "ia", + "id", + "ie", + "ig", + "ii", + "ik", + "io", + "is", + "it", + "iu", + "ja", + "jv", + "ka", + "kg", + "ki", + "kj", + "kk", + "kl", + "km", + "kn", + "ko", + "kr", + "ks", + "ku", + "kv", + "kw", + "ky", + "la", + "lb", + "lg", + "li", + "ln", + "lo", + "lt", + "lu", + "lv", + "mg", + "mh", + "mi", + "mk", + "ml", + "mn", + "mr", + "ms", + "mt", + "my", + "na", + "nb", + "nd", + "ne", + "ng", + "nl", + "nn", + "no", + "nr", + "nv", + "ny", + "oc", + "oj", + "om", + "or", + "os", + "pa", + "pi", + "pl", + "ps", + "pt", + "qu", + "rm", + "rn", + "ro", + "ru", + "rw", + "sa", + "sc", + "sd", + "se", + "sg", + "si", + "sk", + "sl", + "sm", + "sn", + "so", + "sq", + "sr", + "ss", + "st", + "su", + "sv", + "sw", + "ta", + "te", + "tg", + "th", + "ti", + "tk", + "tl", + "tn", + "to", + "tr", + "ts", + "tt", + "tw", + "ty", + "ug", + "uk", + "ur", + "uz", + "ve", + "vi", + "vo", + "wa", + "wo", + "xh", + "yi", + "yue", + "yo", + "za", + "zh", + "zu" + ] + }, + "languages": { + "type": "array", + "description": "These are the languages for transcription as ISO 639-1 codes. Set one or\nmore codes to restrict and bias recognition to those languages. An empty\narray `[]` (or omitting both this and `language`) enables auto-detection\nof the spoken language.", + "enum": [ + "aa", + "ab", + "ae", + "af", + "ak", + "am", + "an", + "ar", + "as", + "av", + "ay", + "az", + "ba", + "be", + "bg", + "bh", + "bi", + "bm", + "bn", + "bo", + "br", + "bs", + "ca", + "ce", + "ch", + "co", + "cr", + "cs", + "cu", + "cv", + "cy", + "da", + "de", + "dv", + "dz", + "ee", + "el", + "en", + "eo", + "es", + "et", + "eu", + "fa", + "ff", + "fi", + "fj", + "fo", + "fr", + "fy", + "ga", + "gd", + "gl", + "gn", + "gu", + "gv", + "ha", + "he", + "hi", + "ho", + "hr", + "ht", + "hu", + "hy", + "hz", + "ia", + "id", + "ie", + "ig", + "ii", + "ik", + "io", + "is", + "it", + "iu", + "ja", + "jv", + "ka", + "kg", + "ki", + "kj", + "kk", + "kl", + "km", + "kn", + "ko", + "kr", + "ks", + "ku", + "kv", + "kw", + "ky", + "la", + "lb", + "lg", + "li", + "ln", + "lo", + "lt", + "lu", + "lv", + "mg", + "mh", + "mi", + "mk", + "ml", + "mn", + "mr", + "ms", + "mt", + "my", + "na", + "nb", + "nd", + "ne", + "ng", + "nl", + "nn", + "no", + "nr", + "nv", + "ny", + "oc", + "oj", + "om", + "or", + "os", + "pa", + "pi", + "pl", + "ps", + "pt", + "qu", + "rm", + "rn", + "ro", + "ru", + "rw", + "sa", + "sc", + "sd", + "se", + "sg", + "si", + "sk", + "sl", + "sm", + "sn", + "so", + "sq", + "sr", + "ss", + "st", + "su", + "sv", + "sw", + "ta", + "te", + "tg", + "th", + "ti", + "tk", + "tl", + "tn", + "to", + "tr", + "ts", + "tt", + "tw", + "ty", + "ug", + "uk", + "ur", + "uz", + "ve", + "vi", + "vo", + "wa", + "wo", + "xh", + "yi", + "yue", + "yo", + "za", + "zh", + "zu" + ], + "items": { + "type": "string", + "enum": [ + "aa", + "ab", + "ae", + "af", + "ak", + "am", + "an", + "ar", + "as", + "av", + "ay", + "az", + "ba", + "be", + "bg", + "bh", + "bi", + "bm", + "bn", + "bo", + "br", + "bs", + "ca", + "ce", + "ch", + "co", + "cr", + "cs", + "cu", + "cv", + "cy", + "da", + "de", + "dv", + "dz", + "ee", + "el", + "en", + "eo", + "es", + "et", + "eu", + "fa", + "ff", + "fi", + "fj", + "fo", + "fr", + "fy", + "ga", + "gd", + "gl", + "gn", + "gu", + "gv", + "ha", + "he", + "hi", + "ho", + "hr", + "ht", + "hu", + "hy", + "hz", + "ia", + "id", + "ie", + "ig", + "ii", + "ik", + "io", + "is", + "it", + "iu", + "ja", + "jv", + "ka", + "kg", + "ki", + "kj", + "kk", + "kl", + "km", + "kn", + "ko", + "kr", + "ks", + "ku", + "kv", + "kw", + "ky", + "la", + "lb", + "lg", + "li", + "ln", + "lo", + "lt", + "lu", + "lv", + "mg", + "mh", + "mi", + "mk", + "ml", + "mn", + "mr", + "ms", + "mt", + "my", + "na", + "nb", + "nd", + "ne", + "ng", + "nl", + "nn", + "no", + "nr", + "nv", + "ny", + "oc", + "oj", + "om", + "or", + "os", + "pa", + "pi", + "pl", + "ps", + "pt", + "qu", + "rm", + "rn", + "ro", + "ru", + "rw", + "sa", + "sc", + "sd", + "se", + "sg", + "si", + "sk", + "sl", + "sm", + "sn", + "so", + "sq", + "sr", + "ss", + "st", + "su", + "sv", + "sw", + "ta", + "te", + "tg", + "th", + "ti", + "tk", + "tl", + "tn", + "to", + "tr", + "ts", + "tt", + "tw", + "ty", + "ug", + "uk", + "ur", + "uz", + "ve", + "vi", + "vo", + "wa", + "wo", + "xh", + "yi", + "yue", + "yo", + "za", + "zh", + "zu" ] } }, - "toolIds": { - "description": "These are the tools that the assistant can use during the call. To use transient tools, use `tools`.\n\nBoth `tools` and `toolIds` can be used together.", + "keywords": { + "description": "These are custom keywords/vocabulary to boost recognition of use-case\nspecific words (company names, product names, jargon).", "type": "array", "items": { "type": "string" } }, - "knowledgeBase": { - "description": "These are the options for the knowledge base.", - "oneOf": [ - { - "$ref": "#/components/schemas/CreateCustomKnowledgeBaseDTO", - "title": "Custom" - } - ] - }, - "knowledgeBaseId": { - "type": "string", - "description": "This is the ID of the knowledge base the model will use." - }, - "model": { + "turnTaking": { "type": "string", - "description": "The specific Anthropic/Claude model that will be used.", + "description": "This is the turn-taking mode. `intelligent` uses the underlying model's\nnative end-of-turn detection; `manual` ignores it and waits a fixed\nend-of-turn delay. Defaults to `intelligent`.", "enum": [ - "claude-3-opus-20240229", - "claude-3-sonnet-20240229", - "claude-3-haiku-20240307", - "claude-3-5-sonnet-20240620", - "claude-3-5-sonnet-20241022", - "claude-3-5-haiku-20241022", - "claude-3-7-sonnet-20250219", - "claude-opus-4-20250514", - "claude-sonnet-4-20250514" + "intelligent", + "manual" ] - }, + } + }, + "required": [ + "provider" + ] + }, + "FallbackAssemblyAITranscriber": { + "type": "object", + "properties": { "provider": { "type": "string", - "description": "The provider identifier for Anthropic.", + "description": "This is the transcription provider that will be used.", "enum": [ - "anthropic" + "assembly-ai" ] }, - "thinking": { - "description": "Optional configuration for Anthropic's thinking feature.\nOnly applicable for claude-3-7-sonnet-20250219 model.\nIf provided, maxTokens must be greater than thinking.budgetTokens.", - "allOf": [ - { - "$ref": "#/components/schemas/AnthropicThinkingConfig" - } + "language": { + "type": "string", + "description": "This is the language that will be set for the transcription.", + "enum": [ + "multi", + "en" ] }, - "temperature": { + "confidenceThreshold": { "type": "number", - "description": "This is the temperature that will be used for calls. Default is 0 to leverage caching for lower latency.", + "description": "Transcripts below this confidence threshold will be discarded.\n\n@default 0.4", "minimum": 0, - "maximum": 2 - }, - "maxTokens": { - "type": "number", - "description": "This is the max number of tokens that the assistant will be allowed to generate in each turn of the conversation. Default is 250.", - "minimum": 50, - "maximum": 10000 + "maximum": 1, + "example": 0.4 }, - "emotionRecognitionEnabled": { + "formatTurns": { "type": "boolean", - "description": "This determines whether we detect user's emotion while they speak and send it as an additional info to model.\n\nDefault `false` because the model is usually are good at understanding the user's emotion from text.\n\n@default false" + "description": "This enables formatting of transcripts.\n\n@default true", + "example": true }, - "numFastTurns": { + "endOfTurnConfidenceThreshold": { "type": "number", - "description": "This sets how many turns at the start of the conversation to use a smaller, faster model from the same provider before switching to the primary model. Example, gpt-3.5-turbo if provider is openai.\n\nDefault is 0.\n\n@default 0", - "minimum": 0 - } - }, - "required": [ - "model", - "provider" - ] - }, - "CerebrasModel": { - "type": "object", - "properties": { - "messages": { - "description": "This is the starting state for the conversation.", + "description": "This is the end of turn confidence threshold. The minimum confidence that the end of turn is detected.\nNote: Only used if startSpeakingPlan.smartEndpointingPlan is not set.\n@min 0\n@max 1\n@default 0.7", + "minimum": 0, + "maximum": 1, + "example": 0.7 + }, + "minEndOfTurnSilenceWhenConfident": { + "type": "number", + "description": "This is the minimum end of turn silence when confident in milliseconds.\nNote: Only used if startSpeakingPlan.smartEndpointingPlan is not set.\n@default 160", + "minimum": 0, + "example": 160 + }, + "wordFinalizationMaxWaitTime": { + "type": "number", + "deprecated": true, + "minimum": 0, + "example": 160 + }, + "maxTurnSilence": { + "type": "number", + "description": "This is the maximum turn silence time in milliseconds.\nNote: Only used if startSpeakingPlan.smartEndpointingPlan is not set.\n@default 400", + "minimum": 0, + "example": 400 + }, + "vadAssistedEndpointingEnabled": { + "type": "boolean", + "description": "Use VAD to assist with endpointing decisions from the transcriber.\nWhen enabled, transcriber endpointing will be buffered if VAD detects the user is still speaking, preventing premature turn-taking.\nWhen disabled, transcriber endpointing will be used immediately regardless of VAD state, allowing for quicker but more aggressive turn-taking.\nNote: Only used if startSpeakingPlan.smartEndpointingPlan is not set.\n\n@default true", + "example": true + }, + "mode": { + "type": "string", + "description": "This is the transcription mode used by the `universal-3-5-pro` speech model. Only applies to the `universal-3-5-pro` speech model.\n\n@default 'balanced'", + "enum": [ + "max_accuracy", + "min_latency", + "balanced" + ] + }, + "prompt": { + "type": "string", + "description": "This is a prompt that provides additional context to the transcription model. Only applies to the `universal-3-5-pro` speech model.", + "maxLength": 1750 + }, + "agentContext": { + "type": "string", + "description": "This is context about the voice agent that guides the transcription model. Only applies to the `universal-3-5-pro` speech model.", + "maxLength": 1750 + }, + "languageCodes": { "type": "array", + "description": "These are language codes used to steer automatic language detection. Only applies to the `universal-3-5-pro` speech model.", + "enum": [ + "en", + "es", + "fr", + "de", + "it", + "pt", + "tr", + "nl", + "sv", + "no", + "da", + "fi", + "hi", + "vi", + "ar", + "he", + "ja", + "zh" + ], "items": { - "$ref": "#/components/schemas/OpenAIMessage" + "type": "string", + "enum": [ + "en", + "es", + "fr", + "de", + "it", + "pt", + "tr", + "nl", + "sv", + "no", + "da", + "fi", + "hi", + "vi", + "ar", + "he", + "ja", + "zh" + ] } }, - "tools": { + "speechModel": { + "type": "string", + "description": "This is the speech model used for the streaming session.\nKeyterms prompting is supported on universal-streaming-english and universal-3-5-pro.\nuniversal-3-5-pro is AssemblyAI's most accurate voice-agent model.\n@default 'universal-streaming-english'", + "enum": [ + "universal-streaming-english", + "universal-streaming-multilingual", + "universal-3-5-pro" + ] + }, + "realtimeUrl": { + "type": "string", + "description": "The WebSocket URL that the transcriber connects to." + }, + "wordBoost": { + "description": "Add up to 2500 characters of custom vocabulary.", "type": "array", - "description": "These are the tools that the assistant can use during the call. To use existing tools, use `toolIds`.\n\nBoth `tools` and `toolIds` can be used together.", "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/CreateApiRequestToolDTO", - "title": "ApiRequestTool" - }, - { - "$ref": "#/components/schemas/CreateBashToolDTO", - "title": "BashTool" - }, - { - "$ref": "#/components/schemas/CreateComputerToolDTO", - "title": "ComputerTool" - }, - { - "$ref": "#/components/schemas/CreateDtmfToolDTO", - "title": "DtmfTool" - }, - { - "$ref": "#/components/schemas/CreateEndCallToolDTO", - "title": "EndCallTool" - }, - { - "$ref": "#/components/schemas/CreateFunctionToolDTO", - "title": "FunctionTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelCalendarAvailabilityToolDTO", - "title": "GoHighLevelCalendarAvailabilityTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelCalendarEventCreateToolDTO", - "title": "GoHighLevelCalendarEventCreateTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelContactCreateToolDTO", - "title": "GoHighLevelContactCreateTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelContactGetToolDTO", - "title": "GoHighLevelContactGetTool" - }, - { - "$ref": "#/components/schemas/CreateGoogleCalendarCheckAvailabilityToolDTO", - "title": "GoogleCalendarCheckAvailabilityTool" - }, - { - "$ref": "#/components/schemas/CreateGoogleCalendarCreateEventToolDTO", - "title": "GoogleCalendarCreateEventTool" - }, - { - "$ref": "#/components/schemas/CreateGoogleSheetsRowAppendToolDTO", - "title": "GoogleSheetsRowAppendTool" - }, - { - "$ref": "#/components/schemas/CreateHandoffToolDTO", - "title": "HandoffTool" - }, - { - "$ref": "#/components/schemas/CreateMcpToolDTO", - "title": "McpTool" - }, - { - "$ref": "#/components/schemas/CreateQueryToolDTO", - "title": "QueryTool" - }, - { - "$ref": "#/components/schemas/CreateSlackSendMessageToolDTO", - "title": "SlackSendMessageTool" - }, - { - "$ref": "#/components/schemas/CreateSmsToolDTO", - "title": "SmsTool" - }, - { - "$ref": "#/components/schemas/CreateTextEditorToolDTO", - "title": "TextEditorTool" - }, - { - "$ref": "#/components/schemas/CreateTransferCallToolDTO", - "title": "TransferCallTool" - } - ] + "type": "string", + "maxLength": 2500 } }, - "toolIds": { - "description": "These are the tools that the assistant can use during the call. To use transient tools, use `tools`.\n\nBoth `tools` and `toolIds` can be used together.", + "keytermsPrompt": { + "description": "Keyterms prompting improves recognition accuracy for specific words and phrases.\nCan include up to 100 keyterms, each up to 50 characters.\nCosts an additional $0.04/hour on universal-streaming-english and is included at no extra cost on universal-3-5-pro.", "type": "array", "items": { - "type": "string" + "type": "string", + "maxLength": 50 } }, - "knowledgeBase": { - "description": "These are the options for the knowledge base.", - "oneOf": [ - { - "$ref": "#/components/schemas/CreateCustomKnowledgeBaseDTO", - "title": "Custom" - } - ] + "endUtteranceSilenceThreshold": { + "type": "number", + "description": "The duration of the end utterance silence threshold in milliseconds." }, - "knowledgeBaseId": { + "disablePartialTranscripts": { + "type": "boolean", + "description": "Disable partial transcripts.\nSet to `true` to not receive partial transcripts. Defaults to `false`." + } + }, + "required": [ + "provider" + ] + }, + "FallbackAzureSpeechTranscriber": { + "type": "object", + "properties": { + "provider": { "type": "string", - "description": "This is the ID of the knowledge base the model will use." + "description": "This is the transcription provider that will be used.", + "enum": [ + "azure" + ] }, - "model": { + "language": { "type": "string", - "description": "This is the name of the model. Ex. cognitivecomputations/dolphin-mixtral-8x7b", + "description": "This is the language that will be set for the transcription. The list of languages Azure supports can be found here: https://learn.microsoft.com/en-us/azure/ai-services/speech-service/language-support?tabs=stt", "enum": [ - "llama3.1-8b", - "llama-3.3-70b" + "af-ZA", + "am-ET", + "ar-AE", + "ar-BH", + "ar-DZ", + "ar-EG", + "ar-IL", + "ar-IQ", + "ar-JO", + "ar-KW", + "ar-LB", + "ar-LY", + "ar-MA", + "ar-OM", + "ar-PS", + "ar-QA", + "ar-SA", + "ar-SY", + "ar-TN", + "ar-YE", + "az-AZ", + "bg-BG", + "bn-IN", + "bs-BA", + "ca-ES", + "cs-CZ", + "cy-GB", + "da-DK", + "de-AT", + "de-CH", + "de-DE", + "el-GR", + "en-AU", + "en-CA", + "en-GB", + "en-GH", + "en-HK", + "en-IE", + "en-IN", + "en-KE", + "en-NG", + "en-NZ", + "en-PH", + "en-SG", + "en-TZ", + "en-US", + "en-ZA", + "es-AR", + "es-BO", + "es-CL", + "es-CO", + "es-CR", + "es-CU", + "es-DO", + "es-EC", + "es-ES", + "es-GQ", + "es-GT", + "es-HN", + "es-MX", + "es-NI", + "es-PA", + "es-PE", + "es-PR", + "es-PY", + "es-SV", + "es-US", + "es-UY", + "es-VE", + "et-EE", + "eu-ES", + "fa-IR", + "fi-FI", + "fil-PH", + "fr-BE", + "fr-CA", + "fr-CH", + "fr-FR", + "ga-IE", + "gl-ES", + "gu-IN", + "he-IL", + "hi-IN", + "hr-HR", + "hu-HU", + "hy-AM", + "id-ID", + "is-IS", + "it-CH", + "it-IT", + "ja-JP", + "jv-ID", + "ka-GE", + "kk-KZ", + "km-KH", + "kn-IN", + "ko-KR", + "lo-LA", + "lt-LT", + "lv-LV", + "mk-MK", + "ml-IN", + "mn-MN", + "mr-IN", + "ms-MY", + "mt-MT", + "my-MM", + "nb-NO", + "ne-NP", + "nl-BE", + "nl-NL", + "pa-IN", + "pl-PL", + "ps-AF", + "pt-BR", + "pt-PT", + "ro-RO", + "ru-RU", + "si-LK", + "sk-SK", + "sl-SI", + "so-SO", + "sq-AL", + "sr-RS", + "sv-SE", + "sw-KE", + "sw-TZ", + "ta-IN", + "te-IN", + "th-TH", + "tr-TR", + "uk-UA", + "ur-IN", + "uz-UZ", + "vi-VN", + "wuu-CN", + "yue-CN", + "zh-CN", + "zh-CN-shandong", + "zh-CN-sichuan", + "zh-HK", + "zh-TW", + "zu-ZA" ] }, - "provider": { + "segmentationStrategy": { "type": "string", + "description": "Controls how phrase boundaries are detected, enabling either simple time/silence heuristics or more advanced semantic segmentation.", "enum": [ - "cerebras" + "Default", + "Time", + "Semantic" ] }, - "temperature": { - "type": "number", - "description": "This is the temperature that will be used for calls. Default is 0 to leverage caching for lower latency.", - "minimum": 0, - "maximum": 2 - }, - "maxTokens": { + "segmentationSilenceTimeoutMs": { "type": "number", - "description": "This is the max number of tokens that the assistant will be allowed to generate in each turn of the conversation. Default is 250.", - "minimum": 50, - "maximum": 10000 - }, - "emotionRecognitionEnabled": { - "type": "boolean", - "description": "This determines whether we detect user's emotion while they speak and send it as an additional info to model.\n\nDefault `false` because the model is usually are good at understanding the user's emotion from text.\n\n@default false" + "description": "Duration of detected silence after which the service finalizes a phrase. Configure to adjust sensitivity to pauses in speech.", + "minimum": 100, + "maximum": 5000 }, - "numFastTurns": { + "segmentationMaximumTimeMs": { "type": "number", - "description": "This sets how many turns at the start of the conversation to use a smaller, faster model from the same provider before switching to the primary model. Example, gpt-3.5-turbo if provider is openai.\n\nDefault is 0.\n\n@default 0", - "minimum": 0 + "description": "Maximum duration a segment can reach before being cut off when using time-based segmentation.", + "minimum": 20000, + "maximum": 70000 } }, "required": [ - "model", "provider" ] }, - "CustomLLMModel": { + "FallbackCartesiaTranscriber": { "type": "object", "properties": { - "messages": { - "description": "This is the starting state for the conversation.", - "type": "array", - "items": { - "$ref": "#/components/schemas/OpenAIMessage" - } - }, - "tools": { - "type": "array", - "description": "These are the tools that the assistant can use during the call. To use existing tools, use `toolIds`.\n\nBoth `tools` and `toolIds` can be used together.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/CreateApiRequestToolDTO", - "title": "ApiRequestTool" - }, - { - "$ref": "#/components/schemas/CreateBashToolDTO", - "title": "BashTool" - }, - { - "$ref": "#/components/schemas/CreateComputerToolDTO", - "title": "ComputerTool" - }, - { - "$ref": "#/components/schemas/CreateDtmfToolDTO", - "title": "DtmfTool" - }, - { - "$ref": "#/components/schemas/CreateEndCallToolDTO", - "title": "EndCallTool" - }, - { - "$ref": "#/components/schemas/CreateFunctionToolDTO", - "title": "FunctionTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelCalendarAvailabilityToolDTO", - "title": "GoHighLevelCalendarAvailabilityTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelCalendarEventCreateToolDTO", - "title": "GoHighLevelCalendarEventCreateTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelContactCreateToolDTO", - "title": "GoHighLevelContactCreateTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelContactGetToolDTO", - "title": "GoHighLevelContactGetTool" - }, - { - "$ref": "#/components/schemas/CreateGoogleCalendarCheckAvailabilityToolDTO", - "title": "GoogleCalendarCheckAvailabilityTool" - }, - { - "$ref": "#/components/schemas/CreateGoogleCalendarCreateEventToolDTO", - "title": "GoogleCalendarCreateEventTool" - }, - { - "$ref": "#/components/schemas/CreateGoogleSheetsRowAppendToolDTO", - "title": "GoogleSheetsRowAppendTool" - }, - { - "$ref": "#/components/schemas/CreateHandoffToolDTO", - "title": "HandoffTool" - }, - { - "$ref": "#/components/schemas/CreateMcpToolDTO", - "title": "McpTool" - }, - { - "$ref": "#/components/schemas/CreateQueryToolDTO", - "title": "QueryTool" - }, - { - "$ref": "#/components/schemas/CreateSlackSendMessageToolDTO", - "title": "SlackSendMessageTool" - }, - { - "$ref": "#/components/schemas/CreateSmsToolDTO", - "title": "SmsTool" - }, - { - "$ref": "#/components/schemas/CreateTextEditorToolDTO", - "title": "TextEditorTool" - }, - { - "$ref": "#/components/schemas/CreateTransferCallToolDTO", - "title": "TransferCallTool" - } - ] - } - }, - "toolIds": { - "description": "These are the tools that the assistant can use during the call. To use transient tools, use `tools`.\n\nBoth `tools` and `toolIds` can be used together.", - "type": "array", - "items": { - "type": "string" - } - }, - "knowledgeBase": { - "description": "These are the options for the knowledge base.", - "oneOf": [ - { - "$ref": "#/components/schemas/CreateCustomKnowledgeBaseDTO", - "title": "Custom" - } - ] - }, - "knowledgeBaseId": { - "type": "string", - "description": "This is the ID of the knowledge base the model will use." - }, "provider": { "type": "string", - "description": "This is the provider that will be used for the model. Any service, including your own server, that is compatible with the OpenAI API can be used.", "enum": [ - "custom-llm" + "cartesia" ] }, - "metadataSendMode": { + "model": { "type": "string", - "description": "This determines whether metadata is sent in requests to the custom provider.\n\n- `off` will not send any metadata. payload will look like `{ messages }`\n- `variable` will send `assistant.metadata` as a variable on the payload. payload will look like `{ messages, metadata }`\n- `destructured` will send `assistant.metadata` fields directly on the payload. payload will look like `{ messages, ...metadata }`\n\nFurther, `variable` and `destructured` will send `call`, `phoneNumber`, and `customer` objects in the payload.\n\nDefault is `variable`.", "enum": [ - "off", - "variable", - "destructured" + "ink-whisper", + "ink-2" ] }, - "headers": { - "type": "object", - "description": "Custom headers to send with requests. These headers can override default OpenAI headers except for Authorization (which should be specified using a custom-llm credential).", - "additionalProperties": { - "type": "string" - }, - "example": { - "X-Custom-Header": "value" - } - }, - "url": { - "type": "string", - "description": "These is the URL we'll use for the OpenAI client's `baseURL`. Ex. https://openrouter.ai/api/v1" - }, - "timeoutSeconds": { - "type": "number", - "description": "This sets the timeout for the connection to the custom provider without needing to stream any tokens back. Default is 20 seconds.", - "minimum": 0, - "maximum": 300 - }, - "model": { + "language": { "type": "string", - "description": "This is the name of the model. Ex. cognitivecomputations/dolphin-mixtral-8x7b" - }, - "temperature": { - "type": "number", - "description": "This is the temperature that will be used for calls. Default is 0 to leverage caching for lower latency.", - "minimum": 0, - "maximum": 2 - }, - "maxTokens": { - "type": "number", - "description": "This is the max number of tokens that the assistant will be allowed to generate in each turn of the conversation. Default is 250.", - "minimum": 50, - "maximum": 10000 - }, - "emotionRecognitionEnabled": { - "type": "boolean", - "description": "This determines whether we detect user's emotion while they speak and send it as an additional info to model.\n\nDefault `false` because the model is usually are good at understanding the user's emotion from text.\n\n@default false" - }, - "numFastTurns": { - "type": "number", - "description": "This sets how many turns at the start of the conversation to use a smaller, faster model from the same provider before switching to the primary model. Example, gpt-3.5-turbo if provider is openai.\n\nDefault is 0.\n\n@default 0", - "minimum": 0 + "enum": [ + "aa", + "ab", + "ae", + "af", + "ak", + "am", + "an", + "ar", + "as", + "av", + "ay", + "az", + "ba", + "be", + "bg", + "bh", + "bi", + "bm", + "bn", + "bo", + "br", + "bs", + "ca", + "ce", + "ch", + "co", + "cr", + "cs", + "cu", + "cv", + "cy", + "da", + "de", + "dv", + "dz", + "ee", + "el", + "en", + "eo", + "es", + "et", + "eu", + "fa", + "ff", + "fi", + "fj", + "fo", + "fr", + "fy", + "ga", + "gd", + "gl", + "gn", + "gu", + "gv", + "ha", + "he", + "hi", + "ho", + "hr", + "ht", + "hu", + "hy", + "hz", + "ia", + "id", + "ie", + "ig", + "ii", + "ik", + "io", + "is", + "it", + "iu", + "ja", + "jv", + "ka", + "kg", + "ki", + "kj", + "kk", + "kl", + "km", + "kn", + "ko", + "kr", + "ks", + "ku", + "kv", + "kw", + "ky", + "la", + "lb", + "lg", + "li", + "ln", + "lo", + "lt", + "lu", + "lv", + "mg", + "mh", + "mi", + "mk", + "ml", + "mn", + "mr", + "ms", + "mt", + "my", + "na", + "nb", + "nd", + "ne", + "ng", + "nl", + "nn", + "no", + "nr", + "nv", + "ny", + "oc", + "oj", + "om", + "or", + "os", + "pa", + "pi", + "pl", + "ps", + "pt", + "qu", + "rm", + "rn", + "ro", + "ru", + "rw", + "sa", + "sc", + "sd", + "se", + "sg", + "si", + "sk", + "sl", + "sm", + "sn", + "so", + "sq", + "sr", + "ss", + "st", + "su", + "sv", + "sw", + "ta", + "te", + "tg", + "th", + "ti", + "tk", + "tl", + "tn", + "to", + "tr", + "ts", + "tt", + "tw", + "ty", + "ug", + "uk", + "ur", + "uz", + "ve", + "vi", + "vo", + "wa", + "wo", + "xh", + "yi", + "yue", + "yo", + "za", + "zh", + "zu" + ] } }, "required": [ - "provider", - "url", - "model" + "provider" ] }, - "DeepInfraModel": { + "FallbackCustomTranscriber": { "type": "object", "properties": { - "messages": { - "description": "This is the starting state for the conversation.", - "type": "array", - "items": { - "$ref": "#/components/schemas/OpenAIMessage" - } - }, - "tools": { - "type": "array", - "description": "These are the tools that the assistant can use during the call. To use existing tools, use `toolIds`.\n\nBoth `tools` and `toolIds` can be used together.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/CreateApiRequestToolDTO", - "title": "ApiRequestTool" - }, - { - "$ref": "#/components/schemas/CreateBashToolDTO", - "title": "BashTool" - }, - { - "$ref": "#/components/schemas/CreateComputerToolDTO", - "title": "ComputerTool" - }, - { - "$ref": "#/components/schemas/CreateDtmfToolDTO", - "title": "DtmfTool" - }, - { - "$ref": "#/components/schemas/CreateEndCallToolDTO", - "title": "EndCallTool" - }, - { - "$ref": "#/components/schemas/CreateFunctionToolDTO", - "title": "FunctionTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelCalendarAvailabilityToolDTO", - "title": "GoHighLevelCalendarAvailabilityTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelCalendarEventCreateToolDTO", - "title": "GoHighLevelCalendarEventCreateTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelContactCreateToolDTO", - "title": "GoHighLevelContactCreateTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelContactGetToolDTO", - "title": "GoHighLevelContactGetTool" - }, - { - "$ref": "#/components/schemas/CreateGoogleCalendarCheckAvailabilityToolDTO", - "title": "GoogleCalendarCheckAvailabilityTool" - }, - { - "$ref": "#/components/schemas/CreateGoogleCalendarCreateEventToolDTO", - "title": "GoogleCalendarCreateEventTool" - }, - { - "$ref": "#/components/schemas/CreateGoogleSheetsRowAppendToolDTO", - "title": "GoogleSheetsRowAppendTool" - }, - { - "$ref": "#/components/schemas/CreateHandoffToolDTO", - "title": "HandoffTool" - }, - { - "$ref": "#/components/schemas/CreateMcpToolDTO", - "title": "McpTool" - }, - { - "$ref": "#/components/schemas/CreateQueryToolDTO", - "title": "QueryTool" - }, - { - "$ref": "#/components/schemas/CreateSlackSendMessageToolDTO", - "title": "SlackSendMessageTool" - }, - { - "$ref": "#/components/schemas/CreateSmsToolDTO", - "title": "SmsTool" - }, - { - "$ref": "#/components/schemas/CreateTextEditorToolDTO", - "title": "TextEditorTool" - }, - { - "$ref": "#/components/schemas/CreateTransferCallToolDTO", - "title": "TransferCallTool" - } - ] - } - }, - "toolIds": { - "description": "These are the tools that the assistant can use during the call. To use transient tools, use `tools`.\n\nBoth `tools` and `toolIds` can be used together.", - "type": "array", - "items": { - "type": "string" - } - }, - "knowledgeBase": { - "description": "These are the options for the knowledge base.", - "oneOf": [ - { - "$ref": "#/components/schemas/CreateCustomKnowledgeBaseDTO", - "title": "Custom" - } - ] - }, - "knowledgeBaseId": { - "type": "string", - "description": "This is the ID of the knowledge base the model will use." - }, "provider": { "type": "string", + "description": "This is the transcription provider that will be used. Use `custom-transcriber` for providers that are not natively supported.", "enum": [ - "deepinfra" + "custom-transcriber" ] }, - "model": { - "type": "string", - "description": "This is the name of the model. Ex. cognitivecomputations/dolphin-mixtral-8x7b" - }, - "temperature": { - "type": "number", - "description": "This is the temperature that will be used for calls. Default is 0 to leverage caching for lower latency.", - "minimum": 0, - "maximum": 2 - }, - "maxTokens": { - "type": "number", - "description": "This is the max number of tokens that the assistant will be allowed to generate in each turn of the conversation. Default is 250.", - "minimum": 50, - "maximum": 10000 - }, - "emotionRecognitionEnabled": { - "type": "boolean", - "description": "This determines whether we detect user's emotion while they speak and send it as an additional info to model.\n\nDefault `false` because the model is usually are good at understanding the user's emotion from text.\n\n@default false" - }, - "numFastTurns": { - "type": "number", - "description": "This sets how many turns at the start of the conversation to use a smaller, faster model from the same provider before switching to the primary model. Example, gpt-3.5-turbo if provider is openai.\n\nDefault is 0.\n\n@default 0", - "minimum": 0 + "server": { + "description": "This is where the transcription request will be sent.\n\nUsage:\n1. Vapi will initiate a websocket connection with `server.url`.\n\n2. Vapi will send an initial text frame with the sample rate. Format:\n```\n {\n \"type\": \"start\",\n \"encoding\": \"linear16\", // 16-bit raw PCM format\n \"container\": \"raw\",\n \"sampleRate\": {{sampleRate}},\n \"channels\": 2 // customer is channel 0, assistant is channel 1\n }\n```\n\n3. Vapi will send the audio data in 16-bit raw PCM format as binary frames.\n\n4. You can read the messages something like this:\n```\nws.on('message', (data, isBinary) => {\n if (isBinary) {\n pcmBuffer = Buffer.concat([pcmBuffer, data]);\n console.log(`Received PCM data, buffer size: ${pcmBuffer.length}`);\n } else {\n console.log('Received message:', JSON.parse(data.toString()));\n }\n});\n```\n\n5. You will respond with transcriptions as you have them. Format:\n```\n {\n \"type\": \"transcriber-response\",\n \"transcription\": \"Hello, world!\",\n \"channel\": \"customer\" | \"assistant\"\n }\n```", + "allOf": [ + { + "$ref": "#/components/schemas/Server" + } + ] } }, "required": [ "provider", - "model" + "server" ] }, - "DeepSeekModel": { + "FallbackDeepgramTranscriber": { "type": "object", "properties": { - "messages": { - "description": "This is the starting state for the conversation.", - "type": "array", - "items": { - "$ref": "#/components/schemas/OpenAIMessage" - } - }, - "tools": { - "type": "array", - "description": "These are the tools that the assistant can use during the call. To use existing tools, use `toolIds`.\n\nBoth `tools` and `toolIds` can be used together.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/CreateApiRequestToolDTO", - "title": "ApiRequestTool" - }, - { - "$ref": "#/components/schemas/CreateBashToolDTO", - "title": "BashTool" - }, - { - "$ref": "#/components/schemas/CreateComputerToolDTO", - "title": "ComputerTool" - }, - { - "$ref": "#/components/schemas/CreateDtmfToolDTO", - "title": "DtmfTool" - }, - { - "$ref": "#/components/schemas/CreateEndCallToolDTO", - "title": "EndCallTool" - }, - { - "$ref": "#/components/schemas/CreateFunctionToolDTO", - "title": "FunctionTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelCalendarAvailabilityToolDTO", - "title": "GoHighLevelCalendarAvailabilityTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelCalendarEventCreateToolDTO", - "title": "GoHighLevelCalendarEventCreateTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelContactCreateToolDTO", - "title": "GoHighLevelContactCreateTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelContactGetToolDTO", - "title": "GoHighLevelContactGetTool" - }, - { - "$ref": "#/components/schemas/CreateGoogleCalendarCheckAvailabilityToolDTO", - "title": "GoogleCalendarCheckAvailabilityTool" - }, - { - "$ref": "#/components/schemas/CreateGoogleCalendarCreateEventToolDTO", - "title": "GoogleCalendarCreateEventTool" - }, - { - "$ref": "#/components/schemas/CreateGoogleSheetsRowAppendToolDTO", - "title": "GoogleSheetsRowAppendTool" - }, - { - "$ref": "#/components/schemas/CreateHandoffToolDTO", - "title": "HandoffTool" - }, - { - "$ref": "#/components/schemas/CreateMcpToolDTO", - "title": "McpTool" - }, - { - "$ref": "#/components/schemas/CreateQueryToolDTO", - "title": "QueryTool" - }, - { - "$ref": "#/components/schemas/CreateSlackSendMessageToolDTO", - "title": "SlackSendMessageTool" - }, - { - "$ref": "#/components/schemas/CreateSmsToolDTO", - "title": "SmsTool" - }, - { - "$ref": "#/components/schemas/CreateTextEditorToolDTO", - "title": "TextEditorTool" - }, - { - "$ref": "#/components/schemas/CreateTransferCallToolDTO", - "title": "TransferCallTool" - } - ] - } - }, - "toolIds": { - "description": "These are the tools that the assistant can use during the call. To use transient tools, use `tools`.\n\nBoth `tools` and `toolIds` can be used together.", - "type": "array", - "items": { - "type": "string" - } - }, - "knowledgeBase": { - "description": "These are the options for the knowledge base.", - "oneOf": [ - { - "$ref": "#/components/schemas/CreateCustomKnowledgeBaseDTO", - "title": "Custom" - } - ] - }, - "knowledgeBaseId": { - "type": "string", - "description": "This is the ID of the knowledge base the model will use." - }, - "model": { - "type": "string", - "description": "This is the name of the model. Ex. cognitivecomputations/dolphin-mixtral-8x7b", - "enum": [ - "deepseek-chat", - "deepseek-reasoner" - ] - }, "provider": { "type": "string", + "description": "This is the transcription provider that will be used.", "enum": [ - "deep-seek" + "deepgram" ] }, - "temperature": { - "type": "number", - "description": "This is the temperature that will be used for calls. Default is 0 to leverage caching for lower latency.", - "minimum": 0, - "maximum": 2 + "model": { + "description": "This is the Deepgram model that will be used. A list of models can be found here: https://developers.deepgram.com/docs/models-languages-overview", + "oneOf": [ + { + "type": "string", + "enum": [ + "nova-3", + "nova-3-general", + "nova-3-medical", + "nova-2", + "nova-2-general", + "nova-2-meeting", + "nova-2-phonecall", + "nova-2-finance", + "nova-2-conversationalai", + "nova-2-voicemail", + "nova-2-video", + "nova-2-medical", + "nova-2-drivethru", + "nova-2-automotive", + "nova", + "nova-general", + "nova-phonecall", + "nova-medical", + "enhanced", + "enhanced-general", + "enhanced-meeting", + "enhanced-phonecall", + "enhanced-finance", + "base", + "base-general", + "base-meeting", + "base-phonecall", + "base-finance", + "base-conversationalai", + "base-voicemail", + "base-video", + "whisper", + "flux-general-en", + "flux-general-multi" + ] + }, + { + "type": "string" + } + ] }, - "maxTokens": { - "type": "number", - "description": "This is the max number of tokens that the assistant will be allowed to generate in each turn of the conversation. Default is 250.", - "minimum": 50, - "maximum": 10000 + "language": { + "type": "string", + "description": "This is the language that will be set for the transcription. The list of languages Deepgram supports can be found here: https://developers.deepgram.com/docs/models-languages-overview", + "enum": [ + "ar", + "az", + "ba", + "be", + "bg", + "bn", + "br", + "bs", + "ca", + "cs", + "da", + "da-DK", + "de", + "de-CH", + "el", + "en", + "en-AU", + "en-CA", + "en-GB", + "en-IE", + "en-IN", + "en-NZ", + "en-US", + "es", + "es-419", + "es-LATAM", + "et", + "eu", + "fa", + "fi", + "fr", + "fr-CA", + "ha", + "haw", + "he", + "hi", + "hi-Latn", + "hr", + "hu", + "id", + "is", + "it", + "ja", + "jw", + "kn", + "ko", + "ko-KR", + "ln", + "lt", + "lv", + "mk", + "mr", + "ms", + "multi", + "nl", + "nl-BE", + "no", + "pl", + "pt", + "pt-BR", + "pt-PT", + "ro", + "ru", + "sk", + "sl", + "sn", + "so", + "sr", + "su", + "sv", + "sv-SE", + "ta", + "taq", + "te", + "th", + "th-TH", + "tl", + "tr", + "tt", + "uk", + "ur", + "vi", + "yo", + "zh", + "zh-CN", + "zh-HK", + "zh-Hans", + "zh-Hant", + "zh-TW" + ] }, - "emotionRecognitionEnabled": { + "smartFormat": { "type": "boolean", - "description": "This determines whether we detect user's emotion while they speak and send it as an additional info to model.\n\nDefault `false` because the model is usually are good at understanding the user's emotion from text.\n\n@default false" + "description": "This will be use smart format option provided by Deepgram. It's default disabled because it can sometimes format numbers as times but it's getting better.", + "example": false }, - "numFastTurns": { - "type": "number", - "description": "This sets how many turns at the start of the conversation to use a smaller, faster model from the same provider before switching to the primary model. Example, gpt-3.5-turbo if provider is openai.\n\nDefault is 0.\n\n@default 0", - "minimum": 0 - } - }, - "required": [ - "model", - "provider" - ] - }, - "GeminiMultimodalLivePrebuiltVoiceConfig": { - "type": "object", - "properties": { - "voiceName": { - "type": "string", + "mipOptOut": { + "type": "boolean", + "description": "If set to true, this will add mip_opt_out=true as a query parameter of all API requests. See https://developers.deepgram.com/docs/the-deepgram-model-improvement-partnership-program#want-to-opt-out\n\nThis will only be used if you are using your own Deepgram API key.\n\n@default false", + "example": false, + "default": false + }, + "numerals": { + "type": "boolean", + "description": "If set to true, this will cause deepgram to convert spoken numbers to literal numerals. For example, \"my phone number is nine-seven-two...\" would become \"my phone number is 972...\"\n\n@default false", + "example": false + }, + "profanityFilter": { + "type": "boolean", + "description": "If set to true, Deepgram will replace profanity in transcripts with surrounding asterisks, e.g. \"f***\".\n\n@default false", + "example": false + }, + "redaction": { + "type": "array", + "description": "Enables redaction of sensitive information from transcripts.\n\nOptions include:\n- \"pci\": Redacts credit card numbers, expiration dates, and CVV.\n- \"pii\": Redacts personally identifiable information (names, locations, identifying numbers, etc.).\n- \"phi\": Redacts protected health information (medical conditions, drugs, injuries, etc.).\n- \"numbers\": Redacts numerical and identifying entities (dates, account numbers, SSNs, etc.).\n\nMultiple values can be provided to redact different categories simultaneously.\nRedacted content is replaced with entity labels like [CREDIT_CARD_1], [SSN_1], etc.\n\nSee https://developers.deepgram.com/docs/redaction for details.", "enum": [ - "Puck", - "Charon", - "Kore", - "Fenrir", - "Aoede" - ] - } - }, - "required": [ - "voiceName" - ] - }, - "GeminiMultimodalLiveVoiceConfig": { - "type": "object", - "properties": { - "prebuiltVoiceConfig": { - "$ref": "#/components/schemas/GeminiMultimodalLivePrebuiltVoiceConfig" - } - }, - "required": [ - "prebuiltVoiceConfig" - ] - }, - "GeminiMultimodalLiveSpeechConfig": { - "type": "object", - "properties": { - "voiceConfig": { - "$ref": "#/components/schemas/GeminiMultimodalLiveVoiceConfig" - } - }, - "required": [ - "voiceConfig" - ] - }, - "GoogleRealtimeConfig": { - "type": "object", - "properties": { - "topP": { - "type": "number", - "description": "This is the nucleus sampling parameter that controls the cumulative probability of tokens considered during text generation.\nOnly applicable with the Gemini Flash 2.0 Multimodal Live API." + "pci", + "pii", + "phi", + "numbers" + ], + "example": [ + "pci", + "phi" + ], + "items": { + "type": "string", + "enum": [ + "pci", + "pii", + "phi", + "numbers" + ] + } }, - "topK": { + "confidenceThreshold": { "type": "number", - "description": "This is the top-k sampling parameter that limits the number of highest probability tokens considered during text generation.\nOnly applicable with the Gemini Flash 2.0 Multimodal Live API." + "description": "Transcripts below this confidence threshold will be discarded.\n\n@default 0.4", + "minimum": 0, + "maximum": 1, + "example": 0.4 }, - "presencePenalty": { + "eotThreshold": { "type": "number", - "description": "This is the presence penalty parameter that influences the model's likelihood to repeat information by penalizing tokens based on their presence in the text.\nOnly applicable with the Gemini Flash 2.0 Multimodal Live API." + "description": "End-of-turn confidence required to finish a turn. Only used with Flux models.\n\n@default 0.7", + "minimum": 0.5, + "maximum": 0.9, + "example": 0.7 }, - "frequencyPenalty": { + "eotTimeoutMs": { "type": "number", - "description": "This is the frequency penalty parameter that influences the model's likelihood to repeat tokens by penalizing them based on their frequency in the text.\nOnly applicable with the Gemini Flash 2.0 Multimodal Live API." + "description": "A turn will be finished when this much time has passed after speech, regardless of EOT confidence. Only used with Flux models.\n\n@default 5000", + "minimum": 500, + "maximum": 10000, + "example": 5000 }, - "speechConfig": { - "description": "This is the speech configuration object that defines the voice settings to be used for the model's speech output.\nOnly applicable with the Gemini Flash 2.0 Multimodal Live API.", - "allOf": [ - { - "$ref": "#/components/schemas/GeminiMultimodalLiveSpeechConfig" - } - ] - } - } - }, - "GoogleModel": { - "type": "object", - "properties": { - "messages": { - "description": "This is the starting state for the conversation.", + "languages": { + "description": "Language hints to bias Flux Multilingual (`flux-general-multi`) toward specific languages.\nProvide BCP-47 language codes (e.g. \"en\", \"es\", \"fr\"). Multiple hints can be given for\nmultilingual or code-switching scenarios. Omit for auto-detection. Only used with `flux-general-multi`.", + "example": [ + "en", + "es" + ], "type": "array", "items": { - "$ref": "#/components/schemas/OpenAIMessage" + "type": "string" } }, - "tools": { + "keywords": { + "description": "These keywords are passed to the transcription model to help it pick up use-case specific words. Anything that may not be a common word, like your company name, should be added here.", "type": "array", - "description": "These are the tools that the assistant can use during the call. To use existing tools, use `toolIds`.\n\nBoth `tools` and `toolIds` can be used together.", "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/CreateApiRequestToolDTO", - "title": "ApiRequestTool" - }, - { - "$ref": "#/components/schemas/CreateBashToolDTO", - "title": "BashTool" - }, - { - "$ref": "#/components/schemas/CreateComputerToolDTO", - "title": "ComputerTool" - }, - { - "$ref": "#/components/schemas/CreateDtmfToolDTO", - "title": "DtmfTool" - }, - { - "$ref": "#/components/schemas/CreateEndCallToolDTO", - "title": "EndCallTool" - }, - { - "$ref": "#/components/schemas/CreateFunctionToolDTO", - "title": "FunctionTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelCalendarAvailabilityToolDTO", - "title": "GoHighLevelCalendarAvailabilityTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelCalendarEventCreateToolDTO", - "title": "GoHighLevelCalendarEventCreateTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelContactCreateToolDTO", - "title": "GoHighLevelContactCreateTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelContactGetToolDTO", - "title": "GoHighLevelContactGetTool" - }, - { - "$ref": "#/components/schemas/CreateGoogleCalendarCheckAvailabilityToolDTO", - "title": "GoogleCalendarCheckAvailabilityTool" - }, - { - "$ref": "#/components/schemas/CreateGoogleCalendarCreateEventToolDTO", - "title": "GoogleCalendarCreateEventTool" - }, - { - "$ref": "#/components/schemas/CreateGoogleSheetsRowAppendToolDTO", - "title": "GoogleSheetsRowAppendTool" - }, - { - "$ref": "#/components/schemas/CreateHandoffToolDTO", - "title": "HandoffTool" - }, - { - "$ref": "#/components/schemas/CreateMcpToolDTO", - "title": "McpTool" - }, - { - "$ref": "#/components/schemas/CreateQueryToolDTO", - "title": "QueryTool" - }, - { - "$ref": "#/components/schemas/CreateSlackSendMessageToolDTO", - "title": "SlackSendMessageTool" - }, - { - "$ref": "#/components/schemas/CreateSmsToolDTO", - "title": "SmsTool" - }, - { - "$ref": "#/components/schemas/CreateTextEditorToolDTO", - "title": "TextEditorTool" - }, - { - "$ref": "#/components/schemas/CreateTransferCallToolDTO", - "title": "TransferCallTool" - } - ] + "type": "string", + "pattern": "/^\\p{L}[\\p{L}\\d]*(?::[+-]?\\d+)?$/u" } }, - "toolIds": { - "description": "These are the tools that the assistant can use during the call. To use transient tools, use `tools`.\n\nBoth `tools` and `toolIds` can be used together.", + "keyterm": { + "description": "Keyterm Prompting allows you improve Keyword Recall Rate (KRR) for important keyterms or phrases up to 90%.", "type": "array", "items": { "type": "string" } }, - "knowledgeBase": { - "description": "These are the options for the knowledge base.", - "oneOf": [ - { - "$ref": "#/components/schemas/CreateCustomKnowledgeBaseDTO", - "title": "Custom" - } - ] - }, - "knowledgeBaseId": { - "type": "string", - "description": "This is the ID of the knowledge base the model will use." - }, - "model": { - "type": "string", - "description": "This is the Google model that will be used.", - "enum": [ - "gemini-2.5-pro", - "gemini-2.5-flash", - "gemini-2.5-flash-lite", - "gemini-2.0-flash-thinking-exp", - "gemini-2.0-pro-exp-02-05", - "gemini-2.0-flash", - "gemini-2.0-flash-lite", - "gemini-2.0-flash-exp", - "gemini-2.0-flash-realtime-exp", - "gemini-1.5-flash", - "gemini-1.5-flash-002", - "gemini-1.5-pro", - "gemini-1.5-pro-002", - "gemini-1.0-pro" - ] - }, - "provider": { - "type": "string", - "enum": [ - "google" - ] - }, - "realtimeConfig": { - "description": "This is the session configuration for the Gemini Flash 2.0 Multimodal Live API.\nOnly applicable if the model `gemini-2.0-flash-realtime-exp` is selected.", - "allOf": [ - { - "$ref": "#/components/schemas/GoogleRealtimeConfig" - } - ] - }, - "temperature": { - "type": "number", - "description": "This is the temperature that will be used for calls. Default is 0 to leverage caching for lower latency.", - "minimum": 0, - "maximum": 2 - }, - "maxTokens": { - "type": "number", - "description": "This is the max number of tokens that the assistant will be allowed to generate in each turn of the conversation. Default is 250.", - "minimum": 50, - "maximum": 10000 - }, - "emotionRecognitionEnabled": { - "type": "boolean", - "description": "This determines whether we detect user's emotion while they speak and send it as an additional info to model.\n\nDefault `false` because the model is usually are good at understanding the user's emotion from text.\n\n@default false" - }, - "numFastTurns": { + "endpointing": { "type": "number", - "description": "This sets how many turns at the start of the conversation to use a smaller, faster model from the same provider before switching to the primary model. Example, gpt-3.5-turbo if provider is openai.\n\nDefault is 0.\n\n@default 0", - "minimum": 0 + "description": "This is the timeout after which Deepgram will send transcription on user silence. You can read in-depth documentation here: https://developers.deepgram.com/docs/endpointing.\n\nHere are the most important bits:\n- Defaults to 10. This is recommended for most use cases to optimize for latency.\n- 10 can cause some missing transcriptions since because of the shorter context. This mostly happens for one-word utterances. For those uses cases, it's recommended to try 300. It will add a bit of latency but the quality and reliability of the experience will be better.\n- If neither 10 nor 300 work, contact support@vapi.ai and we'll find another solution.\n\n@default 10", + "minimum": 10, + "maximum": 500 } }, "required": [ - "model", "provider" ] }, - "GroqModel": { + "FallbackElevenLabsTranscriber": { "type": "object", "properties": { - "messages": { - "description": "This is the starting state for the conversation.", - "type": "array", - "items": { - "$ref": "#/components/schemas/OpenAIMessage" - } + "provider": { + "type": "string", + "description": "This is the transcription provider that will be used.", + "enum": [ + "11labs" + ] }, - "tools": { - "type": "array", - "description": "These are the tools that the assistant can use during the call. To use existing tools, use `toolIds`.\n\nBoth `tools` and `toolIds` can be used together.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/CreateApiRequestToolDTO", - "title": "ApiRequestTool" - }, - { - "$ref": "#/components/schemas/CreateBashToolDTO", - "title": "BashTool" - }, - { - "$ref": "#/components/schemas/CreateComputerToolDTO", - "title": "ComputerTool" - }, - { - "$ref": "#/components/schemas/CreateDtmfToolDTO", - "title": "DtmfTool" - }, - { - "$ref": "#/components/schemas/CreateEndCallToolDTO", - "title": "EndCallTool" - }, - { - "$ref": "#/components/schemas/CreateFunctionToolDTO", - "title": "FunctionTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelCalendarAvailabilityToolDTO", - "title": "GoHighLevelCalendarAvailabilityTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelCalendarEventCreateToolDTO", - "title": "GoHighLevelCalendarEventCreateTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelContactCreateToolDTO", - "title": "GoHighLevelContactCreateTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelContactGetToolDTO", - "title": "GoHighLevelContactGetTool" - }, - { - "$ref": "#/components/schemas/CreateGoogleCalendarCheckAvailabilityToolDTO", - "title": "GoogleCalendarCheckAvailabilityTool" - }, - { - "$ref": "#/components/schemas/CreateGoogleCalendarCreateEventToolDTO", - "title": "GoogleCalendarCreateEventTool" - }, - { - "$ref": "#/components/schemas/CreateGoogleSheetsRowAppendToolDTO", - "title": "GoogleSheetsRowAppendTool" - }, - { - "$ref": "#/components/schemas/CreateHandoffToolDTO", - "title": "HandoffTool" - }, - { - "$ref": "#/components/schemas/CreateMcpToolDTO", - "title": "McpTool" - }, - { - "$ref": "#/components/schemas/CreateQueryToolDTO", - "title": "QueryTool" - }, - { - "$ref": "#/components/schemas/CreateSlackSendMessageToolDTO", - "title": "SlackSendMessageTool" - }, - { - "$ref": "#/components/schemas/CreateSmsToolDTO", - "title": "SmsTool" - }, - { - "$ref": "#/components/schemas/CreateTextEditorToolDTO", - "title": "TextEditorTool" - }, - { - "$ref": "#/components/schemas/CreateTransferCallToolDTO", - "title": "TransferCallTool" - } - ] - } - }, - "toolIds": { - "description": "These are the tools that the assistant can use during the call. To use transient tools, use `tools`.\n\nBoth `tools` and `toolIds` can be used together.", - "type": "array", - "items": { - "type": "string" - } - }, - "knowledgeBase": { - "description": "These are the options for the knowledge base.", + "model": { + "description": "This is the model that will be used for the transcription.", "oneOf": [ { - "$ref": "#/components/schemas/CreateCustomKnowledgeBaseDTO", - "title": "Custom" + "type": "string", + "enum": [ + "scribe_v1", + "scribe_v2", + "scribe_v2_realtime" + ] } ] }, - "knowledgeBaseId": { - "type": "string", - "description": "This is the ID of the knowledge base the model will use." - }, - "model": { + "language": { "type": "string", - "description": "This is the name of the model. Ex. cognitivecomputations/dolphin-mixtral-8x7b", + "description": "This is the language that will be used for the transcription.", "enum": [ - "openai/gpt-oss-20b", - "openai/gpt-oss-120b", - "deepseek-r1-distill-llama-70b", - "llama-3.3-70b-versatile", - "llama-3.1-405b-reasoning", - "llama-3.1-8b-instant", - "llama3-8b-8192", - "llama3-70b-8192", - "gemma2-9b-it", - "meta-llama/llama-4-maverick-17b-128e-instruct", - "meta-llama/llama-4-scout-17b-16e-instruct", - "mistral-saba-24b", - "compound-beta", - "compound-beta-mini" + "aa", + "ab", + "ae", + "af", + "ak", + "am", + "an", + "ar", + "as", + "av", + "ay", + "az", + "ba", + "be", + "bg", + "bh", + "bi", + "bm", + "bn", + "bo", + "br", + "bs", + "ca", + "ce", + "ch", + "co", + "cr", + "cs", + "cu", + "cv", + "cy", + "da", + "de", + "dv", + "dz", + "ee", + "el", + "en", + "eo", + "es", + "et", + "eu", + "fa", + "ff", + "fi", + "fj", + "fo", + "fr", + "fy", + "ga", + "gd", + "gl", + "gn", + "gu", + "gv", + "ha", + "he", + "hi", + "ho", + "hr", + "ht", + "hu", + "hy", + "hz", + "ia", + "id", + "ie", + "ig", + "ii", + "ik", + "io", + "is", + "it", + "iu", + "ja", + "jv", + "ka", + "kg", + "ki", + "kj", + "kk", + "kl", + "km", + "kn", + "ko", + "kr", + "ks", + "ku", + "kv", + "kw", + "ky", + "la", + "lb", + "lg", + "li", + "ln", + "lo", + "lt", + "lu", + "lv", + "mg", + "mh", + "mi", + "mk", + "ml", + "mn", + "mr", + "ms", + "mt", + "my", + "na", + "nb", + "nd", + "ne", + "ng", + "nl", + "nn", + "no", + "nr", + "nv", + "ny", + "oc", + "oj", + "om", + "or", + "os", + "pa", + "pi", + "pl", + "ps", + "pt", + "qu", + "rm", + "rn", + "ro", + "ru", + "rw", + "sa", + "sc", + "sd", + "se", + "sg", + "si", + "sk", + "sl", + "sm", + "sn", + "so", + "sq", + "sr", + "ss", + "st", + "su", + "sv", + "sw", + "ta", + "te", + "tg", + "th", + "ti", + "tk", + "tl", + "tn", + "to", + "tr", + "ts", + "tt", + "tw", + "ty", + "ug", + "uk", + "ur", + "uz", + "ve", + "vi", + "vo", + "wa", + "wo", + "xh", + "yi", + "yue", + "yo", + "za", + "zh", + "zu" ] }, - "provider": { - "type": "string", - "enum": [ - "groq" - ] + "silenceThresholdSeconds": { + "type": "number", + "description": "This is the number of seconds of silence before VAD commits (0.3-3.0).", + "minimum": 0.3, + "maximum": 3, + "example": 1.5 }, - "temperature": { + "confidenceThreshold": { "type": "number", - "description": "This is the temperature that will be used for calls. Default is 0 to leverage caching for lower latency.", - "minimum": 0, - "maximum": 2 + "description": "This is the VAD sensitivity (0.1-0.9, lower indicates more sensitive).", + "minimum": 0.1, + "maximum": 0.9, + "example": 0.4 }, - "maxTokens": { + "minSpeechDurationMs": { "type": "number", - "description": "This is the max number of tokens that the assistant will be allowed to generate in each turn of the conversation. Default is 250.", + "description": "This is the minimum speech duration for VAD (50-2000ms).", "minimum": 50, - "maximum": 10000 - }, - "emotionRecognitionEnabled": { - "type": "boolean", - "description": "This determines whether we detect user's emotion while they speak and send it as an additional info to model.\n\nDefault `false` because the model is usually are good at understanding the user's emotion from text.\n\n@default false" + "maximum": 2000, + "example": 100 }, - "numFastTurns": { + "minSilenceDurationMs": { "type": "number", - "description": "This sets how many turns at the start of the conversation to use a smaller, faster model from the same provider before switching to the primary model. Example, gpt-3.5-turbo if provider is openai.\n\nDefault is 0.\n\n@default 0", - "minimum": 0 + "description": "This is the minimum silence duration for VAD (50-2000ms).", + "minimum": 50, + "maximum": 2000, + "example": 100 } }, "required": [ - "model", "provider" ] }, - "InflectionAIModel": { + "GladiaVocabularyItemDTO": { "type": "object", "properties": { - "messages": { - "description": "This is the starting state for the conversation.", - "type": "array", - "items": { - "$ref": "#/components/schemas/OpenAIMessage" - } - }, - "tools": { - "type": "array", - "description": "These are the tools that the assistant can use during the call. To use existing tools, use `toolIds`.\n\nBoth `tools` and `toolIds` can be used together.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/CreateApiRequestToolDTO", - "title": "ApiRequestTool" - }, - { - "$ref": "#/components/schemas/CreateBashToolDTO", - "title": "BashTool" - }, - { - "$ref": "#/components/schemas/CreateComputerToolDTO", - "title": "ComputerTool" - }, - { - "$ref": "#/components/schemas/CreateDtmfToolDTO", - "title": "DtmfTool" - }, - { - "$ref": "#/components/schemas/CreateEndCallToolDTO", - "title": "EndCallTool" - }, - { - "$ref": "#/components/schemas/CreateFunctionToolDTO", - "title": "FunctionTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelCalendarAvailabilityToolDTO", - "title": "GoHighLevelCalendarAvailabilityTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelCalendarEventCreateToolDTO", - "title": "GoHighLevelCalendarEventCreateTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelContactCreateToolDTO", - "title": "GoHighLevelContactCreateTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelContactGetToolDTO", - "title": "GoHighLevelContactGetTool" - }, - { - "$ref": "#/components/schemas/CreateGoogleCalendarCheckAvailabilityToolDTO", - "title": "GoogleCalendarCheckAvailabilityTool" - }, - { - "$ref": "#/components/schemas/CreateGoogleCalendarCreateEventToolDTO", - "title": "GoogleCalendarCreateEventTool" - }, - { - "$ref": "#/components/schemas/CreateGoogleSheetsRowAppendToolDTO", - "title": "GoogleSheetsRowAppendTool" - }, - { - "$ref": "#/components/schemas/CreateHandoffToolDTO", - "title": "HandoffTool" - }, - { - "$ref": "#/components/schemas/CreateMcpToolDTO", - "title": "McpTool" - }, - { - "$ref": "#/components/schemas/CreateQueryToolDTO", - "title": "QueryTool" - }, - { - "$ref": "#/components/schemas/CreateSlackSendMessageToolDTO", - "title": "SlackSendMessageTool" - }, - { - "$ref": "#/components/schemas/CreateSmsToolDTO", - "title": "SmsTool" - }, - { - "$ref": "#/components/schemas/CreateTextEditorToolDTO", - "title": "TextEditorTool" - }, - { - "$ref": "#/components/schemas/CreateTransferCallToolDTO", - "title": "TransferCallTool" - } - ] - } + "value": { + "type": "string", + "description": "The vocabulary word or phrase" }, - "toolIds": { - "description": "These are the tools that the assistant can use during the call. To use transient tools, use `tools`.\n\nBoth `tools` and `toolIds` can be used together.", + "pronunciations": { + "description": "Alternative pronunciations for the vocabulary item", "type": "array", "items": { "type": "string" } }, - "knowledgeBase": { - "description": "These are the options for the knowledge base.", - "oneOf": [ - { - "$ref": "#/components/schemas/CreateCustomKnowledgeBaseDTO", - "title": "Custom" - } - ] - }, - "knowledgeBaseId": { - "type": "string", - "description": "This is the ID of the knowledge base the model will use." - }, - "model": { - "type": "string", - "description": "This is the name of the model. Ex. cognitivecomputations/dolphin-mixtral-8x7b", - "enum": [ - "inflection_3_pi" - ] - }, - "provider": { - "type": "string", - "enum": [ - "inflection-ai" - ] - }, - "temperature": { + "intensity": { "type": "number", - "description": "This is the temperature that will be used for calls. Default is 0 to leverage caching for lower latency.", "minimum": 0, - "maximum": 2 - }, - "maxTokens": { - "type": "number", - "description": "This is the max number of tokens that the assistant will be allowed to generate in each turn of the conversation. Default is 250.", - "minimum": 50, - "maximum": 10000 - }, - "emotionRecognitionEnabled": { - "type": "boolean", - "description": "This determines whether we detect user's emotion while they speak and send it as an additional info to model.\n\nDefault `false` because the model is usually are good at understanding the user's emotion from text.\n\n@default false" + "maximum": 1, + "description": "Intensity for this specific vocabulary item (0.0 to 1.0)" }, - "numFastTurns": { - "type": "number", - "description": "This sets how many turns at the start of the conversation to use a smaller, faster model from the same provider before switching to the primary model. Example, gpt-3.5-turbo if provider is openai.\n\nDefault is 0.\n\n@default 0", - "minimum": 0 + "language": { + "type": "string", + "description": "Language code for this vocabulary item (ISO 639-1)" } }, "required": [ - "model", - "provider" + "value" ] }, - "OpenAIModel": { + "FallbackGladiaTranscriber": { "type": "object", "properties": { - "messages": { - "description": "This is the starting state for the conversation.", - "type": "array", - "items": { - "$ref": "#/components/schemas/OpenAIMessage" - } + "provider": { + "type": "string", + "description": "This is the transcription provider that will be used.", + "enum": [ + "gladia" + ] }, - "tools": { - "type": "array", - "description": "These are the tools that the assistant can use during the call. To use existing tools, use `toolIds`.\n\nBoth `tools` and `toolIds` can be used together.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/CreateApiRequestToolDTO", - "title": "ApiRequestTool" - }, - { - "$ref": "#/components/schemas/CreateBashToolDTO", - "title": "BashTool" - }, - { - "$ref": "#/components/schemas/CreateComputerToolDTO", - "title": "ComputerTool" - }, - { - "$ref": "#/components/schemas/CreateDtmfToolDTO", - "title": "DtmfTool" - }, - { - "$ref": "#/components/schemas/CreateEndCallToolDTO", - "title": "EndCallTool" - }, - { - "$ref": "#/components/schemas/CreateFunctionToolDTO", - "title": "FunctionTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelCalendarAvailabilityToolDTO", - "title": "GoHighLevelCalendarAvailabilityTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelCalendarEventCreateToolDTO", - "title": "GoHighLevelCalendarEventCreateTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelContactCreateToolDTO", - "title": "GoHighLevelContactCreateTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelContactGetToolDTO", - "title": "GoHighLevelContactGetTool" - }, - { - "$ref": "#/components/schemas/CreateGoogleCalendarCheckAvailabilityToolDTO", - "title": "GoogleCalendarCheckAvailabilityTool" - }, - { - "$ref": "#/components/schemas/CreateGoogleCalendarCreateEventToolDTO", - "title": "GoogleCalendarCreateEventTool" - }, - { - "$ref": "#/components/schemas/CreateGoogleSheetsRowAppendToolDTO", - "title": "GoogleSheetsRowAppendTool" - }, - { - "$ref": "#/components/schemas/CreateHandoffToolDTO", - "title": "HandoffTool" - }, - { - "$ref": "#/components/schemas/CreateMcpToolDTO", - "title": "McpTool" - }, - { - "$ref": "#/components/schemas/CreateQueryToolDTO", - "title": "QueryTool" - }, - { - "$ref": "#/components/schemas/CreateSlackSendMessageToolDTO", - "title": "SlackSendMessageTool" - }, - { - "$ref": "#/components/schemas/CreateSmsToolDTO", - "title": "SmsTool" - }, - { - "$ref": "#/components/schemas/CreateTextEditorToolDTO", - "title": "TextEditorTool" - }, - { - "$ref": "#/components/schemas/CreateTransferCallToolDTO", - "title": "TransferCallTool" - } - ] - } - }, - "toolIds": { - "description": "These are the tools that the assistant can use during the call. To use transient tools, use `tools`.\n\nBoth `tools` and `toolIds` can be used together.", - "type": "array", - "items": { - "type": "string" - } - }, - "knowledgeBase": { - "description": "These are the options for the knowledge base.", + "model": { + "description": "This is the Gladia model that will be used. Default is 'fast'", "oneOf": [ { - "$ref": "#/components/schemas/CreateCustomKnowledgeBaseDTO", - "title": "Custom" + "type": "string", + "enum": [ + "fast", + "accurate", + "solaria-1" + ] } ] }, - "knowledgeBaseId": { - "type": "string", - "description": "This is the ID of the knowledge base the model will use." - }, - "provider": { - "type": "string", - "description": "This is the provider that will be used for the model.", - "enum": [ - "openai" + "languageBehaviour": { + "description": "Defines how the transcription model detects the audio language. Default value is 'automatic single language'.", + "oneOf": [ + { + "type": "string", + "enum": [ + "manual", + "automatic single language", + "automatic multiple languages" + ] + } ] }, - "model": { + "language": { "type": "string", - "description": "This is the OpenAI model that will be used.\n\nWhen using Vapi OpenAI or your own Azure Credentials, you have the option to specify the region for the selected model. This shouldn't be specified unless you have a specific reason to do so. Vapi will automatically find the fastest region that make sense.\nThis is helpful when you are required to comply with Data Residency rules. Learn more about Azure regions here https://azure.microsoft.com/en-us/explore/global-infrastructure/data-residency/.\n\n@default undefined", + "description": "Defines the language to use for the transcription. Required when languageBehaviour is 'manual'.", "enum": [ - "gpt-5", - "gpt-5-mini", - "gpt-5-nano", - "gpt-4.1-2025-04-14", - "gpt-4.1-mini-2025-04-14", - "gpt-4.1-nano-2025-04-14", - "gpt-4.1", - "gpt-4.1-mini", - "gpt-4.1-nano", - "chatgpt-4o-latest", - "o3", - "o3-mini", - "o4-mini", - "o1-mini", - "o1-mini-2024-09-12", - "gpt-4o-realtime-preview-2024-10-01", - "gpt-4o-realtime-preview-2024-12-17", - "gpt-4o-mini-realtime-preview-2024-12-17", - "gpt-4o-mini-2024-07-18", - "gpt-4o-mini", - "gpt-4o", - "gpt-4o-2024-05-13", - "gpt-4o-2024-08-06", - "gpt-4o-2024-11-20", - "gpt-4-turbo", - "gpt-4-turbo-2024-04-09", - "gpt-4-turbo-preview", - "gpt-4-0125-preview", - "gpt-4-1106-preview", - "gpt-4", - "gpt-4-0613", - "gpt-3.5-turbo", - "gpt-3.5-turbo-0125", - "gpt-3.5-turbo-1106", - "gpt-3.5-turbo-16k", - "gpt-3.5-turbo-0613", - "gpt-4.1-2025-04-14:westus", - "gpt-4.1-2025-04-14:eastus2", - "gpt-4.1-2025-04-14:eastus", - "gpt-4.1-2025-04-14:westus3", - "gpt-4.1-2025-04-14:northcentralus", - "gpt-4.1-2025-04-14:southcentralus", - "gpt-4.1-mini-2025-04-14:westus", - "gpt-4.1-mini-2025-04-14:eastus2", - "gpt-4.1-mini-2025-04-14:eastus", - "gpt-4.1-mini-2025-04-14:westus3", - "gpt-4.1-mini-2025-04-14:northcentralus", - "gpt-4.1-mini-2025-04-14:southcentralus", - "gpt-4.1-nano-2025-04-14:westus", - "gpt-4.1-nano-2025-04-14:eastus2", - "gpt-4.1-nano-2025-04-14:westus3", - "gpt-4.1-nano-2025-04-14:northcentralus", - "gpt-4.1-nano-2025-04-14:southcentralus", - "gpt-4o-2024-11-20:swedencentral", - "gpt-4o-2024-11-20:westus", - "gpt-4o-2024-11-20:eastus2", - "gpt-4o-2024-11-20:eastus", - "gpt-4o-2024-11-20:westus3", - "gpt-4o-2024-11-20:southcentralus", - "gpt-4o-2024-08-06:westus", - "gpt-4o-2024-08-06:westus3", - "gpt-4o-2024-08-06:eastus", - "gpt-4o-2024-08-06:eastus2", - "gpt-4o-2024-08-06:northcentralus", - "gpt-4o-2024-08-06:southcentralus", - "gpt-4o-mini-2024-07-18:westus", - "gpt-4o-mini-2024-07-18:westus3", - "gpt-4o-mini-2024-07-18:eastus", - "gpt-4o-mini-2024-07-18:eastus2", - "gpt-4o-mini-2024-07-18:northcentralus", - "gpt-4o-mini-2024-07-18:southcentralus", - "gpt-4o-2024-05-13:eastus2", - "gpt-4o-2024-05-13:eastus", - "gpt-4o-2024-05-13:northcentralus", - "gpt-4o-2024-05-13:southcentralus", - "gpt-4o-2024-05-13:westus3", - "gpt-4o-2024-05-13:westus", - "gpt-4-turbo-2024-04-09:eastus2", - "gpt-4-0125-preview:eastus", - "gpt-4-0125-preview:northcentralus", - "gpt-4-0125-preview:southcentralus", - "gpt-4-1106-preview:australia", - "gpt-4-1106-preview:canadaeast", - "gpt-4-1106-preview:france", - "gpt-4-1106-preview:india", - "gpt-4-1106-preview:norway", - "gpt-4-1106-preview:swedencentral", - "gpt-4-1106-preview:uk", - "gpt-4-1106-preview:westus", - "gpt-4-1106-preview:westus3", - "gpt-4-0613:canadaeast", - "gpt-3.5-turbo-0125:canadaeast", - "gpt-3.5-turbo-0125:northcentralus", - "gpt-3.5-turbo-0125:southcentralus", - "gpt-3.5-turbo-1106:canadaeast", - "gpt-3.5-turbo-1106:westus" + "af", + "sq", + "am", + "ar", + "hy", + "as", + "az", + "ba", + "eu", + "be", + "bn", + "bs", + "br", + "bg", + "ca", + "zh", + "hr", + "cs", + "da", + "nl", + "en", + "et", + "fo", + "fi", + "fr", + "gl", + "ka", + "de", + "el", + "gu", + "ht", + "ha", + "haw", + "he", + "hi", + "hu", + "is", + "id", + "it", + "ja", + "jv", + "kn", + "kk", + "km", + "ko", + "lo", + "la", + "lv", + "ln", + "lt", + "lb", + "mk", + "mg", + "ms", + "ml", + "mt", + "mi", + "mr", + "mn", + "my", + "ne", + "no", + "nn", + "oc", + "ps", + "fa", + "pl", + "pt", + "pa", + "ro", + "ru", + "sa", + "sr", + "sn", + "sd", + "si", + "sk", + "sl", + "so", + "es", + "su", + "sw", + "sv", + "tl", + "tg", + "ta", + "tt", + "te", + "th", + "bo", + "tr", + "tk", + "uk", + "ur", + "uz", + "vi", + "cy", + "yi", + "yo" ] }, - "fallbackModels": { + "languages": { "type": "array", - "description": "These are the fallback models that will be used if the primary model fails. This shouldn't be specified unless you have a specific reason to do so. Vapi will automatically find the fastest fallbacks that make sense.", - "enum": [ - "gpt-5", - "gpt-5-mini", - "gpt-5-nano", - "gpt-4.1-2025-04-14", - "gpt-4.1-mini-2025-04-14", - "gpt-4.1-nano-2025-04-14", - "gpt-4.1", - "gpt-4.1-mini", - "gpt-4.1-nano", - "chatgpt-4o-latest", - "o3", - "o3-mini", - "o4-mini", - "o1-mini", - "o1-mini-2024-09-12", - "gpt-4o-realtime-preview-2024-10-01", - "gpt-4o-realtime-preview-2024-12-17", - "gpt-4o-mini-realtime-preview-2024-12-17", - "gpt-4o-mini-2024-07-18", - "gpt-4o-mini", - "gpt-4o", - "gpt-4o-2024-05-13", - "gpt-4o-2024-08-06", - "gpt-4o-2024-11-20", - "gpt-4-turbo", - "gpt-4-turbo-2024-04-09", - "gpt-4-turbo-preview", - "gpt-4-0125-preview", - "gpt-4-1106-preview", - "gpt-4", - "gpt-4-0613", - "gpt-3.5-turbo", - "gpt-3.5-turbo-0125", - "gpt-3.5-turbo-1106", - "gpt-3.5-turbo-16k", - "gpt-3.5-turbo-0613", - "gpt-4.1-2025-04-14:westus", - "gpt-4.1-2025-04-14:eastus2", - "gpt-4.1-2025-04-14:eastus", - "gpt-4.1-2025-04-14:westus3", - "gpt-4.1-2025-04-14:northcentralus", - "gpt-4.1-2025-04-14:southcentralus", - "gpt-4.1-mini-2025-04-14:westus", - "gpt-4.1-mini-2025-04-14:eastus2", - "gpt-4.1-mini-2025-04-14:eastus", - "gpt-4.1-mini-2025-04-14:westus3", - "gpt-4.1-mini-2025-04-14:northcentralus", - "gpt-4.1-mini-2025-04-14:southcentralus", - "gpt-4.1-nano-2025-04-14:westus", - "gpt-4.1-nano-2025-04-14:eastus2", - "gpt-4.1-nano-2025-04-14:westus3", - "gpt-4.1-nano-2025-04-14:northcentralus", - "gpt-4.1-nano-2025-04-14:southcentralus", - "gpt-4o-2024-11-20:swedencentral", - "gpt-4o-2024-11-20:westus", - "gpt-4o-2024-11-20:eastus2", - "gpt-4o-2024-11-20:eastus", - "gpt-4o-2024-11-20:westus3", - "gpt-4o-2024-11-20:southcentralus", - "gpt-4o-2024-08-06:westus", - "gpt-4o-2024-08-06:westus3", - "gpt-4o-2024-08-06:eastus", - "gpt-4o-2024-08-06:eastus2", - "gpt-4o-2024-08-06:northcentralus", - "gpt-4o-2024-08-06:southcentralus", - "gpt-4o-mini-2024-07-18:westus", - "gpt-4o-mini-2024-07-18:westus3", - "gpt-4o-mini-2024-07-18:eastus", - "gpt-4o-mini-2024-07-18:eastus2", - "gpt-4o-mini-2024-07-18:northcentralus", - "gpt-4o-mini-2024-07-18:southcentralus", - "gpt-4o-2024-05-13:eastus2", - "gpt-4o-2024-05-13:eastus", - "gpt-4o-2024-05-13:northcentralus", - "gpt-4o-2024-05-13:southcentralus", - "gpt-4o-2024-05-13:westus3", - "gpt-4o-2024-05-13:westus", - "gpt-4-turbo-2024-04-09:eastus2", - "gpt-4-0125-preview:eastus", - "gpt-4-0125-preview:northcentralus", - "gpt-4-0125-preview:southcentralus", - "gpt-4-1106-preview:australia", - "gpt-4-1106-preview:canadaeast", - "gpt-4-1106-preview:france", - "gpt-4-1106-preview:india", - "gpt-4-1106-preview:norway", - "gpt-4-1106-preview:swedencentral", - "gpt-4-1106-preview:uk", - "gpt-4-1106-preview:westus", - "gpt-4-1106-preview:westus3", - "gpt-4-0613:canadaeast", - "gpt-3.5-turbo-0125:canadaeast", - "gpt-3.5-turbo-0125:northcentralus", - "gpt-3.5-turbo-0125:southcentralus", - "gpt-3.5-turbo-1106:canadaeast", - "gpt-3.5-turbo-1106:westus" - ], - "example": [ - "gpt-4-0125-preview", - "gpt-4-0613" - ], + "description": "Defines the languages to use for the transcription. Required when languageBehaviour is 'manual'.", "items": { "type": "string", "enum": [ - "gpt-5", - "gpt-5-mini", - "gpt-5-nano", - "gpt-4.1-2025-04-14", - "gpt-4.1-mini-2025-04-14", - "gpt-4.1-nano-2025-04-14", - "gpt-4.1", - "gpt-4.1-mini", - "gpt-4.1-nano", - "chatgpt-4o-latest", - "o3", - "o3-mini", - "o4-mini", - "o1-mini", - "o1-mini-2024-09-12", - "gpt-4o-realtime-preview-2024-10-01", - "gpt-4o-realtime-preview-2024-12-17", - "gpt-4o-mini-realtime-preview-2024-12-17", - "gpt-4o-mini-2024-07-18", - "gpt-4o-mini", - "gpt-4o", - "gpt-4o-2024-05-13", - "gpt-4o-2024-08-06", - "gpt-4o-2024-11-20", - "gpt-4-turbo", - "gpt-4-turbo-2024-04-09", - "gpt-4-turbo-preview", - "gpt-4-0125-preview", - "gpt-4-1106-preview", - "gpt-4", - "gpt-4-0613", - "gpt-3.5-turbo", - "gpt-3.5-turbo-0125", - "gpt-3.5-turbo-1106", - "gpt-3.5-turbo-16k", - "gpt-3.5-turbo-0613", - "gpt-4.1-2025-04-14:westus", - "gpt-4.1-2025-04-14:eastus2", - "gpt-4.1-2025-04-14:eastus", - "gpt-4.1-2025-04-14:westus3", - "gpt-4.1-2025-04-14:northcentralus", - "gpt-4.1-2025-04-14:southcentralus", - "gpt-4.1-mini-2025-04-14:westus", - "gpt-4.1-mini-2025-04-14:eastus2", - "gpt-4.1-mini-2025-04-14:eastus", - "gpt-4.1-mini-2025-04-14:westus3", - "gpt-4.1-mini-2025-04-14:northcentralus", - "gpt-4.1-mini-2025-04-14:southcentralus", - "gpt-4.1-nano-2025-04-14:westus", - "gpt-4.1-nano-2025-04-14:eastus2", - "gpt-4.1-nano-2025-04-14:westus3", - "gpt-4.1-nano-2025-04-14:northcentralus", - "gpt-4.1-nano-2025-04-14:southcentralus", - "gpt-4o-2024-11-20:swedencentral", - "gpt-4o-2024-11-20:westus", - "gpt-4o-2024-11-20:eastus2", - "gpt-4o-2024-11-20:eastus", - "gpt-4o-2024-11-20:westus3", - "gpt-4o-2024-11-20:southcentralus", - "gpt-4o-2024-08-06:westus", - "gpt-4o-2024-08-06:westus3", - "gpt-4o-2024-08-06:eastus", - "gpt-4o-2024-08-06:eastus2", - "gpt-4o-2024-08-06:northcentralus", - "gpt-4o-2024-08-06:southcentralus", - "gpt-4o-mini-2024-07-18:westus", - "gpt-4o-mini-2024-07-18:westus3", - "gpt-4o-mini-2024-07-18:eastus", - "gpt-4o-mini-2024-07-18:eastus2", - "gpt-4o-mini-2024-07-18:northcentralus", - "gpt-4o-mini-2024-07-18:southcentralus", - "gpt-4o-2024-05-13:eastus2", - "gpt-4o-2024-05-13:eastus", - "gpt-4o-2024-05-13:northcentralus", - "gpt-4o-2024-05-13:southcentralus", - "gpt-4o-2024-05-13:westus3", - "gpt-4o-2024-05-13:westus", - "gpt-4-turbo-2024-04-09:eastus2", - "gpt-4-0125-preview:eastus", - "gpt-4-0125-preview:northcentralus", - "gpt-4-0125-preview:southcentralus", - "gpt-4-1106-preview:australia", - "gpt-4-1106-preview:canadaeast", - "gpt-4-1106-preview:france", - "gpt-4-1106-preview:india", - "gpt-4-1106-preview:norway", - "gpt-4-1106-preview:swedencentral", - "gpt-4-1106-preview:uk", - "gpt-4-1106-preview:westus", - "gpt-4-1106-preview:westus3", - "gpt-4-0613:canadaeast", - "gpt-3.5-turbo-0125:canadaeast", - "gpt-3.5-turbo-0125:northcentralus", - "gpt-3.5-turbo-0125:southcentralus", - "gpt-3.5-turbo-1106:canadaeast", - "gpt-3.5-turbo-1106:westus" + "af", + "sq", + "am", + "ar", + "hy", + "as", + "az", + "ba", + "eu", + "be", + "bn", + "bs", + "br", + "bg", + "ca", + "zh", + "hr", + "cs", + "da", + "nl", + "en", + "et", + "fo", + "fi", + "fr", + "gl", + "ka", + "de", + "el", + "gu", + "ht", + "ha", + "haw", + "he", + "hi", + "hu", + "is", + "id", + "it", + "ja", + "jv", + "kn", + "kk", + "km", + "ko", + "lo", + "la", + "lv", + "ln", + "lt", + "lb", + "mk", + "mg", + "ms", + "ml", + "mt", + "mi", + "mr", + "mn", + "my", + "ne", + "no", + "nn", + "oc", + "ps", + "fa", + "pl", + "pt", + "pa", + "ro", + "ru", + "sa", + "sr", + "sn", + "sd", + "si", + "sk", + "sl", + "so", + "es", + "su", + "sw", + "sv", + "tl", + "tg", + "ta", + "tt", + "te", + "th", + "bo", + "tr", + "tk", + "uk", + "ur", + "uz", + "vi", + "cy", + "yi", + "yo" ] } }, - "toolStrictCompatibilityMode": { + "transcriptionHint": { "type": "string", - "description": "Azure OpenAI doesn't support `maxLength` right now https://learn.microsoft.com/en-us/azure/ai-services/openai/how-to/structured-outputs?tabs=python-secure%2Cdotnet-entra-id&pivots=programming-language-csharp#unsupported-type-specific-keywords. Need to strip.\n\n- `strip-parameters-with-unsupported-validation` will strip parameters with unsupported validation.\n- `strip-unsupported-validation` will keep the parameters but strip unsupported validation.\n\n@default `strip-unsupported-validation`", - "enum": [ - "strip-parameters-with-unsupported-validation", - "strip-unsupported-validation" - ] + "description": "Provides a custom vocabulary to the model to improve accuracy of transcribing context specific words, technical terms, names, etc. If empty, this argument is ignored.\n⚠️ Warning ⚠️: Please be aware that the transcription_hint field has a character limit of 600. If you provide a transcription_hint longer than 600 characters, it will be automatically truncated to meet this limit.", + "maxLength": 600, + "example": "custom vocabulary" }, - "temperature": { + "prosody": { + "type": "boolean", + "description": "If prosody is true, you will get a transcription that can contain prosodies i.e. (laugh) (giggles) (malefic laugh) (toss) (music)… Default value is false.", + "example": false + }, + "audioEnhancer": { + "type": "boolean", + "description": "If true, audio will be pre-processed to improve accuracy but latency will increase. Default value is false.", + "example": false + }, + "confidenceThreshold": { "type": "number", - "description": "This is the temperature that will be used for calls. Default is 0 to leverage caching for lower latency.", + "description": "Transcripts below this confidence threshold will be discarded.\n\n@default 0.4", "minimum": 0, - "maximum": 2 + "maximum": 1, + "example": 0.4 }, - "maxTokens": { + "endpointing": { "type": "number", - "description": "This is the max number of tokens that the assistant will be allowed to generate in each turn of the conversation. Default is 250.", - "minimum": 50, - "maximum": 10000 + "minimum": 0.01, + "maximum": 10, + "example": 0.05, + "description": "Endpointing time in seconds - time to wait before considering speech ended" }, - "emotionRecognitionEnabled": { + "speechThreshold": { + "type": "number", + "minimum": 0, + "maximum": 1, + "example": 0.6, + "description": "Speech threshold - sensitivity configuration for speech detection (0.0 to 1.0)" + }, + "customVocabularyEnabled": { "type": "boolean", - "description": "This determines whether we detect user's emotion while they speak and send it as an additional info to model.\n\nDefault `false` because the model is usually are good at understanding the user's emotion from text.\n\n@default false" + "example": false, + "description": "Enable custom vocabulary for improved accuracy" }, - "numFastTurns": { - "type": "number", - "description": "This sets how many turns at the start of the conversation to use a smaller, faster model from the same provider before switching to the primary model. Example, gpt-3.5-turbo if provider is openai.\n\nDefault is 0.\n\n@default 0", - "minimum": 0 + "customVocabularyConfig": { + "description": "Custom vocabulary configuration", + "allOf": [ + { + "$ref": "#/components/schemas/GladiaCustomVocabularyConfigDTO" + } + ] + }, + "region": { + "type": "string", + "enum": [ + "us-west", + "eu-west" + ], + "description": "Region for processing audio (us-west or eu-west)", + "example": "us-west" + }, + "receivePartialTranscripts": { + "type": "boolean", + "example": false, + "description": "Enable partial transcripts for low-latency streaming transcription" } }, "required": [ - "provider", - "model" + "provider" ] }, - "OpenRouterModel": { + "FallbackSonioxTranscriber": { "type": "object", "properties": { - "messages": { - "description": "This is the starting state for the conversation.", - "type": "array", - "items": { - "$ref": "#/components/schemas/OpenAIMessage" - } + "provider": { + "type": "string", + "enum": [ + "soniox" + ] }, - "tools": { + "model": { + "type": "string", + "enum": [ + "stt-rt-v4", + "stt-rt-v5" + ], + "description": "The Soniox model to use for transcription." + }, + "language": { + "type": "string", + "enum": [ + "aa", + "ab", + "ae", + "af", + "ak", + "am", + "an", + "ar", + "as", + "av", + "ay", + "az", + "ba", + "be", + "bg", + "bh", + "bi", + "bm", + "bn", + "bo", + "br", + "bs", + "ca", + "ce", + "ch", + "co", + "cr", + "cs", + "cu", + "cv", + "cy", + "da", + "de", + "dv", + "dz", + "ee", + "el", + "en", + "eo", + "es", + "et", + "eu", + "fa", + "ff", + "fi", + "fj", + "fo", + "fr", + "fy", + "ga", + "gd", + "gl", + "gn", + "gu", + "gv", + "ha", + "he", + "hi", + "ho", + "hr", + "ht", + "hu", + "hy", + "hz", + "ia", + "id", + "ie", + "ig", + "ii", + "ik", + "io", + "is", + "it", + "iu", + "ja", + "jv", + "ka", + "kg", + "ki", + "kj", + "kk", + "kl", + "km", + "kn", + "ko", + "kr", + "ks", + "ku", + "kv", + "kw", + "ky", + "la", + "lb", + "lg", + "li", + "ln", + "lo", + "lt", + "lu", + "lv", + "mg", + "mh", + "mi", + "mk", + "ml", + "mn", + "mr", + "ms", + "mt", + "my", + "na", + "nb", + "nd", + "ne", + "ng", + "nl", + "nn", + "no", + "nr", + "nv", + "ny", + "oc", + "oj", + "om", + "or", + "os", + "pa", + "pi", + "pl", + "ps", + "pt", + "qu", + "rm", + "rn", + "ro", + "ru", + "rw", + "sa", + "sc", + "sd", + "se", + "sg", + "si", + "sk", + "sl", + "sm", + "sn", + "so", + "sq", + "sr", + "ss", + "st", + "su", + "sv", + "sw", + "ta", + "te", + "tg", + "th", + "ti", + "tk", + "tl", + "tn", + "to", + "tr", + "ts", + "tt", + "tw", + "ty", + "ug", + "uk", + "ur", + "uz", + "ve", + "vi", + "vo", + "wa", + "wo", + "xh", + "yi", + "yue", + "yo", + "za", + "zh", + "zu" + ], + "description": "Single language for transcription as an ISO 639-1 code (e.g., `en`, `es`). For multi-language hints or to enable Soniox auto-detect, use `languages` instead — when `languages` is set (including to an empty array), this field is ignored when building the Soniox request. Defaults to `en` if neither this nor `languages` is set." + }, + "languages": { "type": "array", - "description": "These are the tools that the assistant can use during the call. To use existing tools, use `toolIds`.\n\nBoth `tools` and `toolIds` can be used together.", + "description": "Language hints sent to Soniox as `language_hints`. Provide `[lang1, lang2, ...]` (ISO 639-1 codes) to bias recognition toward specific languages, or provide an explicit empty array `[]` to enable Soniox auto-detect across all 60+ supported languages. When set (including the empty array), this field takes precedence over the singular `language` field. When omitted, falls back to the singular `language` (which defaults to `en` if also unset). Best accuracy is achieved with a single language.", "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/CreateApiRequestToolDTO", - "title": "ApiRequestTool" - }, - { - "$ref": "#/components/schemas/CreateBashToolDTO", - "title": "BashTool" - }, - { - "$ref": "#/components/schemas/CreateComputerToolDTO", - "title": "ComputerTool" - }, - { - "$ref": "#/components/schemas/CreateDtmfToolDTO", - "title": "DtmfTool" - }, - { - "$ref": "#/components/schemas/CreateEndCallToolDTO", - "title": "EndCallTool" - }, - { - "$ref": "#/components/schemas/CreateFunctionToolDTO", - "title": "FunctionTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelCalendarAvailabilityToolDTO", - "title": "GoHighLevelCalendarAvailabilityTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelCalendarEventCreateToolDTO", - "title": "GoHighLevelCalendarEventCreateTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelContactCreateToolDTO", - "title": "GoHighLevelContactCreateTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelContactGetToolDTO", - "title": "GoHighLevelContactGetTool" - }, - { - "$ref": "#/components/schemas/CreateGoogleCalendarCheckAvailabilityToolDTO", - "title": "GoogleCalendarCheckAvailabilityTool" - }, - { - "$ref": "#/components/schemas/CreateGoogleCalendarCreateEventToolDTO", - "title": "GoogleCalendarCreateEventTool" - }, - { - "$ref": "#/components/schemas/CreateGoogleSheetsRowAppendToolDTO", - "title": "GoogleSheetsRowAppendTool" - }, - { - "$ref": "#/components/schemas/CreateHandoffToolDTO", - "title": "HandoffTool" - }, - { - "$ref": "#/components/schemas/CreateMcpToolDTO", - "title": "McpTool" - }, - { - "$ref": "#/components/schemas/CreateQueryToolDTO", - "title": "QueryTool" - }, - { - "$ref": "#/components/schemas/CreateSlackSendMessageToolDTO", - "title": "SlackSendMessageTool" - }, - { - "$ref": "#/components/schemas/CreateSmsToolDTO", - "title": "SmsTool" - }, - { - "$ref": "#/components/schemas/CreateTextEditorToolDTO", - "title": "TextEditorTool" - }, - { - "$ref": "#/components/schemas/CreateTransferCallToolDTO", - "title": "TransferCallTool" - } + "type": "string", + "enum": [ + "aa", + "ab", + "ae", + "af", + "ak", + "am", + "an", + "ar", + "as", + "av", + "ay", + "az", + "ba", + "be", + "bg", + "bh", + "bi", + "bm", + "bn", + "bo", + "br", + "bs", + "ca", + "ce", + "ch", + "co", + "cr", + "cs", + "cu", + "cv", + "cy", + "da", + "de", + "dv", + "dz", + "ee", + "el", + "en", + "eo", + "es", + "et", + "eu", + "fa", + "ff", + "fi", + "fj", + "fo", + "fr", + "fy", + "ga", + "gd", + "gl", + "gn", + "gu", + "gv", + "ha", + "he", + "hi", + "ho", + "hr", + "ht", + "hu", + "hy", + "hz", + "ia", + "id", + "ie", + "ig", + "ii", + "ik", + "io", + "is", + "it", + "iu", + "ja", + "jv", + "ka", + "kg", + "ki", + "kj", + "kk", + "kl", + "km", + "kn", + "ko", + "kr", + "ks", + "ku", + "kv", + "kw", + "ky", + "la", + "lb", + "lg", + "li", + "ln", + "lo", + "lt", + "lu", + "lv", + "mg", + "mh", + "mi", + "mk", + "ml", + "mn", + "mr", + "ms", + "mt", + "my", + "na", + "nb", + "nd", + "ne", + "ng", + "nl", + "nn", + "no", + "nr", + "nv", + "ny", + "oc", + "oj", + "om", + "or", + "os", + "pa", + "pi", + "pl", + "ps", + "pt", + "qu", + "rm", + "rn", + "ro", + "ru", + "rw", + "sa", + "sc", + "sd", + "se", + "sg", + "si", + "sk", + "sl", + "sm", + "sn", + "so", + "sq", + "sr", + "ss", + "st", + "su", + "sv", + "sw", + "ta", + "te", + "tg", + "th", + "ti", + "tk", + "tl", + "tn", + "to", + "tr", + "ts", + "tt", + "tw", + "ty", + "ug", + "uk", + "ur", + "uz", + "ve", + "vi", + "vo", + "wa", + "wo", + "xh", + "yi", + "yue", + "yo", + "za", + "zh", + "zu" ] } }, - "toolIds": { - "description": "These are the tools that the assistant can use during the call. To use transient tools, use `tools`.\n\nBoth `tools` and `toolIds` can be used together.", + "languageHintsStrict": { + "type": "boolean", + "description": "When `true`, Soniox strictly restricts transcription to the languages in `languages` (or the singular `language` if `languages` is unset). When `false`, Soniox biases toward those languages but still allows transcription in other languages. Has no effect when no language hints are sent (e.g., `languages: []` for auto-detect). Defaults to `true` (strict mode)." + }, + "maxEndpointDelayMs": { + "type": "number", + "minimum": 500, + "maximum": 3000, + "description": "Maximum delay in milliseconds between when the speaker stops and when the endpoint is detected. Lower values mean faster turn-taking but more false endpoints. Range: 500-3000. Default: 500." + }, + "endpointSensitivity": { + "type": "number", + "description": "How likely Soniox is to emit an endpoint (end the caller turn). Higher values make endpoints more likely for faster turn-taking; negative values make them less likely, which helps when callers pause mid-sentence (e.g. reading numbers group by group). Range: -1.0 to 1.0. Default: 0.3 (the platform low-latency voice profile; Soniox's own default is 0.0). Supported by stt-rt-v5; omitted from the Soniox request on explicit stt-rt-v4. Soniox recommends tuning endpointLatencyAdjustmentLevel first, and advises against negative sensitivity while the level is above 0 (the settings work against each other).", + "minimum": -1, + "maximum": 1, + "example": 0.3 + }, + "endpointLatencyAdjustmentLevel": { + "type": "number", + "description": "How aggressively Soniox reduces endpoint latency. 0 is Soniox's default semantic endpointing; 3 is the most aggressive. Higher levels return endpoints sooner but may split speech into more segments and slightly reduce accuracy. Integer. Range: 0-3. Default: 2 (the platform low-latency voice profile; Soniox's own default is 0). Supported by stt-rt-v5; omitted from the Soniox request on explicit stt-rt-v4.", + "minimum": 0, + "maximum": 3, + "example": 2 + }, + "customVocabulary": { + "description": "Custom vocabulary terms to boost recognition accuracy. Useful for brand names, product names, and domain-specific terminology. Maps to Soniox context.terms.", "type": "array", "items": { "type": "string" } }, - "knowledgeBase": { - "description": "These are the options for the knowledge base.", - "oneOf": [ + "contextGeneral": { + "description": "General context key-value pairs that guide the AI model during transcription. Helps adapt vocabulary to the correct domain, improving accuracy. Recommended: 10 or fewer pairs. Maps to Soniox context.general.", + "example": [ { - "$ref": "#/components/schemas/CreateCustomKnowledgeBaseDTO", - "title": "Custom" + "key": "domain", + "value": "Healthcare" + }, + { + "key": "topic", + "value": "Diabetes management consultation" } + ], + "type": "array", + "items": { + "$ref": "#/components/schemas/SonioxContextGeneralItem" + } + } + }, + "required": [ + "provider" + ] + }, + "FallbackSpeechmaticsTranscriber": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "description": "This is the transcription provider that will be used.", + "enum": [ + "speechmatics" ] }, - "knowledgeBaseId": { + "model": { "type": "string", - "description": "This is the ID of the knowledge base the model will use." + "description": "This is the model that will be used for the transcription.", + "enum": [ + "default" + ] }, - "provider": { + "language": { "type": "string", "enum": [ - "openrouter" + "auto", + "ar", + "ar_en", + "ba", + "eu", + "be", + "bn", + "bg", + "yue", + "ca", + "hr", + "cs", + "da", + "nl", + "en", + "eo", + "et", + "fi", + "fr", + "gl", + "de", + "el", + "he", + "hi", + "hu", + "id", + "ia", + "ga", + "it", + "ja", + "ko", + "lv", + "lt", + "ms", + "en_ms", + "mt", + "cmn", + "cmn_en", + "mr", + "mn", + "no", + "fa", + "pl", + "pt", + "ro", + "ru", + "sk", + "sl", + "es", + "en_es", + "sw", + "sv", + "tl", + "ta", + "en_ta", + "th", + "tr", + "uk", + "ur", + "ug", + "vi", + "cy" ] }, - "model": { + "operatingPoint": { "type": "string", - "description": "This is the name of the model. Ex. cognitivecomputations/dolphin-mixtral-8x7b" + "description": "This is the operating point for the transcription. Choose between `standard` for faster turnaround with strong accuracy or `enhanced` for highest accuracy when precision is critical.\n\n@default 'enhanced'", + "example": "enhanced", + "enum": [ + "standard", + "enhanced" + ], + "default": "enhanced" }, - "temperature": { + "region": { + "type": "string", + "description": "This is the region for the Speechmatics API. Choose between EU (Europe) and US (United States) regions for lower latency and data sovereignty compliance.\n\n@default 'eu'", + "example": "us", + "enum": [ + "eu", + "us" + ], + "default": "eu" + }, + "enableDiarization": { + "type": "boolean", + "description": "This enables speaker diarization, which identifies and separates speakers in the transcription. Essential for multi-speaker conversations and conference calls.\n\n@default false", + "example": true, + "default": false + }, + "maxDelay": { "type": "number", - "description": "This is the temperature that will be used for calls. Default is 0 to leverage caching for lower latency.", - "minimum": 0, - "maximum": 2 + "description": "This sets the maximum delay in milliseconds for partial transcripts. Balances latency and accuracy.\n\n@default 3000", + "example": 1500, + "minimum": 500, + "maximum": 10000, + "default": 3000 }, - "maxTokens": { + "customVocabulary": { + "example": [ + { + "content": "Speechmatics", + "soundsLike": [ + "speech mattix" + ] + } + ], + "type": "array", + "items": { + "$ref": "#/components/schemas/SpeechmaticsCustomVocabularyItem" + } + }, + "numeralStyle": { + "type": "string", + "description": "This controls how numbers, dates, currencies, and other entities are formatted in the transcription output.\n\n@default 'written'", + "example": "spoken", + "enum": [ + "written", + "spoken" + ], + "default": "written" + }, + "endOfTurnSensitivity": { "type": "number", - "description": "This is the max number of tokens that the assistant will be allowed to generate in each turn of the conversation. Default is 250.", - "minimum": 50, - "maximum": 10000 + "description": "This is the sensitivity level for end-of-turn detection, which determines when a speaker has finished talking. Higher values are more sensitive.\n\n@default 0.5", + "example": 0.8, + "minimum": 0, + "maximum": 1, + "default": 0.5 }, - "emotionRecognitionEnabled": { + "removeDisfluencies": { "type": "boolean", - "description": "This determines whether we detect user's emotion while they speak and send it as an additional info to model.\n\nDefault `false` because the model is usually are good at understanding the user's emotion from text.\n\n@default false" + "description": "This enables removal of disfluencies (um, uh) from the transcript to create cleaner, more professional output.\n\nThis is only supported for the English language transcriber.\n\n@default false", + "example": true, + "default": false }, - "numFastTurns": { + "minimumSpeechDuration": { "type": "number", - "description": "This sets how many turns at the start of the conversation to use a smaller, faster model from the same provider before switching to the primary model. Example, gpt-3.5-turbo if provider is openai.\n\nDefault is 0.\n\n@default 0", - "minimum": 0 + "description": "This is the minimum duration in seconds for speech segments. Shorter segments will be filtered out. Helps remove noise and improve accuracy.\n\n@default 0.0", + "example": 0.2, + "minimum": 0, + "maximum": 5, + "default": 0 } }, "required": [ "provider", - "model" + "customVocabulary" ] }, - "PerplexityAIModel": { + "FallbackTalkscriberTranscriber": { "type": "object", "properties": { - "messages": { - "description": "This is the starting state for the conversation.", - "type": "array", - "items": { - "$ref": "#/components/schemas/OpenAIMessage" - } + "provider": { + "type": "string", + "description": "This is the transcription provider that will be used.", + "enum": [ + "talkscriber" + ] }, - "tools": { - "type": "array", - "description": "These are the tools that the assistant can use during the call. To use existing tools, use `toolIds`.\n\nBoth `tools` and `toolIds` can be used together.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/CreateApiRequestToolDTO", - "title": "ApiRequestTool" - }, - { - "$ref": "#/components/schemas/CreateBashToolDTO", - "title": "BashTool" - }, - { - "$ref": "#/components/schemas/CreateComputerToolDTO", - "title": "ComputerTool" - }, - { - "$ref": "#/components/schemas/CreateDtmfToolDTO", - "title": "DtmfTool" - }, - { - "$ref": "#/components/schemas/CreateEndCallToolDTO", - "title": "EndCallTool" - }, - { - "$ref": "#/components/schemas/CreateFunctionToolDTO", - "title": "FunctionTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelCalendarAvailabilityToolDTO", - "title": "GoHighLevelCalendarAvailabilityTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelCalendarEventCreateToolDTO", - "title": "GoHighLevelCalendarEventCreateTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelContactCreateToolDTO", - "title": "GoHighLevelContactCreateTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelContactGetToolDTO", - "title": "GoHighLevelContactGetTool" - }, - { - "$ref": "#/components/schemas/CreateGoogleCalendarCheckAvailabilityToolDTO", - "title": "GoogleCalendarCheckAvailabilityTool" - }, - { - "$ref": "#/components/schemas/CreateGoogleCalendarCreateEventToolDTO", - "title": "GoogleCalendarCreateEventTool" - }, - { - "$ref": "#/components/schemas/CreateGoogleSheetsRowAppendToolDTO", - "title": "GoogleSheetsRowAppendTool" - }, - { - "$ref": "#/components/schemas/CreateHandoffToolDTO", - "title": "HandoffTool" - }, - { - "$ref": "#/components/schemas/CreateMcpToolDTO", - "title": "McpTool" - }, - { - "$ref": "#/components/schemas/CreateQueryToolDTO", - "title": "QueryTool" - }, - { - "$ref": "#/components/schemas/CreateSlackSendMessageToolDTO", - "title": "SlackSendMessageTool" - }, - { - "$ref": "#/components/schemas/CreateSmsToolDTO", - "title": "SmsTool" - }, - { - "$ref": "#/components/schemas/CreateTextEditorToolDTO", - "title": "TextEditorTool" - }, - { - "$ref": "#/components/schemas/CreateTransferCallToolDTO", - "title": "TransferCallTool" - } - ] - } - }, - "toolIds": { - "description": "These are the tools that the assistant can use during the call. To use transient tools, use `tools`.\n\nBoth `tools` and `toolIds` can be used together.", - "type": "array", - "items": { - "type": "string" - } - }, - "knowledgeBase": { - "description": "These are the options for the knowledge base.", - "oneOf": [ - { - "$ref": "#/components/schemas/CreateCustomKnowledgeBaseDTO", - "title": "Custom" - } + "model": { + "type": "string", + "description": "This is the model that will be used for the transcription.", + "enum": [ + "whisper" ] }, - "knowledgeBaseId": { + "language": { "type": "string", - "description": "This is the ID of the knowledge base the model will use." - }, + "description": "This is the language that will be set for the transcription. The list of languages Whisper supports can be found here: https://github.com/openai/whisper/blob/main/whisper/tokenizer.py", + "enum": [ + "en", + "zh", + "de", + "es", + "ru", + "ko", + "fr", + "ja", + "pt", + "tr", + "pl", + "ca", + "nl", + "ar", + "sv", + "it", + "id", + "hi", + "fi", + "vi", + "he", + "uk", + "el", + "ms", + "cs", + "ro", + "da", + "hu", + "ta", + "no", + "th", + "ur", + "hr", + "bg", + "lt", + "la", + "mi", + "ml", + "cy", + "sk", + "te", + "fa", + "lv", + "bn", + "sr", + "az", + "sl", + "kn", + "et", + "mk", + "br", + "eu", + "is", + "hy", + "ne", + "mn", + "bs", + "kk", + "sq", + "sw", + "gl", + "mr", + "pa", + "si", + "km", + "sn", + "yo", + "so", + "af", + "oc", + "ka", + "be", + "tg", + "sd", + "gu", + "am", + "yi", + "lo", + "uz", + "fo", + "ht", + "ps", + "tk", + "nn", + "mt", + "sa", + "lb", + "my", + "bo", + "tl", + "mg", + "as", + "tt", + "haw", + "ln", + "ha", + "ba", + "jw", + "su", + "yue" + ] + } + }, + "required": [ + "provider" + ] + }, + "FallbackGoogleTranscriber": { + "type": "object", + "properties": { "provider": { "type": "string", + "description": "This is the transcription provider that will be used.", "enum": [ - "perplexity-ai" + "google" ] }, "model": { "type": "string", - "description": "This is the name of the model. Ex. cognitivecomputations/dolphin-mixtral-8x7b" - }, - "temperature": { - "type": "number", - "description": "This is the temperature that will be used for calls. Default is 0 to leverage caching for lower latency.", - "minimum": 0, - "maximum": 2 - }, - "maxTokens": { - "type": "number", - "description": "This is the max number of tokens that the assistant will be allowed to generate in each turn of the conversation. Default is 250.", - "minimum": 50, - "maximum": 10000 - }, - "emotionRecognitionEnabled": { - "type": "boolean", - "description": "This determines whether we detect user's emotion while they speak and send it as an additional info to model.\n\nDefault `false` because the model is usually are good at understanding the user's emotion from text.\n\n@default false" + "description": "This is the model that will be used for the transcription.", + "enum": [ + "gemini-3.5-flash", + "gemini-3.1-flash-lite", + "gemini-3-flash-preview", + "gemini-2.5-pro", + "gemini-2.5-flash", + "gemini-2.5-flash-lite", + "gemini-2.0-flash-thinking-exp", + "gemini-2.0-pro-exp-02-05", + "gemini-2.0-flash", + "gemini-2.0-flash-lite", + "gemini-2.0-flash-exp", + "gemini-2.0-flash-realtime-exp", + "gemini-1.5-flash", + "gemini-1.5-flash-002", + "gemini-1.5-pro", + "gemini-1.5-pro-002", + "gemini-1.0-pro" + ] }, - "numFastTurns": { - "type": "number", - "description": "This sets how many turns at the start of the conversation to use a smaller, faster model from the same provider before switching to the primary model. Example, gpt-3.5-turbo if provider is openai.\n\nDefault is 0.\n\n@default 0", - "minimum": 0 + "language": { + "type": "string", + "description": "This is the language that will be set for the transcription.", + "enum": [ + "Multilingual", + "Arabic", + "Bengali", + "Bulgarian", + "Chinese", + "Croatian", + "Czech", + "Danish", + "Dutch", + "English", + "Estonian", + "Finnish", + "French", + "German", + "Greek", + "Hebrew", + "Hindi", + "Hungarian", + "Indonesian", + "Italian", + "Japanese", + "Korean", + "Latvian", + "Lithuanian", + "Norwegian", + "Polish", + "Portuguese", + "Romanian", + "Russian", + "Serbian", + "Slovak", + "Slovenian", + "Spanish", + "Swahili", + "Swedish", + "Thai", + "Turkish", + "Ukrainian", + "Vietnamese" + ] } }, "required": [ - "provider", - "model" + "provider" ] }, - "TogetherAIModel": { + "FallbackOpenAITranscriber": { "type": "object", "properties": { - "messages": { - "description": "This is the starting state for the conversation.", - "type": "array", - "items": { - "$ref": "#/components/schemas/OpenAIMessage" - } - }, - "tools": { - "type": "array", - "description": "These are the tools that the assistant can use during the call. To use existing tools, use `toolIds`.\n\nBoth `tools` and `toolIds` can be used together.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/CreateApiRequestToolDTO", - "title": "ApiRequestTool" - }, - { - "$ref": "#/components/schemas/CreateBashToolDTO", - "title": "BashTool" - }, - { - "$ref": "#/components/schemas/CreateComputerToolDTO", - "title": "ComputerTool" - }, - { - "$ref": "#/components/schemas/CreateDtmfToolDTO", - "title": "DtmfTool" - }, - { - "$ref": "#/components/schemas/CreateEndCallToolDTO", - "title": "EndCallTool" - }, - { - "$ref": "#/components/schemas/CreateFunctionToolDTO", - "title": "FunctionTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelCalendarAvailabilityToolDTO", - "title": "GoHighLevelCalendarAvailabilityTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelCalendarEventCreateToolDTO", - "title": "GoHighLevelCalendarEventCreateTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelContactCreateToolDTO", - "title": "GoHighLevelContactCreateTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelContactGetToolDTO", - "title": "GoHighLevelContactGetTool" - }, - { - "$ref": "#/components/schemas/CreateGoogleCalendarCheckAvailabilityToolDTO", - "title": "GoogleCalendarCheckAvailabilityTool" - }, - { - "$ref": "#/components/schemas/CreateGoogleCalendarCreateEventToolDTO", - "title": "GoogleCalendarCreateEventTool" - }, - { - "$ref": "#/components/schemas/CreateGoogleSheetsRowAppendToolDTO", - "title": "GoogleSheetsRowAppendTool" - }, - { - "$ref": "#/components/schemas/CreateHandoffToolDTO", - "title": "HandoffTool" - }, - { - "$ref": "#/components/schemas/CreateMcpToolDTO", - "title": "McpTool" - }, - { - "$ref": "#/components/schemas/CreateQueryToolDTO", - "title": "QueryTool" - }, - { - "$ref": "#/components/schemas/CreateSlackSendMessageToolDTO", - "title": "SlackSendMessageTool" - }, - { - "$ref": "#/components/schemas/CreateSmsToolDTO", - "title": "SmsTool" - }, - { - "$ref": "#/components/schemas/CreateTextEditorToolDTO", - "title": "TextEditorTool" - }, - { - "$ref": "#/components/schemas/CreateTransferCallToolDTO", - "title": "TransferCallTool" - } - ] - } - }, - "toolIds": { - "description": "These are the tools that the assistant can use during the call. To use transient tools, use `tools`.\n\nBoth `tools` and `toolIds` can be used together.", - "type": "array", - "items": { - "type": "string" - } - }, - "knowledgeBase": { - "description": "These are the options for the knowledge base.", - "oneOf": [ - { - "$ref": "#/components/schemas/CreateCustomKnowledgeBaseDTO", - "title": "Custom" - } - ] - }, - "knowledgeBaseId": { - "type": "string", - "description": "This is the ID of the knowledge base the model will use." - }, "provider": { "type": "string", + "description": "This is the transcription provider that will be used.", "enum": [ - "together-ai" + "openai" ] }, "model": { "type": "string", - "description": "This is the name of the model. Ex. cognitivecomputations/dolphin-mixtral-8x7b" - }, - "temperature": { - "type": "number", - "description": "This is the temperature that will be used for calls. Default is 0 to leverage caching for lower latency.", - "minimum": 0, - "maximum": 2 - }, - "maxTokens": { - "type": "number", - "description": "This is the max number of tokens that the assistant will be allowed to generate in each turn of the conversation. Default is 250.", - "minimum": 50, - "maximum": 10000 - }, - "emotionRecognitionEnabled": { - "type": "boolean", - "description": "This determines whether we detect user's emotion while they speak and send it as an additional info to model.\n\nDefault `false` because the model is usually are good at understanding the user's emotion from text.\n\n@default false" + "description": "This is the model that will be used for the transcription.", + "enum": [ + "gpt-4o-transcribe", + "gpt-4o-mini-transcribe" + ] }, - "numFastTurns": { - "type": "number", - "description": "This sets how many turns at the start of the conversation to use a smaller, faster model from the same provider before switching to the primary model. Example, gpt-3.5-turbo if provider is openai.\n\nDefault is 0.\n\n@default 0", - "minimum": 0 + "language": { + "type": "string", + "description": "This is the language that will be set for the transcription.", + "enum": [ + "af", + "ar", + "hy", + "az", + "be", + "bs", + "bg", + "ca", + "zh", + "hr", + "cs", + "da", + "nl", + "en", + "et", + "fi", + "fr", + "gl", + "de", + "el", + "he", + "hi", + "hu", + "is", + "id", + "it", + "ja", + "kn", + "kk", + "ko", + "lv", + "lt", + "mk", + "ms", + "mr", + "mi", + "ne", + "no", + "fa", + "pl", + "pt", + "ro", + "ru", + "sr", + "sk", + "sl", + "es", + "sw", + "sv", + "tl", + "ta", + "th", + "tr", + "uk", + "ur", + "vi", + "cy" + ] } }, "required": [ @@ -15139,1132 +15786,1554 @@ "model" ] }, - "HangupNode": { + "FallbackXaiTranscriber": { "type": "object", "properties": { - "type": { + "provider": { "type": "string", "enum": [ - "hangup" + "xai" ] }, - "name": { + "model": { "type": "string", - "maxLength": 80 - }, - "isStart": { - "type": "boolean", - "description": "This is whether or not the node is the start of the workflow." + "description": "The xAI speech-to-text model to use. xAI currently exposes a single STT model — placeholder for future model selection.", + "enum": [ + "default" + ] }, - "metadata": { - "type": "object", - "description": "This is for metadata you want to store on the task." + "language": { + "type": "string", + "description": "Single language for transcription as an ISO 639-1 code (e.g., `en`, `es`). Defaults to `en` if not set. xAI auto-detects when omitted via the API but Vapi defaults to English for deterministic behavior.", + "enum": [ + "ar", + "cs", + "da", + "nl", + "en", + "fil", + "fr", + "de", + "hi", + "id", + "it", + "ja", + "ko", + "mk", + "ms", + "fa", + "pl", + "pt", + "ro", + "ru", + "es", + "sv", + "th", + "tr", + "vi" + ] } }, "required": [ - "type", - "name" + "provider" ] }, - "WorkflowOpenAIModel": { + "LangfuseObservabilityPlan": { "type": "object", "properties": { "provider": { "type": "string", - "description": "This is the provider of the model (`openai`).", "enum": [ - "openai" + "langfuse" ] }, - "model": { + "promptName": { "type": "string", - "description": "This is the OpenAI model that will be used.\n\nWhen using Vapi OpenAI or your own Azure Credentials, you have the option to specify the region for the selected model. This shouldn't be specified unless you have a specific reason to do so. Vapi will automatically find the fastest region that make sense.\nThis is helpful when you are required to comply with Data Residency rules. Learn more about Azure regions here https://azure.microsoft.com/en-us/explore/global-infrastructure/data-residency/.", - "maxLength": 100, - "enum": [ - "gpt-5", - "gpt-5-mini", - "gpt-5-nano", - "gpt-4.1-2025-04-14", - "gpt-4.1-mini-2025-04-14", - "gpt-4.1-nano-2025-04-14", - "gpt-4.1", - "gpt-4.1-mini", - "gpt-4.1-nano", - "chatgpt-4o-latest", - "o3", - "o3-mini", - "o4-mini", - "o1-mini", - "o1-mini-2024-09-12", - "gpt-4o-mini-2024-07-18", - "gpt-4o-mini", - "gpt-4o", - "gpt-4o-2024-05-13", - "gpt-4o-2024-08-06", - "gpt-4o-2024-11-20", - "gpt-4-turbo", - "gpt-4-turbo-2024-04-09", - "gpt-4-turbo-preview", - "gpt-4-0125-preview", - "gpt-4-1106-preview", - "gpt-4", - "gpt-4-0613", - "gpt-3.5-turbo", - "gpt-3.5-turbo-0125", - "gpt-3.5-turbo-1106", - "gpt-3.5-turbo-16k", - "gpt-3.5-turbo-0613", - "gpt-4.1-2025-04-14:westus", - "gpt-4.1-2025-04-14:eastus2", - "gpt-4.1-2025-04-14:eastus", - "gpt-4.1-2025-04-14:westus3", - "gpt-4.1-2025-04-14:northcentralus", - "gpt-4.1-2025-04-14:southcentralus", - "gpt-4.1-mini-2025-04-14:westus", - "gpt-4.1-mini-2025-04-14:eastus2", - "gpt-4.1-mini-2025-04-14:eastus", - "gpt-4.1-mini-2025-04-14:westus3", - "gpt-4.1-mini-2025-04-14:northcentralus", - "gpt-4.1-mini-2025-04-14:southcentralus", - "gpt-4.1-nano-2025-04-14:westus", - "gpt-4.1-nano-2025-04-14:eastus2", - "gpt-4.1-nano-2025-04-14:westus3", - "gpt-4.1-nano-2025-04-14:northcentralus", - "gpt-4.1-nano-2025-04-14:southcentralus", - "gpt-4o-2024-11-20:swedencentral", - "gpt-4o-2024-11-20:westus", - "gpt-4o-2024-11-20:eastus2", - "gpt-4o-2024-11-20:eastus", - "gpt-4o-2024-11-20:westus3", - "gpt-4o-2024-11-20:southcentralus", - "gpt-4o-2024-08-06:westus", - "gpt-4o-2024-08-06:westus3", - "gpt-4o-2024-08-06:eastus", - "gpt-4o-2024-08-06:eastus2", - "gpt-4o-2024-08-06:northcentralus", - "gpt-4o-2024-08-06:southcentralus", - "gpt-4o-mini-2024-07-18:westus", - "gpt-4o-mini-2024-07-18:westus3", - "gpt-4o-mini-2024-07-18:eastus", - "gpt-4o-mini-2024-07-18:eastus2", - "gpt-4o-mini-2024-07-18:northcentralus", - "gpt-4o-mini-2024-07-18:southcentralus", - "gpt-4o-2024-05-13:eastus2", - "gpt-4o-2024-05-13:eastus", - "gpt-4o-2024-05-13:northcentralus", - "gpt-4o-2024-05-13:southcentralus", - "gpt-4o-2024-05-13:westus3", - "gpt-4o-2024-05-13:westus", - "gpt-4-turbo-2024-04-09:eastus2", - "gpt-4-0125-preview:eastus", - "gpt-4-0125-preview:northcentralus", - "gpt-4-0125-preview:southcentralus", - "gpt-4-1106-preview:australia", - "gpt-4-1106-preview:canadaeast", - "gpt-4-1106-preview:france", - "gpt-4-1106-preview:india", - "gpt-4-1106-preview:norway", - "gpt-4-1106-preview:swedencentral", - "gpt-4-1106-preview:uk", - "gpt-4-1106-preview:westus", - "gpt-4-1106-preview:westus3", - "gpt-4-0613:canadaeast", - "gpt-3.5-turbo-0125:canadaeast", - "gpt-3.5-turbo-0125:northcentralus", - "gpt-3.5-turbo-0125:southcentralus", - "gpt-3.5-turbo-1106:canadaeast", - "gpt-3.5-turbo-1106:westus" - ] + "description": "The name of a Langfuse prompt to link generations to. This enables tracking which prompt version was used for each generation. https://langfuse.com/docs/prompt-management/features/link-to-traces" }, - "temperature": { + "promptVersion": { "type": "number", - "description": "This is the temperature of the model.", - "minimum": 0, - "maximum": 2 + "description": "The version number of the Langfuse prompt to link generations to. Used together with promptName to identify the exact prompt version. https://langfuse.com/docs/prompt-management/features/link-to-traces", + "minimum": 1 }, - "maxTokens": { - "type": "number", - "description": "This is the max tokens of the model.", - "minimum": 50, - "maximum": 10000 + "traceName": { + "type": "string", + "description": "Custom name for the Langfuse trace. Supports Liquid templates.\n\nAvailable variables:\n- {{ call.id }} - Call UUID\n- {{ call.type }} - 'inboundPhoneCall', 'outboundPhoneCall', 'webCall'\n- {{ assistant.name }} - Assistant name\n- {{ assistant.id }} - Assistant ID\n\nExample: \"{{ assistant.name }} - {{ call.type }}\"\n\nDefaults to call ID if not provided." + }, + "tags": { + "description": "This is an array of tags to be added to the Langfuse trace. Tags allow you to categorize and filter traces. https://langfuse.com/docs/tracing-features/tags", + "type": "array", + "items": { + "type": "string" + } + }, + "metadata": { + "type": "object", + "description": "This is a JSON object that will be added to the Langfuse trace. Traces can be enriched with metadata to better understand your users, application, and experiments. https://langfuse.com/docs/tracing-features/metadata\nBy default it includes the call metadata, assistant metadata, and assistant overrides." } }, "required": [ "provider", - "model" + "tags" ] }, - "WorkflowAnthropicModel": { + "TextContent": { "type": "object", "properties": { - "provider": { + "type": { "type": "string", - "description": "This is the provider of the model (`anthropic`).", "enum": [ - "anthropic" + "text" ] }, - "model": { + "text": { + "type": "string" + }, + "language": { "type": "string", - "description": "This is the specific model that will be used.", - "maxLength": 100, "enum": [ - "claude-3-opus-20240229", - "claude-3-sonnet-20240229", - "claude-3-haiku-20240307", - "claude-3-5-sonnet-20240620", - "claude-3-5-sonnet-20241022", - "claude-3-5-haiku-20241022", - "claude-3-7-sonnet-20250219", - "claude-opus-4-20250514", - "claude-sonnet-4-20250514" - ] - }, - "thinking": { - "description": "This is the optional configuration for Anthropic's thinking feature.\n\n- Only applicable for `claude-3-7-sonnet-20250219` model.\n- If provided, `maxTokens` must be greater than `thinking.budgetTokens`.", - "allOf": [ - { - "$ref": "#/components/schemas/AnthropicThinkingConfig" - } + "aa", + "ab", + "ae", + "af", + "ak", + "am", + "an", + "ar", + "as", + "av", + "ay", + "az", + "ba", + "be", + "bg", + "bh", + "bi", + "bm", + "bn", + "bo", + "br", + "bs", + "ca", + "ce", + "ch", + "co", + "cr", + "cs", + "cu", + "cv", + "cy", + "da", + "de", + "dv", + "dz", + "ee", + "el", + "en", + "eo", + "es", + "et", + "eu", + "fa", + "ff", + "fi", + "fj", + "fo", + "fr", + "fy", + "ga", + "gd", + "gl", + "gn", + "gu", + "gv", + "ha", + "he", + "hi", + "ho", + "hr", + "ht", + "hu", + "hy", + "hz", + "ia", + "id", + "ie", + "ig", + "ii", + "ik", + "io", + "is", + "it", + "iu", + "ja", + "jv", + "ka", + "kg", + "ki", + "kj", + "kk", + "kl", + "km", + "kn", + "ko", + "kr", + "ks", + "ku", + "kv", + "kw", + "ky", + "la", + "lb", + "lg", + "li", + "ln", + "lo", + "lt", + "lu", + "lv", + "mg", + "mh", + "mi", + "mk", + "ml", + "mn", + "mr", + "ms", + "mt", + "my", + "na", + "nb", + "nd", + "ne", + "ng", + "nl", + "nn", + "no", + "nr", + "nv", + "ny", + "oc", + "oj", + "om", + "or", + "os", + "pa", + "pi", + "pl", + "ps", + "pt", + "qu", + "rm", + "rn", + "ro", + "ru", + "rw", + "sa", + "sc", + "sd", + "se", + "sg", + "si", + "sk", + "sl", + "sm", + "sn", + "so", + "sq", + "sr", + "ss", + "st", + "su", + "sv", + "sw", + "ta", + "te", + "tg", + "th", + "ti", + "tk", + "tl", + "tn", + "to", + "tr", + "ts", + "tt", + "tw", + "ty", + "ug", + "uk", + "ur", + "uz", + "ve", + "vi", + "vo", + "wa", + "wo", + "xh", + "yi", + "yue", + "yo", + "za", + "zh", + "zu" ] - }, - "temperature": { - "type": "number", - "description": "This is the temperature of the model.", - "minimum": 0, - "maximum": 2 - }, - "maxTokens": { - "type": "number", - "description": "This is the max tokens of the model.", - "minimum": 50, - "maximum": 10000 } }, "required": [ - "provider", - "model" + "type", + "text", + "language" ] }, - "WorkflowGoogleModel": { + "Condition": { "type": "object", "properties": { - "provider": { + "operator": { "type": "string", - "description": "This is the provider of the model (`google`).", + "description": "This is the operator you want to use to compare the parameter and value.", "enum": [ - "google" + "eq", + "neq", + "gt", + "gte", + "lt", + "lte" ] }, - "model": { + "param": { "type": "string", - "description": "This is the name of the model. Ex. cognitivecomputations/dolphin-mixtral-8x7b", - "maxLength": 100, - "enum": [ - "gemini-2.5-pro", - "gemini-2.5-flash", - "gemini-2.5-flash-lite", - "gemini-2.0-flash-thinking-exp", - "gemini-2.0-pro-exp-02-05", - "gemini-2.0-flash", - "gemini-2.0-flash-lite", - "gemini-2.0-flash-exp", - "gemini-2.0-flash-realtime-exp", - "gemini-1.5-flash", - "gemini-1.5-flash-002", - "gemini-1.5-pro", - "gemini-1.5-pro-002", - "gemini-1.0-pro" - ] - }, - "temperature": { - "type": "number", - "description": "This is the temperature of the model.", - "minimum": 0, - "maximum": 2 + "description": "This is the name of the parameter that you want to check.", + "maxLength": 1000 }, - "maxTokens": { - "type": "number", - "description": "This is the max tokens of the model.", - "minimum": 50, - "maximum": 10000 + "value": { + "type": "string", + "description": "This is the value you want to compare against the parameter.", + "maxLength": 1000 } }, "required": [ - "provider", - "model" + "operator", + "param", + "value" ] }, - "WorkflowCustomModel": { + "ToolMessageStart": { "type": "object", "properties": { - "provider": { - "type": "string", - "description": "This is the provider of the model (`custom-llm`).", - "enum": [ - "custom-llm" - ] + "contents": { + "type": "array", + "description": "This is an alternative to the `content` property. It allows to specify variants of the same content, one per language.\n\nUsage:\n- If your assistants are multilingual, you can provide content for each language.\n- If you don't provide content for a language, the first item in the array will be automatically translated to the active language at that moment.\n\nThis will override the `content` property.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/TextContent", + "title": "Text" + } + ] + } }, - "metadataSendMode": { + "type": { "type": "string", - "description": "This determines whether metadata is sent in requests to the custom provider.\n\n- `off` will not send any metadata. payload will look like `{ messages }`\n- `variable` will send `assistant.metadata` as a variable on the payload. payload will look like `{ messages, metadata }`\n- `destructured` will send `assistant.metadata` fields directly on the payload. payload will look like `{ messages, ...metadata }`\n\nFurther, `variable` and `destructured` will send `call`, `phoneNumber`, and `customer` objects in the payload.\n\nDefault is `variable`.", "enum": [ - "off", - "variable", - "destructured" - ] - }, - "url": { - "type": "string", - "description": "These is the URL we'll use for the OpenAI client's `baseURL`. Ex. https://openrouter.ai/api/v1" - }, - "headers": { - "type": "object", - "description": "These are the headers we'll use for the OpenAI client's `headers`." + "request-start" + ], + "description": "This message is triggered when the tool call starts.\n\nThis message is never triggered for async tools.\n\nMultiple request-start messages are variants. One eligible variant is selected each time the tool starts.\n\nIf this message is not provided, one of the default filler messages \"Hold on a sec\", \"One moment\", \"Just a sec\", \"Give me a moment\" or \"This'll just take a sec\" will be used." }, - "timeoutSeconds": { - "type": "number", - "description": "This sets the timeout for the connection to the custom provider without needing to stream any tokens back. Default is 20 seconds.", - "minimum": 20, - "maximum": 600 + "blocking": { + "type": "boolean", + "description": "This is an optional boolean that if true, the tool call will only trigger after the message is spoken. Default is false.\n\n@default false", + "example": false, + "default": false }, - "model": { + "content": { "type": "string", - "description": "This is the name of the model. Ex. cognitivecomputations/dolphin-mixtral-8x7b", - "maxLength": 100 - }, - "temperature": { - "type": "number", - "description": "This is the temperature of the model.", - "minimum": 0, - "maximum": 2 + "description": "This is the content that the assistant says when this message is triggered.", + "maxLength": 1000 }, - "maxTokens": { - "type": "number", - "description": "This is the max tokens of the model.", - "minimum": 50, - "maximum": 10000 + "conditions": { + "description": "This is an optional array of conditions that the tool call arguments must meet in order for this message to be triggered.", + "type": "array", + "items": { + "$ref": "#/components/schemas/Condition" + } } }, "required": [ - "provider", - "url", - "model" + "type" ] }, - "GlobalNodePlan": { + "ToolMessageComplete": { "type": "object", "properties": { - "enabled": { - "type": "boolean", - "description": "This is the flag to determine if this node is a global node\n\n@default false", - "default": false + "contents": { + "type": "array", + "description": "This is an alternative to the `content` property. It allows to specify variants of the same content, one per language.\n\nUsage:\n- If your assistants are multilingual, you can provide content for each language.\n- If you don't provide content for a language, the first item in the array will be automatically translated to the active language at that moment.\n\nThis will override the `content` property.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/TextContent", + "title": "Text" + } + ] + } }, - "enterCondition": { - "type": "string", - "description": "This is the condition that will be checked to determine if the global node should be executed.\n\n@default ''", - "maxLength": 1000, - "default": "" - } - } - }, - "ConversationNode": { - "type": "object", - "properties": { "type": { "type": "string", - "description": "This is the Conversation node. This can be used to start a conversation with the customer.\n\nThe flow is:\n- Workflow starts the conversation node\n- Model is active with the `prompt` and global context.\n- Model will call a tool to exit this node.\n- Workflow will extract variables from the conversation.\n- Workflow continues.", + "description": "This message is triggered when the tool call is complete.\n\nThis message is triggered immediately without waiting for your server to respond for async tool calls.\n\nIf this message is not provided, the model will be requested to respond.\n\nIf this message is provided, only this message will be spoken and the model will not be requested to come up with a response. It's an exclusive OR.", "enum": [ - "conversation" + "request-complete" ] }, - "model": { - "description": "This is the model for the node.\n\nThis overrides `workflow.model`.", - "oneOf": [ - { - "$ref": "#/components/schemas/WorkflowOpenAIModel", - "title": "WorkflowOpenAIModel" - }, - { - "$ref": "#/components/schemas/WorkflowAnthropicModel", - "title": "WorkflowAnthropicModel" - }, - { - "$ref": "#/components/schemas/WorkflowGoogleModel", - "title": "WorkflowGoogleModel" - }, - { - "$ref": "#/components/schemas/WorkflowCustomModel", - "title": "WorkflowCustomModel" - } + "role": { + "type": "string", + "description": "This is optional and defaults to \"assistant\".\n\nWhen role=assistant, `content` is said out loud.\n\nWhen role=system, `content` is passed to the model in a system message. Example:\n system: default one\n assistant:\n user:\n assistant:\n user:\n assistant:\n user:\n assistant: tool called\n tool: your server response\n <--- system prompt as hint\n ---> model generates response which is spoken\nThis is useful when you want to provide a hint to the model about what to say next.", + "enum": [ + "assistant", + "system" ] }, - "transcriber": { - "description": "This is the transcriber for the node.\n\nThis overrides `workflow.transcriber`.", - "oneOf": [ - { - "$ref": "#/components/schemas/AssemblyAITranscriber", - "title": "AssemblyAITranscriber" - }, - { - "$ref": "#/components/schemas/AzureSpeechTranscriber", - "title": "AzureSpeechTranscriber" - }, - { - "$ref": "#/components/schemas/CustomTranscriber", - "title": "CustomTranscriber" - }, - { - "$ref": "#/components/schemas/DeepgramTranscriber", - "title": "DeepgramTranscriber" - }, - { - "$ref": "#/components/schemas/ElevenLabsTranscriber", - "title": "ElevenLabsTranscriber" - }, - { - "$ref": "#/components/schemas/GladiaTranscriber", - "title": "GladiaTranscriber" - }, - { - "$ref": "#/components/schemas/GoogleTranscriber", - "title": "GoogleTranscriber" - }, - { - "$ref": "#/components/schemas/SpeechmaticsTranscriber", - "title": "SpeechmaticsTranscriber" - }, - { - "$ref": "#/components/schemas/TalkscriberTranscriber", - "title": "TalkscriberTranscriber" - }, - { - "$ref": "#/components/schemas/OpenAITranscriber", - "title": "OpenAITranscriber" - }, - { - "$ref": "#/components/schemas/CartesiaTranscriber", - "title": "CartesiaTranscriber" - } - ] + "endCallAfterSpokenEnabled": { + "type": "boolean", + "description": "This is an optional boolean that if true, the call will end after the message is spoken. Default is false.\n\nThis is ignored if `role` is set to `system`.\n\n@default false", + "example": false }, - "voice": { - "description": "This is the voice for the node.\n\nThis overrides `workflow.voice`.", - "oneOf": [ - { - "$ref": "#/components/schemas/AzureVoice", - "title": "AzureVoice" - }, - { - "$ref": "#/components/schemas/CartesiaVoice", - "title": "CartesiaVoice" - }, - { - "$ref": "#/components/schemas/CustomVoice", - "title": "CustomVoice" - }, - { - "$ref": "#/components/schemas/DeepgramVoice", - "title": "DeepgramVoice" - }, - { - "$ref": "#/components/schemas/ElevenLabsVoice", - "title": "ElevenLabsVoice" - }, - { - "$ref": "#/components/schemas/HumeVoice", - "title": "HumeVoice" - }, - { - "$ref": "#/components/schemas/LMNTVoice", - "title": "LMNTVoice" - }, - { - "$ref": "#/components/schemas/NeuphonicVoice", - "title": "NeuphonicVoice" - }, - { - "$ref": "#/components/schemas/OpenAIVoice", - "title": "OpenAIVoice" - }, - { - "$ref": "#/components/schemas/PlayHTVoice", - "title": "PlayHTVoice" - }, - { - "$ref": "#/components/schemas/RimeAIVoice", - "title": "RimeAIVoice" - }, - { - "$ref": "#/components/schemas/SmallestAIVoice", - "title": "SmallestAIVoice" - }, - { - "$ref": "#/components/schemas/TavusVoice", - "title": "TavusVoice" - }, - { - "$ref": "#/components/schemas/VapiVoice", - "title": "VapiVoice" - }, - { - "$ref": "#/components/schemas/SesameVoice", - "title": "SesameVoice" - }, - { - "$ref": "#/components/schemas/InworldVoice", - "title": "InworldVoice" - }, - { - "$ref": "#/components/schemas/MinimaxVoice", - "title": "MinimaxVoice" - } - ] + "content": { + "type": "string", + "description": "This is the content that the assistant says when this message is triggered.", + "maxLength": 1000 }, - "tools": { + "conditions": { + "description": "This is an optional array of conditions that the tool call arguments must meet in order for this message to be triggered.", "type": "array", - "description": "These are the tools that the conversation node can use during the call. To use existing tools, use `toolIds`.\n\nBoth `tools` and `toolIds` can be used together.", + "items": { + "$ref": "#/components/schemas/Condition" + } + } + }, + "required": [ + "type" + ] + }, + "ToolMessageFailed": { + "type": "object", + "properties": { + "contents": { + "type": "array", + "description": "This is an alternative to the `content` property. It allows to specify variants of the same content, one per language.\n\nUsage:\n- If your assistants are multilingual, you can provide content for each language.\n- If you don't provide content for a language, the first item in the array will be automatically translated to the active language at that moment.\n\nThis will override the `content` property.", "items": { "oneOf": [ { - "$ref": "#/components/schemas/CreateApiRequestToolDTO", - "title": "ApiRequestTool" - }, - { - "$ref": "#/components/schemas/CreateBashToolDTO", - "title": "BashTool" - }, - { - "$ref": "#/components/schemas/CreateComputerToolDTO", - "title": "ComputerTool" - }, - { - "$ref": "#/components/schemas/CreateDtmfToolDTO", - "title": "DtmfTool" - }, - { - "$ref": "#/components/schemas/CreateEndCallToolDTO", - "title": "EndCallTool" - }, - { - "$ref": "#/components/schemas/CreateFunctionToolDTO", - "title": "FunctionTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelCalendarAvailabilityToolDTO", - "title": "GoHighLevelCalendarAvailabilityTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelCalendarEventCreateToolDTO", - "title": "GoHighLevelCalendarEventCreateTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelContactCreateToolDTO", - "title": "GoHighLevelContactCreateTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelContactGetToolDTO", - "title": "GoHighLevelContactGetTool" - }, - { - "$ref": "#/components/schemas/CreateGoogleCalendarCheckAvailabilityToolDTO", - "title": "GoogleCalendarCheckAvailabilityTool" - }, - { - "$ref": "#/components/schemas/CreateGoogleCalendarCreateEventToolDTO", - "title": "GoogleCalendarCreateEventTool" - }, - { - "$ref": "#/components/schemas/CreateGoogleSheetsRowAppendToolDTO", - "title": "GoogleSheetsRowAppendTool" - }, - { - "$ref": "#/components/schemas/CreateHandoffToolDTO", - "title": "HandoffTool" - }, - { - "$ref": "#/components/schemas/CreateMcpToolDTO", - "title": "McpTool" - }, - { - "$ref": "#/components/schemas/CreateQueryToolDTO", - "title": "QueryTool" - }, - { - "$ref": "#/components/schemas/CreateSlackSendMessageToolDTO", - "title": "SlackSendMessageTool" - }, - { - "$ref": "#/components/schemas/CreateSmsToolDTO", - "title": "SmsTool" - }, - { - "$ref": "#/components/schemas/CreateTextEditorToolDTO", - "title": "TextEditorTool" - }, - { - "$ref": "#/components/schemas/CreateTransferCallToolDTO", - "title": "TransferCallTool" + "$ref": "#/components/schemas/TextContent", + "title": "Text" } ] } }, - "toolIds": { - "description": "These are the tools that the conversation node can use during the call. To use transient tools, use `tools`.\n\nBoth `tools` and `toolIds` can be used together.", + "type": { + "type": "string", + "description": "This message is triggered when the tool call fails.\n\nThis message is never triggered for async tool calls.\n\nIf this message is not provided, the model will be requested to respond.\n\nIf this message is provided, only this message will be spoken and the model will not be requested to come up with a response. It's an exclusive OR.", + "enum": [ + "request-failed" + ] + }, + "role": { + "type": "string", + "description": "This is optional and defaults to \"assistant\".\n\nWhen role=assistant, `content` is said out loud when the tool call fails.\n\nWhen role=system, `content` is passed to the model as a system message\nalong with the failure result, and the model's generated response is\nspoken. Example:\n assistant: tool called\n tool: error from your server\n <--- system prompt as hint\n ---> model generates response which is spoken\nThis is useful when you want the model to generate an error-aware\nresponse instead of speaking a fixed failure message.", + "enum": [ + "assistant", + "system" + ] + }, + "endCallAfterSpokenEnabled": { + "type": "boolean", + "description": "This is an optional boolean that if true, the call will end after the message is spoken. Default is false.\n\nThis is ignored if `role` is set to `system`.\n\n@default false", + "example": false + }, + "content": { + "type": "string", + "description": "This is the content that the assistant says when this message is triggered.", + "maxLength": 1000 + }, + "conditions": { + "description": "This is an optional array of conditions that the tool call arguments must meet in order for this message to be triggered.", "type": "array", "items": { - "type": "string" + "$ref": "#/components/schemas/Condition" + } + } + }, + "required": [ + "type" + ] + }, + "ToolMessageDelayed": { + "type": "object", + "properties": { + "contents": { + "type": "array", + "description": "This is an alternative to the `content` property. It allows to specify variants of the same content, one per language.\n\nUsage:\n- If your assistants are multilingual, you can provide content for each language.\n- If you don't provide content for a language, the first item in the array will be automatically translated to the active language at that moment.\n\nThis will override the `content` property.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/TextContent", + "title": "Text" + } + ] } }, - "prompt": { + "type": { "type": "string", - "maxLength": 5000 - }, - "globalNodePlan": { - "description": "This is the plan for the global node.", - "allOf": [ - { - "$ref": "#/components/schemas/GlobalNodePlan" - } + "description": "This message is triggered when the tool call is delayed. Same timing means variants; different timings mean staged updates.", + "enum": [ + "request-response-delayed" ] }, - "variableExtractionPlan": { - "description": "This is the plan that controls the variable extraction from the user's responses.\n\nUsage:\nUse `schema` to specify what you want to extract from the user's responses.\n```json\n{\n \"schema\": {\n \"type\": \"object\",\n \"properties\": {\n \"user\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n },\n \"age\": {\n \"type\": \"number\"\n }\n }\n }\n }\n }\n}\n```\n\nThis will be extracted as `{{ user.name }}` and `{{ user.age }}` respectively.\n\n(Optional) Use `aliases` to create new variables.\n\n```json\n{\n \"aliases\": [\n {\n \"key\": \"userAge\",\n \"value\": \"{{user.age}}\"\n },\n {\n \"key\": \"userName\",\n \"value\": \"{{user.name}}\"\n }\n ]\n}\n```\n\nThis will be extracted as `{{ userAge }}` and `{{ userName }}` respectively.\n\nNote: The `schema` field is required for Conversation nodes if you want to extract variables from the user's responses. `aliases` is just a convenience.", - "allOf": [ - { - "$ref": "#/components/schemas/VariableExtractionPlan" - } - ] + "timingMilliseconds": { + "type": "number", + "minimum": 100, + "maximum": 120000, + "example": 1000, + "description": "The number of milliseconds to wait for the server response before saying this delayed message." }, - "name": { + "content": { "type": "string", - "maxLength": 80 - }, - "isStart": { - "type": "boolean", - "description": "This is whether or not the node is the start of the workflow." + "description": "This is the content that the assistant says when this message is triggered.", + "maxLength": 1000 }, - "metadata": { - "type": "object", - "description": "This is for metadata you want to store on the task." + "conditions": { + "description": "This is an optional array of conditions that the tool call arguments must meet in order for this message to be triggered.", + "type": "array", + "items": { + "$ref": "#/components/schemas/Condition" + } } }, "required": [ - "type", - "name" + "type" ] }, - "ToolNode": { + "MessageTarget": { "type": "object", "properties": { - "type": { + "role": { "type": "string", - "description": "This is the Tool node. This can be used to call a tool in your workflow.\n\nThe flow is:\n- Workflow starts the tool node\n- Model is called to extract parameters needed by the tool from the conversation history\n- Tool is called with the parameters\n- Server returns a response\n- Workflow continues with the response", + "description": "This is the role of the message to target.\n\nIf not specified, will find the position in the message history ignoring role (effectively `any`).", + "example": "user", "enum": [ - "tool" + "user", + "assistant" ] }, - "tool": { - "description": "This is the tool to call. To use an existing tool, send `toolId` instead.", - "oneOf": [ - { - "$ref": "#/components/schemas/CreateApiRequestToolDTO", - "title": "ApiRequestTool" - }, - { - "$ref": "#/components/schemas/CreateBashToolDTO", - "title": "BashTool" - }, - { - "$ref": "#/components/schemas/CreateComputerToolDTO", - "title": "ComputerTool" - }, - { - "$ref": "#/components/schemas/CreateDtmfToolDTO", - "title": "DtmfTool" - }, - { - "$ref": "#/components/schemas/CreateEndCallToolDTO", - "title": "EndCallTool" - }, - { - "$ref": "#/components/schemas/CreateFunctionToolDTO", - "title": "FunctionTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelCalendarAvailabilityToolDTO", - "title": "GoHighLevelCalendarAvailabilityTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelCalendarEventCreateToolDTO", - "title": "GoHighLevelCalendarEventCreateTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelContactCreateToolDTO", - "title": "GoHighLevelContactCreateTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelContactGetToolDTO", - "title": "GoHighLevelContactGetTool" - }, - { - "$ref": "#/components/schemas/CreateGoogleCalendarCheckAvailabilityToolDTO", - "title": "GoogleCalendarCheckAvailabilityTool" - }, - { - "$ref": "#/components/schemas/CreateGoogleCalendarCreateEventToolDTO", - "title": "GoogleCalendarCreateEventTool" - }, - { - "$ref": "#/components/schemas/CreateGoogleSheetsRowAppendToolDTO", - "title": "GoogleSheetsRowAppendTool" - }, - { - "$ref": "#/components/schemas/CreateHandoffToolDTO", - "title": "HandoffTool" - }, - { - "$ref": "#/components/schemas/CreateMcpToolDTO", - "title": "McpTool" - }, - { - "$ref": "#/components/schemas/CreateQueryToolDTO", - "title": "QueryTool" - }, - { - "$ref": "#/components/schemas/CreateSlackSendMessageToolDTO", - "title": "SlackSendMessageTool" - }, - { - "$ref": "#/components/schemas/CreateSmsToolDTO", - "title": "SmsTool" - }, - { - "$ref": "#/components/schemas/CreateTextEditorToolDTO", - "title": "TextEditorTool" - }, - { - "$ref": "#/components/schemas/CreateTransferCallToolDTO", - "title": "TransferCallTool" - } + "position": { + "type": "number", + "description": "This is the position of the message to target.\n- Negative numbers: Count from end (-1 = most recent, -2 = second most recent)\n- 0: First/oldest message in history\n- Positive numbers: Specific position (0-indexed from start)\n\n@default -1 (most recent message)", + "example": -1 + } + } + }, + "RegexCondition": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "This is the type discriminator for regex condition", + "example": "regex", + "enum": [ + "regex" ] }, - "toolId": { + "regex": { "type": "string", - "description": "This is the tool to call. To use a transient tool, send `tool` instead." + "description": "This is the regular expression pattern to match against message content.\n\nNote:\n- This works by using the RegExp.test method in Node.JS. Eg. /hello/.test(\"hello there\") will return true.\n\nHot tips:\n- In JavaScript, escape \\ when sending the regex pattern. Eg. \"hello\\sthere\" will be sent over the wire as \"hellosthere\". Send \"hello\\\\sthere\" instead.\n- RegExp.test does substring matching, so /cat/.test(\"I love cats\") will return true. To do full string matching, use anchors: /^cat$/ will only match exactly \"cat\".\n- Word boundaries \\b are useful for matching whole words: /\\bcat\\b/ matches \"cat\" but not \"cats\" or \"category\".\n- Use inline flags for portability: (?i) for case insensitive, (?m) for multiline", + "examples": [ + "\\\\b(cancel|stop|wait)\\\\b - Matches whole words", + "^yes$ - Matches exactly yes (full string match)", + "(?i)hello - Case insensitive match" + ] }, - "name": { - "type": "string", - "maxLength": 80 + "target": { + "description": "This is the target for messages to check against.\nIf not specified, the condition will run on the last message (position: -1).\nIf role is not specified, it will look at the last message regardless of role.\n@default { position: -1 }", + "allOf": [ + { + "$ref": "#/components/schemas/MessageTarget" + } + ] }, - "isStart": { + "negate": { "type": "boolean", - "description": "This is whether or not the node is the start of the workflow." - }, - "metadata": { - "type": "object", - "description": "This is for metadata you want to store on the task." + "description": "This is the flag that when true, the condition matches if the pattern does NOT match.\nUseful for ensuring certain words/phrases are absent.\n\n@default false", + "example": "true - Reject if user hasn\"t said goodbye: { regex: \"\\\\b(bye|goodbye)\\\\b\", negate: true }" } }, "required": [ "type", - "name" + "regex" ] }, - "AIEdgeCondition": { + "LiquidCondition": { "type": "object", "properties": { "type": { "type": "string", + "description": "This is the type discriminator for liquid condition", + "example": "liquid", "enum": [ - "ai" + "liquid" ] }, - "prompt": { + "liquid": { "type": "string", - "description": "This is the prompt for the AI edge condition. It should evaluate to a boolean.", - "maxLength": 1000 + "description": "This is the Liquid template that must return exactly \"true\" or \"false\" as a string.\nThe template is evaluated and the entire output must be either \"true\" or \"false\" - nothing else.\n\nAvailable variables:\n- `messages`: Array of recent messages in OpenAI chat completions format (ChatCompletionMessageParam[])\n Each message has properties like: role ('user', 'assistant', 'system'), content (string), etc.\n- `now`: Current timestamp in milliseconds (built-in Liquid variable)\n- Any assistant variable values (e.g., `userName`, `accountStatus`)\n\nUseful Liquid filters for messages:\n- `messages | last: 5` - Get the 5 most recent messages\n- `messages | where: 'role', 'user'` - Filter to only user messages\n- `messages | reverse` - Reverse the order of messages", + "examples": [ + "{% if messages.last.content contains goodbye %}true{% else %}false{% endif %}", + "{% assign userMessages = messages | where: role, user %}{% if userMessages.size > 3 %}true{% else %}false{% endif %}" + ] } }, "required": [ "type", - "prompt" + "liquid" ] }, - "Edge": { + "GroupCondition": { "type": "object", "properties": { - "condition": { - "oneOf": [ - { - "$ref": "#/components/schemas/AIEdgeCondition", - "title": "AIEdgeCondition" - } - ] - }, - "from": { + "type": { "type": "string", - "maxLength": 80 + "description": "This is the type discriminator for group condition", + "example": "group", + "enum": [ + "group" + ] }, - "to": { + "operator": { "type": "string", - "maxLength": 80 + "description": "This is the logical operator for combining conditions in this group", + "examples": [ + "AND", + "OR" + ], + "enum": [ + "AND", + "OR" + ] }, - "metadata": { - "type": "object", - "description": "This is for metadata you want to store on the edge." + "conditions": { + "type": "array", + "description": "This is the list of nested conditions to evaluate.\nSupports recursive nesting of groups for complex logic.", + "examples": [ + "[{ type: \"regex\", regex: \"(?i)stop\", target: { role: \"user\" } }]", + "[{ type: \"group\", operator: \"AND\", conditions: [...] }]" + ], + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/RegexCondition", + "title": "RegexCondition" + }, + { + "$ref": "#/components/schemas/LiquidCondition", + "title": "LiquidCondition" + }, + { + "$ref": "#/components/schemas/GroupCondition", + "title": "GroupCondition", + "description": "This is the GroupCondition object but Swagger does not display nested schemas correctly." + } + ] + } } }, "required": [ - "from", - "to" + "type", + "operator", + "conditions" ] }, - "SecurityFilterBase": { - "type": "object", - "properties": {} - }, - "SecurityFilterPlan": { + "ToolRejectionPlan": { "type": "object", "properties": { - "enabled": { - "type": "boolean", - "description": "Whether the security filter is enabled.\n@default false", - "default": false - }, - "filters": { - "description": "Array of security filter types to apply.\nIf array is not empty, only those security filters are run.", - "example": "[{ type: \"sql-injection\" }, { type: \"xss\" }]", + "conditions": { "type": "array", + "description": "This is the list of conditions that must be evaluated.\n\nUsage:\n- If all conditions match (AND logic), the tool call is rejected.\n- For OR logic at the top level, use a single 'group' condition with operator: 'OR'.\n\n@default [] - Empty array means tool always executes", + "examples": [ + "[{ type: \"regex\", regex: \"(?i)\\\\b(cancel|stop)\\\\b\", target: { role: \"user\" } }]", + "[{ type: \"group\", operator: \"OR\", conditions: [...] }]" + ], "items": { - "$ref": "#/components/schemas/SecurityFilterBase" + "oneOf": [ + { + "$ref": "#/components/schemas/RegexCondition", + "title": "RegexCondition" + }, + { + "$ref": "#/components/schemas/LiquidCondition", + "title": "LiquidCondition" + }, + { + "$ref": "#/components/schemas/GroupCondition", + "title": "GroupCondition", + "description": "This is the GroupCondition object but Swagger does not display nested schemas correctly." + } + ] } - }, - "mode": { - "type": "string", - "description": "Mode of operation when a security threat is detected.\n- 'sanitize': Remove or replace the threatening content\n- 'reject': Replace the entire transcript with replacement text\n- 'replace': Replace threatening patterns with replacement text\n@default 'sanitize'", - "enum": [ - "sanitize", - "reject", - "replace" - ], - "default": "sanitize" - }, - "replacementText": { - "type": "string", - "description": "Text to use when replacing filtered content.\n@default '[FILTERED]'", - "default": "[FILTERED]" } } }, - "CompliancePlan": { + "CreateDtmfToolDTO": { "type": "object", "properties": { - "hipaaEnabled": { - "type": "boolean", - "description": "When this is enabled, no logs, recordings, or transcriptions will be stored.\nAt the end of the call, you will still receive an end-of-call-report message to store on your server. Defaults to false.", - "example": { - "hipaaEnabled": false + "messages": { + "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" + }, + { + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] } }, - "pciEnabled": { + "type": { + "type": "string", + "enum": [ + "dtmf" + ], + "description": "The type of tool. \"dtmf\" for DTMF tool." + }, + "sipInfoDtmfEnabled": { "type": "boolean", - "description": "When this is enabled, the user will be restricted to use PCI-compliant providers, and no logs or transcripts are stored.\nAt the end of the call, you will receive an end-of-call-report message to store on your server. Defaults to false.", - "example": { - "pciEnabled": false - } + "description": "This enables sending DTMF tones via SIP INFO messages instead of RFC 2833 (RTP events). When enabled, DTMF digits will be sent using the SIP INFO method, which can be more reliable in some network configurations. Only relevant when using the `vapi.sip` transport.", + "default": false }, - "securityFilterPlan": { - "description": "This is the security filter plan for the assistant. It allows filtering of transcripts for security threats before sending to LLM.", + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", "allOf": [ { - "$ref": "#/components/schemas/SecurityFilterPlan" + "$ref": "#/components/schemas/ToolRejectionPlan" } ] } - } + }, + "required": [ + "type" + ] }, - "StructuredDataPlan": { + "CreateEndCallToolDTO": { "type": "object", "properties": { "messages": { - "description": "These are the messages used to generate the structured data.\n\n@default: ```\n[\n {\n \"role\": \"system\",\n \"content\": \"You are an expert data extractor. You will be given a transcript of a call. Extract structured data per the JSON Schema. DO NOT return anything except the structured data.\\n\\nJson Schema:\\\\n{{schema}}\\n\\nOnly respond with the JSON.\"\n },\n {\n \"role\": \"user\",\n \"content\": \"Here is the transcript:\\n\\n{{transcript}}\\n\\n. Here is the ended reason of the call:\\n\\n{{endedReason}}\\n\\n\"\n }\n]```\n\nYou can customize by providing any messages you want.\n\nHere are the template variables available:\n- {{transcript}}: the transcript of the call from `call.artifact.transcript`- {{systemPrompt}}: the system prompt of the call from `assistant.model.messages[type=system].content`- {{messages}}: the messages of the call from `assistant.model.messages`- {{schema}}: the schema of the structured data from `structuredDataPlan.schema`- {{endedReason}}: the ended reason of the call from `call.endedReason`", "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", "items": { - "type": "object" + "oneOf": [ + { + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" + }, + { + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] } }, - "enabled": { - "type": "boolean", - "description": "This determines whether structured data is generated and stored in `call.analysis.structuredData`. Defaults to false.\n\nUsage:\n- If you want to extract structured data, set this to true and provide a `schema`.\n\n@default false" - }, - "schema": { - "description": "This is the schema of the structured data. The output is stored in `call.analysis.structuredData`.\n\nComplete guide on JSON Schema can be found [here](https://ajv.js.org/json-schema.html#json-data-type).", - "allOf": [ - { - "$ref": "#/components/schemas/JsonSchema" - } - ] - }, - "timeoutSeconds": { - "type": "number", - "description": "This is how long the request is tried before giving up. When request times out, `call.analysis.structuredData` will be empty.\n\nUsage:\n- To guarantee the structured data is generated, set this value high. Note, this will delay the end of call report in cases where model is slow to respond.\n\n@default 5 seconds", - "minimum": 1, - "maximum": 60 - } - } - }, - "StructuredDataMultiPlan": { - "type": "object", - "properties": { - "key": { + "type": { "type": "string", - "description": "This is the key of the structured data plan in the catalog." + "enum": [ + "endCall" + ], + "description": "The type of tool. \"endCall\" for End Call tool." }, - "plan": { - "description": "This is an individual structured data plan in the catalog.", + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", "allOf": [ { - "$ref": "#/components/schemas/StructuredDataPlan" + "$ref": "#/components/schemas/ToolRejectionPlan" } ] } }, "required": [ - "key", - "plan" + "type" ] }, - "SuccessEvaluationPlan": { + "CreateVoicemailToolDTO": { "type": "object", "properties": { - "rubric": { - "type": "string", - "enum": [ - "NumericScale", - "DescriptiveScale", - "Checklist", - "Matrix", - "PercentageScale", - "LikertScale", - "AutomaticRubric", - "PassFail" - ], - "description": "This enforces the rubric of the evaluation. The output is stored in `call.analysis.successEvaluation`.\n\nOptions include:\n- 'NumericScale': A scale of 1 to 10.\n- 'DescriptiveScale': A scale of Excellent, Good, Fair, Poor.\n- 'Checklist': A checklist of criteria and their status.\n- 'Matrix': A grid that evaluates multiple criteria across different performance levels.\n- 'PercentageScale': A scale of 0% to 100%.\n- 'LikertScale': A scale of Strongly Agree, Agree, Neutral, Disagree, Strongly Disagree.\n- 'AutomaticRubric': Automatically break down evaluation into several criteria, each with its own score.\n- 'PassFail': A simple 'true' if call passed, 'false' if not.\n\nDefault is 'PassFail'." - }, "messages": { - "description": "These are the messages used to generate the success evaluation.\n\n@default: ```\n[\n {\n \"role\": \"system\",\n \"content\": \"You are an expert call evaluator. You will be given a transcript of a call and the system prompt of the AI participant. Determine if the call was successful based on the objectives inferred from the system prompt. DO NOT return anything except the result.\\n\\nRubric:\\\\n{{rubric}}\\n\\nOnly respond with the result.\"\n },\n {\n \"role\": \"user\",\n \"content\": \"Here is the transcript:\\n\\n{{transcript}}\\n\\n\"\n },\n {\n \"role\": \"user\",\n \"content\": \"Here was the system prompt of the call:\\n\\n{{systemPrompt}}\\n\\n. Here is the ended reason of the call:\\n\\n{{endedReason}}\\n\\n\"\n }\n]```\n\nYou can customize by providing any messages you want.\n\nHere are the template variables available:\n- {{transcript}}: the transcript of the call from `call.artifact.transcript`- {{systemPrompt}}: the system prompt of the call from `assistant.model.messages[type=system].content`- {{messages}}: the messages of the call from `assistant.model.messages`- {{rubric}}: the rubric of the success evaluation from `successEvaluationPlan.rubric`- {{endedReason}}: the ended reason of the call from `call.endedReason`", "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", "items": { - "type": "object" + "oneOf": [ + { + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" + }, + { + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] } }, - "enabled": { + "type": { + "type": "string", + "description": "The type of tool. \"voicemail\" for Voicemail tool.", + "enum": [ + "voicemail" + ] + }, + "beepDetectionEnabled": { "type": "boolean", - "description": "This determines whether a success evaluation is generated and stored in `call.analysis.successEvaluation`. Defaults to true.\n\nUsage:\n- If you want to disable the success evaluation, set this to false.\n\n@default true" + "description": "This is the flag that enables beep detection for voicemail detection and applies only for twilio based calls.\n\n@default false", + "default": false, + "example": false }, - "timeoutSeconds": { - "type": "number", - "description": "This is how long the request is tried before giving up. When request times out, `call.analysis.successEvaluation` will be empty.\n\nUsage:\n- To guarantee the success evaluation is generated, set this value high. Note, this will delay the end of call report in cases where model is slow to respond.\n\n@default 5 seconds", - "minimum": 1, - "maximum": 60 + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "allOf": [ + { + "$ref": "#/components/schemas/ToolRejectionPlan" + } + ] } - } + }, + "required": [ + "type" + ] }, - "AnalysisPlan": { + "JsonSchema": { "type": "object", "properties": { - "minMessagesThreshold": { - "type": "number", - "description": "The minimum number of messages required to run the analysis plan.\nIf the number of messages is less than this, analysis will be skipped.\n@default 2", - "minimum": 0 + "type": { + "type": "string", + "description": "This is the type of output you'd like.\n\n`string`, `number`, `integer`, `boolean` are the primitive types and should be obvious.\n\n`array` and `object` are more interesting and quite powerful. They allow you to define nested structures.\n\nFor `array`, you can define the schema of the items in the array using the `items` property.\n\nFor `object`, you can define the properties of the object using the `properties` property.", + "enum": [ + "string", + "number", + "integer", + "boolean", + "array", + "object" + ] }, - "summaryPlan": { - "description": "This is the plan for generating the summary of the call. This outputs to `call.analysis.summary`.", + "items": { + "description": "This is required if the type is \"array\". This is the schema of the items in the array. This is a recursive reference to JsonSchema.", "allOf": [ { - "$ref": "#/components/schemas/SummaryPlan" + "$ref": "#/components/schemas/JsonSchema" } ] }, - "structuredDataPlan": { - "description": "This is the plan for generating the structured data from the call. This outputs to `call.analysis.structuredData`.", - "allOf": [ - { - "$ref": "#/components/schemas/StructuredDataPlan" - } + "properties": { + "type": "object", + "description": "This is required if the type is \"object\". This specifies the properties of the object. This is a map of property names to JsonSchema objects.", + "additionalProperties": { + "$ref": "#/components/schemas/JsonSchema" + } + }, + "description": { + "type": "string", + "description": "This is the description to help the model understand what it needs to output." + }, + "pattern": { + "type": "string", + "description": "This is the pattern of the string. This is a regex that will be used to validate the data in question. To use a common format, use the `format` property instead.\n\nOpenAI documentation: https://platform.openai.com/docs/guides/structured-outputs#supported-properties" + }, + "format": { + "type": "string", + "description": "This is the format of the string. To pass a regex, use the `pattern` property instead.\n\nOpenAI documentation: https://platform.openai.com/docs/guides/structured-outputs?api-mode=chat&type-restrictions=string-restrictions", + "enum": [ + "date-time", + "time", + "date", + "duration", + "email", + "hostname", + "ipv4", + "ipv6", + "uuid" ] }, - "structuredDataMultiPlan": { - "description": "This is an array of structured data plan catalogs. Each entry includes a `key` and a `plan` for generating the structured data from the call. This outputs to `call.analysis.structuredDataMulti`.", + "required": { + "description": "This is a list of properties that are required.\n\nThis only makes sense if the type is \"object\".", "type": "array", "items": { - "$ref": "#/components/schemas/StructuredDataMultiPlan" + "type": "string" } }, - "successEvaluationPlan": { - "description": "This is the plan for generating the success evaluation of the call. This outputs to `call.analysis.successEvaluation`.", - "allOf": [ - { - "$ref": "#/components/schemas/SuccessEvaluationPlan" - } - ] - }, - "outcomeIds": { - "description": "This is an array of outcome UUIDs to be calculated during analysis.\nThe outcomes will be calculated and stored in `call.analysis.outcomes`.", + "enum": { + "description": "This array specifies the allowed values that can be used to restrict the output of the model.", "type": "array", "items": { "type": "string" } - } - } - }, - "RegexOption": { - "type": "object", - "properties": { - "type": { - "type": "string", - "description": "This is the type of the regex option. Options are:\n- `ignore-case`: Ignores the case of the text being matched. Add\n- `whole-word`: Matches whole words only.\n- `multi-line`: Matches across multiple lines.", - "enum": [ - "ignore-case", - "whole-word", - "multi-line" - ] }, - "enabled": { - "type": "boolean", - "description": "This is whether to enable the option.\n\n@default false" + "title": { + "type": "string", + "description": "This is the title of the schema." } }, "required": [ - "type", - "enabled" + "type" ] }, - "AssistantCustomEndpointingRule": { + "VariableExtractionAlias": { "type": "object", "properties": { - "type": { + "key": { "type": "string", - "description": "This endpointing rule is based on the last assistant message before customer started speaking.\n\nFlow:\n- Assistant speaks\n- Customer starts speaking\n- Customer transcription comes in\n- This rule is evaluated on the last assistant message\n- If a match is found based on `regex`, the endpointing timeout is set to `timeoutSeconds`\n\nUsage:\n- If you have yes/no questions in your use case like \"are you interested in a loan?\", you can set a shorter timeout.\n- If you have questions where the customer may pause to look up information like \"what's my account number?\", you can set a longer timeout.", - "enum": [ - "assistant" - ] + "description": "This is the key of the variable.\n\nThis variable will be accessible during the call as `{{key}}` and stored in `call.artifact.variableValues` after the call.\n\nRules:\n- Must start with a letter (a-z, A-Z).\n- Subsequent characters can be letters, numbers, or underscores.\n- Minimum length of 1 and maximum length of 40.", + "minLength": 1, + "maxLength": 40, + "pattern": "/^[a-zA-Z][a-zA-Z0-9_]*$/" }, - "regex": { + "value": { "type": "string", - "description": "This is the regex pattern to match.\n\nNote:\n- This works by using the `RegExp.test` method in Node.JS. Eg. `/hello/.test(\"hello there\")` will return `true`.\n\nHot tip:\n- In JavaScript, escape `\\` when sending the regex pattern. Eg. `\"hello\\sthere\"` will be sent over the wire as `\"hellosthere\"`. Send `\"hello\\\\sthere\"` instead.\n- `RegExp.test` does substring matching, so `/cat/.test(\"I love cats\")` will return `true`. To do full string matching, send \"^cat$\"." - }, - "regexOptions": { - "description": "These are the options for the regex match. Defaults to all disabled.\n\n@default []", - "type": "array", - "items": { - "$ref": "#/components/schemas/RegexOption" - } - }, - "timeoutSeconds": { - "type": "number", - "description": "This is the endpointing timeout in seconds, if the rule is matched.", - "minimum": 0, - "maximum": 15 + "description": "This is the value of the variable.\n\nThis can reference existing variables, use filters, and perform transformations.\n\nExamples: \"{{name}}\", \"{{customer.email}}\", \"Hello {{name | upcase}}\"", + "maxLength": 10000 } }, "required": [ - "type", - "regex", - "timeoutSeconds" + "key", + "value" ] }, - "CustomerCustomEndpointingRule": { + "VariableExtractionPlan": { "type": "object", "properties": { - "type": { - "type": "string", - "description": "This endpointing rule is based on current customer message as they are speaking.\n\nFlow:\n- Assistant speaks\n- Customer starts speaking\n- Customer transcription comes in\n- This rule is evaluated on the current customer transcription\n- If a match is found based on `regex`, the endpointing timeout is set to `timeoutSeconds`\n\nUsage:\n- If you want to wait longer while customer is speaking numbers, you can set a longer timeout.", - "enum": [ - "customer" + "schema": { + "description": "This is the schema to extract.\n\nExamples:\n1. To extract object properties, you can use the following schema:\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n },\n \"age\": {\n \"type\": \"number\"\n }\n }\n}\n```\n\nThese will be extracted as `{{ name }}` and `{{ age }}` respectively. To emphasize, object properties are extracted as direct global variables.\n\n2. To extract nested properties, you can use the following schema:\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"object\",\n \"properties\": {\n \"first\": {\n \"type\": \"string\"\n },\n \"last\": {\n \"type\": \"string\"\n }\n }\n }\n }\n}\n```\n\nThese will be extracted as `{{ name }}`. And, `{{ name.first }}` and `{{ name.last }}` will be accessible.\n\n3. To extract array items, you can use the following schema:\n```json\n{\n \"type\": \"array\",\n \"title\": \"zipCodes\",\n \"items\": {\n \"type\": \"string\"\n }\n}\n```\n\nThis will be extracted as `{{ zipCodes }}`. To access the array items, you can use `{{ zipCodes[0] }}` and `{{ zipCodes[1] }}`.\n\n4. To extract array of objects, you can use the following schema:\n\n```json\n{\n \"type\": \"array\",\n \"name\": \"people\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n },\n \"age\": {\n \"type\": \"number\"\n },\n \"zipCodes\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n }\n }\n}\n```\n\nThis will be extracted as `{{ people }}`. To access the array items, you can use `{{ people[n].name }}`, `{{ people[n].age }}`, `{{ people[n].zipCodes }}`, `{{ people[n].zipCodes[0] }}` and `{{ people[n].zipCodes[1] }}`.", + "allOf": [ + { + "$ref": "#/components/schemas/JsonSchema" + } ] }, - "regex": { - "type": "string", - "description": "This is the regex pattern to match.\n\nNote:\n- This works by using the `RegExp.test` method in Node.JS. Eg. `/hello/.test(\"hello there\")` will return `true`.\n\nHot tip:\n- In JavaScript, escape `\\` when sending the regex pattern. Eg. `\"hello\\sthere\"` will be sent over the wire as `\"hellosthere\"`. Send `\"hello\\\\sthere\"` instead.\n- `RegExp.test` does substring matching, so `/cat/.test(\"I love cats\")` will return `true`. To do full string matching, send \"^cat$\"." - }, - "regexOptions": { - "description": "These are the options for the regex match. Defaults to all disabled.\n\n@default []", + "aliases": { + "description": "These are additional variables to create.\n\nThese will be accessible during the call as `{{key}}` and stored in `call.artifact.variableValues` after the call.\n\nExample:\n```json\n{\n \"aliases\": [\n {\n \"key\": \"customerName\",\n \"value\": \"{{name}}\"\n },\n {\n \"key\": \"fullName\",\n \"value\": \"{{firstName}} {{lastName}}\"\n },\n {\n \"key\": \"greeting\",\n \"value\": \"Hello {{name}}, welcome to {{company}}!\"\n },\n {\n \"key\": \"customerCity\",\n \"value\": \"{{addresses[0].city}}\"\n },\n {\n \"key\": \"something\",\n \"value\": \"{{any liquid}}\"\n }\n ]\n}\n```\n\nThis will create variables `customerName`, `fullName`, `greeting`, `customerCity`, and `something`. To access these variables, you can reference them as `{{customerName}}`, `{{fullName}}`, `{{greeting}}`, `{{customerCity}}`, and `{{something}}`.", "type": "array", "items": { - "$ref": "#/components/schemas/RegexOption" + "$ref": "#/components/schemas/VariableExtractionAlias" } + } + } + }, + "ToolParameter": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "This is the key of the parameter." }, - "timeoutSeconds": { - "type": "number", - "description": "This is the endpointing timeout in seconds, if the rule is matched.", - "minimum": 0, - "maximum": 15 + "value": { + "description": "The value of the parameter. Any JSON type. String values support Liquid templates.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "object" + }, + { + "type": "array" + } + ] } }, "required": [ - "type", - "regex", - "timeoutSeconds" + "key", + "value" ] }, - "BothCustomEndpointingRule": { + "OpenAIFunctionParameters": { "type": "object", "properties": { "type": { "type": "string", - "description": "This endpointing rule is based on both the last assistant message and the current customer message as they are speaking.\n\nFlow:\n- Assistant speaks\n- Customer starts speaking\n- Customer transcription comes in\n- This rule is evaluated on the last assistant message and the current customer transcription\n- If assistant message matches `assistantRegex` AND customer message matches `customerRegex`, the endpointing timeout is set to `timeoutSeconds`\n\nUsage:\n- If you want to wait longer while customer is speaking numbers, you can set a longer timeout.", + "description": "This must be set to 'object'. It instructs the model to return a JSON object containing the function call properties.", "enum": [ - "both" + "object" ] }, - "assistantRegex": { - "type": "string", - "description": "This is the regex pattern to match the assistant's message.\n\nNote:\n- This works by using the `RegExp.test` method in Node.JS. Eg. `/hello/.test(\"hello there\")` will return `true`.\n\nHot tip:\n- In JavaScript, escape `\\` when sending the regex pattern. Eg. `\"hello\\sthere\"` will be sent over the wire as `\"hellosthere\"`. Send `\"hello\\\\sthere\"` instead.\n- `RegExp.test` does substring matching, so `/cat/.test(\"I love cats\")` will return `true`. To do full string matching, send \"^cat$\"." - }, - "assistantRegexOptions": { - "description": "These are the options for the assistant's message regex match. Defaults to all disabled.\n\n@default []", - "type": "array", - "items": { - "$ref": "#/components/schemas/RegexOption" + "properties": { + "type": "object", + "description": "This provides a description of the properties required by the function.\nJSON Schema can be used to specify expectations for each property.\nRefer to [this doc](https://ajv.js.org/json-schema.html#json-data-type) for a comprehensive guide on JSON Schema.", + "additionalProperties": { + "$ref": "#/components/schemas/JsonSchema" } }, - "customerRegex": { - "type": "string" - }, - "customerRegexOptions": { - "description": "These are the options for the customer's message regex match. Defaults to all disabled.\n\n@default []", + "required": { + "description": "This specifies the properties that are required by the function.", "type": "array", "items": { - "$ref": "#/components/schemas/RegexOption" + "type": "string" } - }, - "timeoutSeconds": { - "type": "number", - "description": "This is the endpointing timeout in seconds, if the rule is matched.", - "minimum": 0, - "maximum": 15 } }, "required": [ "type", - "assistantRegex", - "customerRegex", - "timeoutSeconds" + "properties" ] }, - "VapiSmartEndpointingPlan": { + "OpenAIFunction": { "type": "object", "properties": { - "provider": { + "name": { "type": "string", - "description": "This is the provider for the smart endpointing plan.", - "enum": [ - "vapi", - "livekit", - "custom-endpointing-model" - ], + "description": "This is the the name of the function to be called.\n\nMust be a-z, A-Z, 0-9, or contain underscores and dashes, with a maximum length of 64.", + "maxLength": 64, + "pattern": "/^[a-zA-Z0-9_-]{1,64}$/" + }, + "strict": { + "type": "boolean", + "description": "This is a boolean that controls whether to enable strict schema adherence when generating the function call. If set to true, the model will follow the exact schema defined in the parameters field. Only a subset of JSON Schema is supported when strict is true. Learn more about Structured Outputs in the [OpenAI guide](https://openai.com/index/introducing-structured-outputs-in-the-api/).\n\n@default false", + "default": false + }, + "description": { + "type": "string", + "description": "This is the description of what the function does, used by the AI to choose when and how to call the function." + }, + "parameters": { + "description": "These are the parameters the functions accepts, described as a JSON Schema object.\n\nSee the [OpenAI guide](https://platform.openai.com/docs/guides/function-calling) for examples, and the [JSON Schema reference](https://json-schema.org/understanding-json-schema) for documentation about the format.\n\nOmitting parameters defines a function with an empty parameter list.", + "allOf": [ + { + "$ref": "#/components/schemas/OpenAIFunctionParameters" + } + ] + } + }, + "required": [ + "name" + ] + }, + "CreateFunctionToolDTO": { + "type": "object", + "properties": { + "messages": { + "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" + }, + { + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] + } + }, + "type": { + "type": "string", + "enum": [ + "function" + ], + "description": "The type of tool. \"function\" for Function tool." + }, + "async": { + "type": "boolean", + "example": false, + "description": "This determines if the tool is async.\n\n If async, the assistant will move forward without waiting for your server to respond. This is useful if you just want to trigger something on your server.\n\n If sync, the assistant will wait for your server to respond. This is useful if want assistant to respond with the result from your server.\n\n Defaults to synchronous (`false`)." + }, + "server": { + "description": "\n This is the server where a `tool-calls` webhook will be sent.\n\n Notes:\n - Webhook is sent to this server when a tool call is made.\n - Webhook contains the call, assistant, and phone number objects.\n - Webhook contains the variables set on the assistant.\n - Webhook is sent to the first available URL in this order: {{tool.server.url}}, {{assistant.server.url}}, {{phoneNumber.server.url}}, {{org.server.url}}.\n - Webhook expects a response with tool call result.", + "allOf": [ + { + "$ref": "#/components/schemas/Server" + } + ] + }, + "variableExtractionPlan": { + "description": "Plan to extract variables from the tool response", + "allOf": [ + { + "$ref": "#/components/schemas/VariableExtractionPlan" + } + ] + }, + "parameters": { + "description": "Static key-value pairs merged into the request body. Values support Liquid templates.", + "type": "array", + "items": { + "$ref": "#/components/schemas/ToolParameter" + } + }, + "function": { + "description": "This is the function definition of the tool.", + "allOf": [ + { + "$ref": "#/components/schemas/OpenAIFunction" + } + ] + }, + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "allOf": [ + { + "$ref": "#/components/schemas/ToolRejectionPlan" + } + ] + } + }, + "required": [ + "type" + ] + }, + "GhlToolMetadata": { + "type": "object", + "properties": { + "workflowId": { + "type": "string" + }, + "locationId": { + "type": "string" + } + } + }, + "CreateGhlToolDTO": { + "type": "object", + "properties": { + "messages": { + "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" + }, + { + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] + } + }, + "type": { + "type": "string", + "enum": [ + "ghl" + ], + "description": "The type of tool. \"ghl\" for GHL tool." + }, + "metadata": { + "$ref": "#/components/schemas/GhlToolMetadata" + }, + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "allOf": [ + { + "$ref": "#/components/schemas/ToolRejectionPlan" + } + ] + } + }, + "required": [ + "type", + "metadata" + ] + }, + "MakeToolMetadata": { + "type": "object", + "properties": { + "scenarioId": { + "type": "number" + }, + "triggerHookId": { + "type": "number" + } + } + }, + "CreateMakeToolDTO": { + "type": "object", + "properties": { + "messages": { + "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" + }, + { + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] + } + }, + "type": { + "type": "string", + "enum": [ + "make" + ], + "description": "The type of tool. \"make\" for Make tool." + }, + "metadata": { + "$ref": "#/components/schemas/MakeToolMetadata" + }, + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "allOf": [ + { + "$ref": "#/components/schemas/ToolRejectionPlan" + } + ] + } + }, + "required": [ + "type", + "metadata" + ] + }, + "CustomMessage": { + "type": "object", + "properties": { + "contents": { + "type": "array", + "description": "This is an alternative to the `content` property. It allows to specify variants of the same content, one per language.\n\nUsage:\n- If your assistants are multilingual, you can provide content for each language.\n- If you don't provide content for a language, the first item in the array will be automatically translated to the active language at that moment.\n\nThis will override the `content` property.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/TextContent", + "title": "Text" + } + ] + } + }, + "type": { + "type": "string", + "description": "This is a custom message.", + "enum": [ + "custom-message" + ] + }, + "content": { + "type": "string", + "description": "This is the content that the assistant will say when this message is triggered.", + "maxLength": 1000 + } + }, + "required": [ + "type" + ] + }, + "TransferDestinationAssistant": { + "type": "object", + "properties": { + "message": { + "description": "This is spoken to the customer before connecting them to the destination.\n\nUsage:\n- If this is not provided and transfer tool messages is not provided, default is \"Transferring the call now\".\n- If set to \"\", nothing is spoken. This is useful when you want to silently transfer. This is especially useful when transferring between assistants in a squad. In this scenario, you likely also want to set `assistant.firstMessageMode=assistant-speaks-first-with-model-generated-message` for the destination assistant.\n\nThis accepts a string or a ToolMessageStart class. Latter is useful if you want to specify multiple messages for different languages through the `contents` field.", + "oneOf": [ + { + "type": "string" + }, + { + "$ref": "#/components/schemas/CustomMessage" + } + ] + }, + "type": { + "type": "string", + "enum": [ + "assistant" + ] + }, + "transferMode": { + "type": "string", + "description": "This is the mode to use for the transfer. Defaults to `rolling-history`.\n\n- `rolling-history`: This is the default mode. It keeps the entire conversation history and appends the new assistant's system message on transfer.\n\n Example:\n\n Pre-transfer:\n system: assistant1 system message\n assistant: assistant1 first message\n user: hey, good morning\n assistant: how can i help?\n user: i need help with my account\n assistant: (destination.message)\n\n Post-transfer:\n system: assistant1 system message\n assistant: assistant1 first message\n user: hey, good morning\n assistant: how can i help?\n user: i need help with my account\n assistant: (destination.message)\n system: assistant2 system message\n assistant: assistant2 first message (or model generated if firstMessageMode is set to `assistant-speaks-first-with-model-generated-message`)\n\n- `swap-system-message-in-history`: This replaces the original system message with the new assistant's system message on transfer.\n\n Example:\n\n Pre-transfer:\n system: assistant1 system message\n assistant: assistant1 first message\n user: hey, good morning\n assistant: how can i help?\n user: i need help with my account\n assistant: (destination.message)\n\n Post-transfer:\n system: assistant2 system message\n assistant: assistant1 first message\n user: hey, good morning\n assistant: how can i help?\n user: i need help with my account\n assistant: (destination.message)\n assistant: assistant2 first message (or model generated if firstMessageMode is set to `assistant-speaks-first-with-model-generated-message`)\n\n- `delete-history`: This deletes the entire conversation history on transfer.\n\n Example:\n\n Pre-transfer:\n system: assistant1 system message\n assistant: assistant1 first message\n user: hey, good morning\n assistant: how can i help?\n user: i need help with my account\n assistant: (destination.message)\n\n Post-transfer:\n system: assistant2 system message\n assistant: assistant2 first message\n user: Yes, please\n assistant: how can i help?\n user: i need help with my account\n\n- `swap-system-message-in-history-and-remove-transfer-tool-messages`: This replaces the original system message with the new assistant's system message on transfer and removes transfer tool messages from conversation history sent to the LLM.\n\n Example:\n\n Pre-transfer:\n system: assistant1 system message\n assistant: assistant1 first message\n user: hey, good morning\n assistant: how can i help?\n user: i need help with my account\n transfer-tool\n transfer-tool-result\n assistant: (destination.message)\n\n Post-transfer:\n system: assistant2 system message\n assistant: assistant1 first message\n user: hey, good morning\n assistant: how can i help?\n user: i need help with my account\n assistant: (destination.message)\n assistant: assistant2 first message (or model generated if firstMessageMode is set to `assistant-speaks-first-with-model-generated-message`)\n\n@default 'rolling-history'", + "enum": [ + "rolling-history", + "swap-system-message-in-history", + "swap-system-message-in-history-and-remove-transfer-tool-messages", + "delete-history" + ] + }, + "assistantName": { + "type": "string", + "description": "This is the assistant to transfer the call to." + }, + "name": { + "type": "string", + "description": "This is the name of the transfer destination. This is just for your own reference.\n\nUsage:\n- Optional. Stored with the destination wherever it is supplied. For `number`\n and `sip` destinations it is also persisted on the transfer record in the\n call artifact after a transfer and displayed in the dashboard call log (on\n the transfer divider in the transcript view) alongside the destination.\n When omitted, everything behaves exactly as before.\n- Display-only. Unlike `description`, it is never included in prompts or tool\n descriptions and has no effect on model behavior or destination choice.", + "maxLength": 40 + }, + "description": { + "type": "string", + "description": "This is the description of the destination, used by the AI to choose when and how to transfer the call." + } + }, + "required": [ + "type", + "assistantName" + ] + }, + "TransferFallbackPlan": { + "type": "object", + "properties": { + "message": { + "description": "This is the message the assistant will deliver to the customer if the transfer fails.", + "oneOf": [ + { + "type": "string" + }, + { + "$ref": "#/components/schemas/CustomMessage" + } + ] + }, + "endCallEnabled": { + "type": "boolean", + "description": "This controls what happens after delivering the failure message to the customer.\n- true: End the call after delivering the failure message (default)\n- false: Keep the assistant on the call to continue handling the customer's request\n\n@default true", + "default": true + } + }, + "required": [ + "message" + ] + }, + "TransferAssistantModel": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "description": "The model provider for the transfer assistant", + "enum": [ + "openai", + "anthropic", + "google", + "custom-llm" + ] + }, + "model": { + "type": "string", + "description": "The model name - must be compatible with the selected provider", + "example": "gpt-4o" + }, + "messages": { + "type": "array", + "description": "These are the messages used to configure the transfer assistant.\n\n@default: ```\n[\n {\n role: 'system',\n content: 'You are a transfer assistant designed to facilitate call transfers. Your core responsibility is to manage the transfer process efficiently.\\n\\n## Core Responsibility\\n- Facilitate the transfer process by using transferSuccessful or transferCancel tools appropriately\\n\\n## When to Respond\\n- Answer questions about the transfer process or provide summaries when specifically asked by the operator\\n- Respond to direct questions about the current transfer situation\\n\\n## What to Avoid\\n- Do not discuss topics unrelated to the transfer\\n- Do not engage in general conversation\\n- Keep all interactions focused on facilitating the transfer\\n\\n## Transfer Tools\\n- Use transferSuccessful when the transfer should proceed\\n- Use transferCancel when the transfer cannot be completed\\n\\nStay focused on your core responsibility of facilitating transfers.'\n }\n]```\n\n**Default Behavior:** If you don't provide any messages or don't include a system message as the first message, the default system message above will be automatically added.\n\n**Override Default:** To replace the default system message, provide your own system message as the first message in the array.\n\n**Add Context:** You can provide additional messages (user, assistant, etc.) to add context while keeping the default system message, or combine them with your custom system message." + }, + "tools": { + "type": "array", + "description": "Tools available to the transfer assistant during warm-transfer-experimental.\n\n**Default Behavior:** The transfer assistant will ALWAYS have both `transferSuccessful` and `transferCancel` tools automatically added, regardless of what you provide here.\n\n**Default Tools:**\n- `transferSuccessful`: \"Call this function to confirm the transfer is successful and connect the customer. Use this when you detect a human has answered and is ready to take the call.\"\n- `transferCancel`: \"Call this function to cancel the transfer when no human answers or transfer should not proceed. Use this when you detect voicemail, busy signal, or no answer.\"\n\n**Customization:** You can override the default tools by providing `transferSuccessful` and/or `transferCancel` tools with custom `function` or `messages` configurations.\n\n**Additional Tools:** You can also provide other tools, but the two transfer tools will always be present and available to the assistant." + } + }, + "required": [ + "provider", + "model" + ] + }, + "RegexOption": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "This is the type of the regex option. Options are:\n- `ignore-case`: Ignores the case of the text being matched. Add\n- `whole-word`: Matches whole words only.\n- `multi-line`: Matches across multiple lines.", + "enum": [ + "ignore-case", + "whole-word", + "multi-line" + ] + }, + "enabled": { + "type": "boolean", + "description": "This is whether to enable the option.\n\n@default false" + } + }, + "required": [ + "type", + "enabled" + ] + }, + "AssistantCustomEndpointingRule": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "This endpointing rule is based on the last assistant message before customer started speaking.\n\nFlow:\n- Assistant speaks\n- Customer starts speaking\n- Customer transcription comes in\n- This rule is evaluated on the last assistant message\n- If a match is found based on `regex`, the endpointing timeout is set to `timeoutSeconds`\n\nUsage:\n- If you have yes/no questions in your use case like \"are you interested in a loan?\", you can set a shorter timeout.\n- If you have questions where the customer may pause to look up information like \"what's my account number?\", you can set a longer timeout.", + "enum": [ + "assistant" + ] + }, + "regex": { + "type": "string", + "description": "This is the regex pattern to match.\n\nNote:\n- This works by using the `RegExp.test` method in Node.JS. Eg. `/hello/.test(\"hello there\")` will return `true`.\n\nHot tip:\n- In JavaScript, escape `\\` when sending the regex pattern. Eg. `\"hello\\sthere\"` will be sent over the wire as `\"hellosthere\"`. Send `\"hello\\\\sthere\"` instead.\n- `RegExp.test` does substring matching, so `/cat/.test(\"I love cats\")` will return `true`. To do full string matching, send \"^cat$\"." + }, + "regexOptions": { + "description": "These are the options for the regex match. Defaults to all disabled.\n\n@default []", + "type": "array", + "items": { + "$ref": "#/components/schemas/RegexOption" + } + }, + "timeoutSeconds": { + "type": "number", + "description": "This is the endpointing timeout in seconds, if the rule is matched.", + "minimum": 0, + "maximum": 15 + } + }, + "required": [ + "type", + "regex", + "timeoutSeconds" + ] + }, + "CustomerCustomEndpointingRule": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "This endpointing rule is based on current customer message as they are speaking.\n\nFlow:\n- Assistant speaks\n- Customer starts speaking\n- Customer transcription comes in\n- This rule is evaluated on the current customer transcription\n- If a match is found based on `regex`, the endpointing timeout is set to `timeoutSeconds`\n\nUsage:\n- If you want to wait longer while customer is speaking numbers, you can set a longer timeout.", + "enum": [ + "customer" + ] + }, + "regex": { + "type": "string", + "description": "This is the regex pattern to match.\n\nNote:\n- This works by using the `RegExp.test` method in Node.JS. Eg. `/hello/.test(\"hello there\")` will return `true`.\n\nHot tip:\n- In JavaScript, escape `\\` when sending the regex pattern. Eg. `\"hello\\sthere\"` will be sent over the wire as `\"hellosthere\"`. Send `\"hello\\\\sthere\"` instead.\n- `RegExp.test` does substring matching, so `/cat/.test(\"I love cats\")` will return `true`. To do full string matching, send \"^cat$\"." + }, + "regexOptions": { + "description": "These are the options for the regex match. Defaults to all disabled.\n\n@default []", + "type": "array", + "items": { + "$ref": "#/components/schemas/RegexOption" + } + }, + "timeoutSeconds": { + "type": "number", + "description": "This is the endpointing timeout in seconds, if the rule is matched.", + "minimum": 0, + "maximum": 15 + } + }, + "required": [ + "type", + "regex", + "timeoutSeconds" + ] + }, + "BothCustomEndpointingRule": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "This endpointing rule is based on both the last assistant message and the current customer message as they are speaking.\n\nFlow:\n- Assistant speaks\n- Customer starts speaking\n- Customer transcription comes in\n- This rule is evaluated on the last assistant message and the current customer transcription\n- If assistant message matches `assistantRegex` AND customer message matches `customerRegex`, the endpointing timeout is set to `timeoutSeconds`\n\nUsage:\n- If you want to wait longer while customer is speaking numbers, you can set a longer timeout.", + "enum": [ + "both" + ] + }, + "assistantRegex": { + "type": "string", + "description": "This is the regex pattern to match the assistant's message.\n\nNote:\n- This works by using the `RegExp.test` method in Node.JS. Eg. `/hello/.test(\"hello there\")` will return `true`.\n\nHot tip:\n- In JavaScript, escape `\\` when sending the regex pattern. Eg. `\"hello\\sthere\"` will be sent over the wire as `\"hellosthere\"`. Send `\"hello\\\\sthere\"` instead.\n- `RegExp.test` does substring matching, so `/cat/.test(\"I love cats\")` will return `true`. To do full string matching, send \"^cat$\"." + }, + "assistantRegexOptions": { + "description": "These are the options for the assistant's message regex match. Defaults to all disabled.\n\n@default []", + "type": "array", + "items": { + "$ref": "#/components/schemas/RegexOption" + } + }, + "customerRegex": { + "type": "string" + }, + "customerRegexOptions": { + "description": "These are the options for the customer's message regex match. Defaults to all disabled.\n\n@default []", + "type": "array", + "items": { + "$ref": "#/components/schemas/RegexOption" + } + }, + "timeoutSeconds": { + "type": "number", + "description": "This is the endpointing timeout in seconds, if the rule is matched.", + "minimum": 0, + "maximum": 15 + } + }, + "required": [ + "type", + "assistantRegex", + "customerRegex", + "timeoutSeconds" + ] + }, + "VapiSmartEndpointingPlan": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "description": "This is the provider for the smart endpointing plan.", + "enum": [ + "vapi", + "livekit", + "custom-endpointing-model" + ], "example": "vapi" } }, @@ -16377,7 +17446,7 @@ ] }, "smartEndpointingPlan": { - "description": "This is the plan for smart endpointing. Pick between Vapi smart endpointing or LiveKit smart endpointing (or nothing). We strongly recommend using livekit endpointing when working in English. LiveKit endpointing is not supported in other languages, yet.\n\nIf this is set, it will override and take precedence over `transcriptionEndpointingPlan`.\nThis plan will still be overridden by any matching `customEndpointingRules`.", + "description": "This is the plan for smart endpointing. Pick between Vapi smart endpointing, LiveKit, or custom endpointing model (or nothing). We strongly recommend using livekit endpointing when working in English. LiveKit endpointing is not supported in other languages, yet.\n\nIf this is set, it will override and take precedence over `transcriptionEndpointingPlan`.\nThis plan will still be overridden by any matching `customEndpointingRules`.\n\nIf this is not set, the system will automatically use the transcriber's built-in endpointing capabilities if available.", "oneOf": [ { "$ref": "#/components/schemas/VapiSmartEndpointingPlan", @@ -16414,7 +17483,7 @@ } }, "transcriptionEndpointingPlan": { - "description": "This determines how a customer speech is considered done (endpointing) using the transcription of customer's speech.\n\nOnce an endpoint is triggered, the request is sent to `assistant.model`.\n\nNote: This plan is only used if `smartEndpointingPlan` is not set. If both are provided, `smartEndpointingPlan` takes precedence.\nThis plan will also be overridden by any matching `customEndpointingRules`.", + "description": "This determines how a customer speech is considered done (endpointing) using the transcription of customer's speech.\n\nOnce an endpoint is triggered, the request is sent to `assistant.model`.\n\nNote: This plan is only used if `smartEndpointingPlan` is not set and transcriber does not have built-in endpointing capabilities. If both are provided, `smartEndpointingPlan` takes precedence.\nThis plan will also be overridden by any matching `customEndpointingRules`.", "allOf": [ { "$ref": "#/components/schemas/TranscriptionEndpointingPlan" @@ -16423,172 +17492,13 @@ } } }, - "StopSpeakingPlan": { - "type": "object", - "properties": { - "numWords": { - "type": "number", - "description": "This is the number of words that the customer has to say before the assistant will stop talking.\n\nWords like \"stop\", \"actually\", \"no\", etc. will always interrupt immediately regardless of this value.\n\nWords like \"okay\", \"yeah\", \"right\" will never interrupt.\n\nWhen set to 0, `voiceSeconds` is used in addition to the transcriptions to determine the customer has started speaking.\n\nDefaults to 0.\n\n@default 0", - "minimum": 0, - "maximum": 10, - "example": 0 - }, - "voiceSeconds": { - "type": "number", - "description": "This is the seconds customer has to speak before the assistant stops talking. This uses the VAD (Voice Activity Detection) spike to determine if the customer has started speaking.\n\nConsiderations:\n- A lower value might be more responsive but could potentially pick up non-speech sounds.\n- A higher value reduces false positives but might slightly delay the detection of speech onset.\n\nThis is only used if `numWords` is set to 0.\n\nDefaults to 0.2\n\n@default 0.2", - "minimum": 0, - "maximum": 0.5, - "example": 0.2 - }, - "backoffSeconds": { - "type": "number", - "description": "This is the seconds to wait before the assistant will start talking again after being interrupted.\n\nDefaults to 1.\n\n@default 1", - "minimum": 0, - "maximum": 10, - "example": 1 - }, - "acknowledgementPhrases": { - "description": "These are the phrases that will never interrupt the assistant, even if numWords threshold is met.\nThese are typically acknowledgement or backchanneling phrases.", - "example": [ - "i understand", - "i see", - "i got it", - "i hear you", - "im listening", - "im with you", - "right", - "okay", - "ok", - "sure", - "alright", - "got it", - "understood", - "yeah", - "yes", - "uh-huh", - "mm-hmm", - "gotcha", - "mhmm", - "ah", - "yeah okay", - "yeah sure" - ], - "default": [ - "i understand", - "i see", - "i got it", - "i hear you", - "im listening", - "im with you", - "right", - "okay", - "ok", - "sure", - "alright", - "got it", - "understood", - "yeah", - "yes", - "uh-huh", - "mm-hmm", - "gotcha", - "mhmm", - "ah", - "yeah okay", - "yeah sure" - ], - "type": "array", - "items": { - "type": "string", - "maxLength": 240 - } - }, - "interruptionPhrases": { - "description": "These are the phrases that will always interrupt the assistant immediately, regardless of numWords.\nThese are typically phrases indicating disagreement or desire to stop.", - "example": [ - "stop", - "shut", - "up", - "enough", - "quiet", - "silence", - "but", - "dont", - "not", - "no", - "hold", - "wait", - "cut", - "pause", - "nope", - "nah", - "nevermind", - "never", - "bad", - "actually" - ], - "default": [ - "stop", - "shut", - "up", - "enough", - "quiet", - "silence", - "but", - "dont", - "not", - "no", - "hold", - "wait", - "cut", - "pause", - "nope", - "nah", - "nevermind", - "never", - "bad", - "actually" - ], - "type": "array", - "items": { - "type": "string", - "maxLength": 240 - } - } - } - }, - "MonitorPlan": { - "type": "object", - "properties": { - "listenEnabled": { - "type": "boolean", - "description": "This determines whether the assistant's calls allow live listening. Defaults to true.\n\nFetch `call.monitor.listenUrl` to get the live listening URL.\n\n@default true", - "example": false - }, - "listenAuthenticationEnabled": { - "type": "boolean", - "description": "This enables authentication on the `call.monitor.listenUrl`.\n\nIf `listenAuthenticationEnabled` is `true`, the `call.monitor.listenUrl` will require an `Authorization: Bearer ` header.\n\n@default false", - "example": false - }, - "controlEnabled": { - "type": "boolean", - "description": "This determines whether the assistant's calls allow live control. Defaults to true.\n\nFetch `call.monitor.controlUrl` to get the live control URL.\n\nTo use, send any control message via a POST request to `call.monitor.controlUrl`. Here are the types of controls supported: https://docs.vapi.ai/api-reference/messages/client-inbound-message\n\n@default true", - "example": false - }, - "controlAuthenticationEnabled": { - "type": "boolean", - "description": "This enables authentication on the `call.monitor.controlUrl`.\n\nIf `controlAuthenticationEnabled` is `true`, the `call.monitor.controlUrl` will require an `Authorization: Bearer ` header.\n\n@default false", - "example": false - } - } - }, - "SmartDenoisingPlan": { + "SmartDenoisingPlan": { "type": "object", "properties": { "enabled": { "type": "boolean", "description": "Whether smart denoising using Krisp is enabled.", - "default": false + "default": true } } }, @@ -16661,120 +17571,26 @@ } } }, - "KeypadInputPlan": { + "TransferAssistant": { "type": "object", "properties": { - "enabled": { - "type": "boolean", - "description": "This keeps track of whether the user has enabled keypad input.\nBy default, it is off.\n\n@default false" - }, - "timeoutSeconds": { - "type": "number", - "description": "This is the time in seconds to wait before processing the input.\nIf the input is not received within this time, the input will be ignored.\nIf set to \"off\", the input will be processed when the user enters a delimiter or immediately if no delimiter is used.\n\n@default 2", - "minimum": 0, - "maximum": 10 - }, - "delimiters": { + "name": { "type": "string", - "description": "This is the delimiter(s) that will be used to process the input.\nCan be '#', '*', or an empty array.", - "enum": [ - "#", - "*", - "" - ] - } - } - }, - "WorkflowUserEditable": { - "type": "object", - "properties": { - "nodes": { - "type": "array", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ConversationNode", - "title": "ConversationNode" - }, - { - "$ref": "#/components/schemas/ToolNode", - "title": "ToolNode" - } - ] - } + "description": "Optional name for the transfer assistant", + "maxLength": 100, + "default": "transfer-assistant", + "example": "Sales Transfer Assistant" }, "model": { - "description": "This is the model for the workflow.\n\nThis can be overridden at node level using `nodes[n].model`.", - "oneOf": [ - { - "$ref": "#/components/schemas/WorkflowOpenAIModel", - "title": "WorkflowOpenAIModel" - }, - { - "$ref": "#/components/schemas/WorkflowAnthropicModel", - "title": "WorkflowAnthropicModel" - }, - { - "$ref": "#/components/schemas/WorkflowGoogleModel", - "title": "WorkflowGoogleModel" - }, - { - "$ref": "#/components/schemas/WorkflowCustomModel", - "title": "WorkflowCustomModel" - } - ] - }, - "transcriber": { - "description": "This is the transcriber for the workflow.\n\nThis can be overridden at node level using `nodes[n].transcriber`.", - "oneOf": [ - { - "$ref": "#/components/schemas/AssemblyAITranscriber", - "title": "AssemblyAITranscriber" - }, - { - "$ref": "#/components/schemas/AzureSpeechTranscriber", - "title": "AzureSpeechTranscriber" - }, - { - "$ref": "#/components/schemas/CustomTranscriber", - "title": "CustomTranscriber" - }, - { - "$ref": "#/components/schemas/DeepgramTranscriber", - "title": "DeepgramTranscriber" - }, - { - "$ref": "#/components/schemas/ElevenLabsTranscriber", - "title": "ElevenLabsTranscriber" - }, - { - "$ref": "#/components/schemas/GladiaTranscriber", - "title": "GladiaTranscriber" - }, - { - "$ref": "#/components/schemas/GoogleTranscriber", - "title": "GoogleTranscriber" - }, - { - "$ref": "#/components/schemas/SpeechmaticsTranscriber", - "title": "SpeechmaticsTranscriber" - }, - { - "$ref": "#/components/schemas/TalkscriberTranscriber", - "title": "TalkscriberTranscriber" - }, - { - "$ref": "#/components/schemas/OpenAITranscriber", - "title": "OpenAITranscriber" - }, + "description": "Model configuration for the transfer assistant", + "allOf": [ { - "$ref": "#/components/schemas/CartesiaTranscriber", - "title": "CartesiaTranscriber" + "$ref": "#/components/schemas/TransferAssistantModel" } ] }, "voice": { - "description": "This is the voice for the workflow.\n\nThis can be overridden at node level using `nodes[n].voice`.", + "description": "These are the options for the transfer assistant's voice.", "oneOf": [ { "$ref": "#/components/schemas/AzureVoice", @@ -16816,6 +17632,10 @@ "$ref": "#/components/schemas/PlayHTVoice", "title": "PlayHTVoice" }, + { + "$ref": "#/components/schemas/WellSaidVoice", + "title": "WellSaidVoice" + }, { "$ref": "#/components/schemas/RimeAIVoice", "title": "RimeAIVoice" @@ -16843,28 +17663,88 @@ { "$ref": "#/components/schemas/MinimaxVoice", "title": "MinimaxVoice" + }, + { + "$ref": "#/components/schemas/XaiVoice", + "title": "XaiVoice" + }, + { + "$ref": "#/components/schemas/MicrosoftVoice", + "title": "MicrosoftVoice" } ] }, - "observabilityPlan": { - "description": "This is the plan for observability of workflow's calls.\n\nCurrently, only Langfuse is supported.", + "transcriber": { + "description": "These are the options for the transfer assistant's transcriber.", "oneOf": [ { - "$ref": "#/components/schemas/LangfuseObservabilityPlan", - "title": "Langfuse" - } - ], - "allOf": [ + "$ref": "#/components/schemas/AssemblyAITranscriber", + "title": "AssemblyAITranscriber" + }, { - "$ref": "#/components/schemas/LangfuseObservabilityPlan" + "$ref": "#/components/schemas/AzureSpeechTranscriber", + "title": "AzureSpeechTranscriber" + }, + { + "$ref": "#/components/schemas/CustomTranscriber", + "title": "CustomTranscriber" + }, + { + "$ref": "#/components/schemas/DeepgramTranscriber", + "title": "DeepgramTranscriber" + }, + { + "$ref": "#/components/schemas/ElevenLabsTranscriber", + "title": "ElevenLabsTranscriber" + }, + { + "$ref": "#/components/schemas/GladiaTranscriber", + "title": "GladiaTranscriber" + }, + { + "$ref": "#/components/schemas/GoogleTranscriber", + "title": "GoogleTranscriber" + }, + { + "$ref": "#/components/schemas/SpeechmaticsTranscriber", + "title": "SpeechmaticsTranscriber" + }, + { + "$ref": "#/components/schemas/TalkscriberTranscriber", + "title": "TalkscriberTranscriber" + }, + { + "$ref": "#/components/schemas/OpenAITranscriber", + "title": "OpenAITranscriber" + }, + { + "$ref": "#/components/schemas/CartesiaTranscriber", + "title": "CartesiaTranscriber" + }, + { + "$ref": "#/components/schemas/SonioxTranscriber", + "title": "SonioxTranscriber" + }, + { + "$ref": "#/components/schemas/XaiTranscriber", + "title": "XaiTranscriber" + }, + { + "$ref": "#/components/schemas/VapiTranscriber", + "title": "VapiTranscriber" } ] }, + "firstMessage": { + "type": "string", + "description": "This is the first message that the transfer assistant will say.\nThis can also be a URL to a custom audio file.\n\nIf unspecified, assistant will wait for user to speak and use the model to respond once they speak.", + "example": "Hello! I understand you need to be transferred. Let me connect you." + }, "backgroundSound": { - "description": "This is the background sound in the call. Default for phone calls is 'office' and default for web calls is 'off'.\nYou can also provide a custom sound by providing a URL to an audio file.", + "description": "This is the background sound in the transfer assistant call. Default for phone calls is 'office' and default for web calls is 'off'.\nYou can also provide a custom sound by providing a URL to an audio file.", "oneOf": [ { - "type": "enum", + "type": "string", "enum": [ "off", "office" @@ -16878,10357 +17758,28200 @@ } ] }, - "hooks": { + "startSpeakingPlan": { + "description": "This is the plan for when the transfer assistant should start talking.\n\nYou should configure this if the transfer assistant needs different endpointing behavior than the base assistant.\n\nIf this is not set, the transfer assistant will inherit the start speaking plan from the base assistant.", + "allOf": [ + { + "$ref": "#/components/schemas/StartSpeakingPlan" + } + ] + }, + "firstMessageMode": { + "type": "string", + "description": "This is the mode for the first message. Default is 'assistant-speaks-first'.\n\nUse:\n- 'assistant-speaks-first' to have the assistant speak first.\n- 'assistant-waits-for-user' to have the assistant wait for the user to speak first.\n- 'assistant-speaks-first-with-model-generated-message' to have the assistant speak first with a message generated by the model based on the conversation state.\n\n@default 'assistant-speaks-first'", + "enum": [ + "assistant-speaks-first", + "assistant-speaks-first-with-model-generated-message", + "assistant-waits-for-user" + ], + "example": "assistant-speaks-first" + }, + "maxDurationSeconds": { + "type": "number", + "description": "This is the maximum duration in seconds for the transfer assistant conversation.\nAfter this time, the transfer will be cancelled automatically.\n@default 120", + "minimum": 10, + "maximum": 43200, + "example": 120 + }, + "backgroundSpeechDenoisingPlan": { + "description": "This enables filtering of noise and background speech while the user is talking.\n\nFeatures:\n- Smart denoising using Krisp\n- Fourier denoising\n\nSmart denoising can be combined with or used independently of Fourier denoising.\n\nOrder of precedence:\n- Smart denoising\n- Fourier denoising", + "allOf": [ + { + "$ref": "#/components/schemas/BackgroundSpeechDenoisingPlan" + } + ] + }, + "silenceTimeoutSeconds": { + "type": "number", + "description": "This is the number of seconds of silence to wait before ending the call. Defaults to 30.\n\n@default 30", + "minimum": 5, + "maximum": 3600 + } + }, + "required": [ + "model" + ] + }, + "TransferCancelToolUserEditable": { + "type": "object", + "properties": { + "messages": { "type": "array", - "description": "This is a set of actions that will be performed on certain events.", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", "items": { "oneOf": [ { - "$ref": "#/components/schemas/CallHookCallEnding", - "title": "CallHookCallEnding" + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" }, { - "$ref": "#/components/schemas/CallHookAssistantSpeechInterrupted", - "title": "CallHookAssistantSpeechInterrupted" + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" }, { - "$ref": "#/components/schemas/CallHookCustomerSpeechInterrupted", - "title": "CallHookCustomerSpeechInterrupted" + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" }, { - "$ref": "#/components/schemas/CallHookCustomerSpeechTimeout", - "title": "CallHookCustomerSpeechTimeout" + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" } ] } }, - "credentials": { + "type": { + "type": "string", + "enum": [ + "transferCancel" + ], + "description": "The type of tool. \"transferCancel\" for Transfer Cancel tool. This tool can only be used during warm-transfer-experimental by the transfer assistant to cancel an ongoing transfer and return the call back to the original assistant when the transfer cannot be completed." + }, + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "allOf": [ + { + "$ref": "#/components/schemas/ToolRejectionPlan" + } + ] + } + }, + "required": [ + "type" + ] + }, + "TransferSuccessfulToolUserEditable": { + "type": "object", + "properties": { + "messages": { "type": "array", - "description": "These are dynamic credentials that will be used for the workflow calls. By default, all the credentials are available for use in the call but you can supplement an additional credentials using this. Dynamic credentials override existing credentials.", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", "items": { "oneOf": [ { - "$ref": "#/components/schemas/CreateAnthropicCredentialDTO", - "title": "AnthropicCredential" - }, - { - "$ref": "#/components/schemas/CreateAnyscaleCredentialDTO", - "title": "AnyscaleCredential" - }, - { - "$ref": "#/components/schemas/CreateAssemblyAICredentialDTO", - "title": "AssemblyAICredential" - }, - { - "$ref": "#/components/schemas/CreateAzureCredentialDTO", - "title": "AzureCredential" - }, - { - "$ref": "#/components/schemas/CreateAzureOpenAICredentialDTO", - "title": "AzureOpenAICredential" - }, - { - "$ref": "#/components/schemas/CreateByoSipTrunkCredentialDTO", - "title": "ByoSipTrunkCredential" - }, - { - "$ref": "#/components/schemas/CreateCartesiaCredentialDTO", - "title": "CartesiaCredential" - }, - { - "$ref": "#/components/schemas/CreateCerebrasCredentialDTO", - "title": "CerebrasCredential" - }, - { - "$ref": "#/components/schemas/CreateCloudflareCredentialDTO", - "title": "CloudflareCredential" - }, - { - "$ref": "#/components/schemas/CreateCustomLLMCredentialDTO", - "title": "CustomLLMCredential" - }, - { - "$ref": "#/components/schemas/CreateDeepgramCredentialDTO", - "title": "DeepgramCredential" - }, - { - "$ref": "#/components/schemas/CreateDeepInfraCredentialDTO", - "title": "DeepInfraCredential" - }, - { - "$ref": "#/components/schemas/CreateDeepSeekCredentialDTO", - "title": "DeepSeekCredential" - }, - { - "$ref": "#/components/schemas/CreateElevenLabsCredentialDTO", - "title": "ElevenLabsCredential" - }, - { - "$ref": "#/components/schemas/CreateGcpCredentialDTO", - "title": "GcpCredential" - }, - { - "$ref": "#/components/schemas/CreateGladiaCredentialDTO", - "title": "GladiaCredential" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelCredentialDTO", - "title": "GhlCredential" - }, - { - "$ref": "#/components/schemas/CreateGoogleCredentialDTO", - "title": "GoogleCredential" - }, - { - "$ref": "#/components/schemas/CreateGroqCredentialDTO", - "title": "GroqCredential" + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" }, { - "$ref": "#/components/schemas/CreateHumeCredentialDTO", - "title": "HumeCredential" + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" }, { - "$ref": "#/components/schemas/CreateInflectionAICredentialDTO", - "title": "InflectionAICredential" + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" }, { - "$ref": "#/components/schemas/CreateLangfuseCredentialDTO", - "title": "LangfuseCredential" - }, - { - "$ref": "#/components/schemas/CreateLmntCredentialDTO", - "title": "LmntCredential" - }, - { - "$ref": "#/components/schemas/CreateMakeCredentialDTO", - "title": "MakeCredential" - }, - { - "$ref": "#/components/schemas/CreateMistralCredentialDTO", - "title": "MistralCredential" - }, - { - "$ref": "#/components/schemas/CreateNeuphonicCredentialDTO", - "title": "NeuphonicCredential" - }, - { - "$ref": "#/components/schemas/CreateOpenAICredentialDTO", - "title": "OpenAICredential" - }, - { - "$ref": "#/components/schemas/CreateOpenRouterCredentialDTO", - "title": "OpenRouterCredential" - }, - { - "$ref": "#/components/schemas/CreatePerplexityAICredentialDTO", - "title": "PerplexityAICredential" - }, - { - "$ref": "#/components/schemas/CreatePlayHTCredentialDTO", - "title": "PlayHTCredential" - }, - { - "$ref": "#/components/schemas/CreateRimeAICredentialDTO", - "title": "RimeAICredential" - }, - { - "$ref": "#/components/schemas/CreateRunpodCredentialDTO", - "title": "RunpodCredential" - }, - { - "$ref": "#/components/schemas/CreateS3CredentialDTO", - "title": "S3Credential" - }, - { - "$ref": "#/components/schemas/CreateSmallestAICredentialDTO", - "title": "SmallestAICredential" - }, - { - "$ref": "#/components/schemas/CreateSpeechmaticsCredentialDTO", - "title": "SpeechmaticsCredential" - }, - { - "$ref": "#/components/schemas/CreateSupabaseCredentialDTO", - "title": "SupabaseCredential" - }, - { - "$ref": "#/components/schemas/CreateTavusCredentialDTO", - "title": "TavusCredential" - }, - { - "$ref": "#/components/schemas/CreateTogetherAICredentialDTO", - "title": "TogetherAICredential" - }, - { - "$ref": "#/components/schemas/CreateTrieveCredentialDTO", - "title": "TrieveCredential" - }, - { - "$ref": "#/components/schemas/CreateTwilioCredentialDTO", - "title": "TwilioCredential" - }, - { - "$ref": "#/components/schemas/CreateVonageCredentialDTO", - "title": "VonageCredential" - }, - { - "$ref": "#/components/schemas/CreateWebhookCredentialDTO", - "title": "WebhookCredential" - }, - { - "$ref": "#/components/schemas/CreateXAiCredentialDTO", - "title": "XAiCredential" - }, - { - "$ref": "#/components/schemas/CreateGoogleCalendarOAuth2ClientCredentialDTO", - "title": "GoogleCalendarOAuth2ClientCredential" - }, - { - "$ref": "#/components/schemas/CreateGoogleCalendarOAuth2AuthorizationCredentialDTO", - "title": "GoogleCalendarOAuth2AuthorizationCredential" - }, - { - "$ref": "#/components/schemas/CreateGoogleSheetsOAuth2AuthorizationCredentialDTO", - "title": "GoogleSheetsOAuth2AuthorizationCredential" - }, - { - "$ref": "#/components/schemas/CreateSlackOAuth2AuthorizationCredentialDTO", - "title": "SlackOAuth2AuthorizationCredential" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelMCPCredentialDTO", - "title": "GoHighLevelMCPCredential" - }, - { - "$ref": "#/components/schemas/CreateInworldCredentialDTO", - "title": "InworldCredential" - } - ], - "discriminator": { - "propertyName": "provider", - "mapping": { - "11labs": "#/components/schemas/CreateElevenLabsCredentialDTO", - "anthropic": "#/components/schemas/CreateAnthropicCredentialDTO", - "anyscale": "#/components/schemas/CreateAnyscaleCredentialDTO", - "assembly-ai": "#/components/schemas/CreateAssemblyAICredentialDTO", - "azure-openai": "#/components/schemas/CreateAzureOpenAICredentialDTO", - "azure": "#/components/schemas/CreateAzureCredentialDTO", - "byo-sip-trunk": "#/components/schemas/CreateByoSipTrunkCredentialDTO", - "cartesia": "#/components/schemas/CreateCartesiaCredentialDTO", - "cerebras": "#/components/schemas/CreateCerebrasCredentialDTO", - "cloudflare": "#/components/schemas/CreateCloudflareCredentialDTO", - "custom-llm": "#/components/schemas/CreateCustomLLMCredentialDTO", - "deepgram": "#/components/schemas/CreateDeepgramCredentialDTO", - "deepinfra": "#/components/schemas/CreateDeepInfraCredentialDTO", - "deep-seek": "#/components/schemas/CreateDeepSeekCredentialDTO", - "gcp": "#/components/schemas/CreateGcpCredentialDTO", - "gladia": "#/components/schemas/CreateGladiaCredentialDTO", - "gohighlevel": "#/components/schemas/CreateGoHighLevelCredentialDTO", - "google": "#/components/schemas/CreateGoogleCredentialDTO", - "groq": "#/components/schemas/CreateGroqCredentialDTO", - "inflection-ai": "#/components/schemas/CreateInflectionAICredentialDTO", - "langfuse": "#/components/schemas/CreateLangfuseCredentialDTO", - "lmnt": "#/components/schemas/CreateLmntCredentialDTO", - "make": "#/components/schemas/CreateMakeCredentialDTO", - "openai": "#/components/schemas/CreateOpenAICredentialDTO", - "openrouter": "#/components/schemas/CreateOpenRouterCredentialDTO", - "perplexity-ai": "#/components/schemas/CreatePerplexityAICredentialDTO", - "playht": "#/components/schemas/CreatePlayHTCredentialDTO", - "rime-ai": "#/components/schemas/CreateRimeAICredentialDTO", - "runpod": "#/components/schemas/CreateRunpodCredentialDTO", - "s3": "#/components/schemas/CreateS3CredentialDTO", - "supabase": "#/components/schemas/CreateSupabaseCredentialDTO", - "smallest-ai": "#/components/schemas/CreateSmallestAICredentialDTO", - "tavus": "#/components/schemas/CreateTavusCredentialDTO", - "together-ai": "#/components/schemas/CreateTogetherAICredentialDTO", - "twilio": "#/components/schemas/CreateTwilioCredentialDTO", - "vonage": "#/components/schemas/CreateVonageCredentialDTO", - "webhook": "#/components/schemas/CreateWebhookCredentialDTO", - "xai": "#/components/schemas/CreateXAiCredentialDTO", - "neuphonic": "#/components/schemas/CreateNeuphonicCredentialDTO", - "hume": "#/components/schemas/CreateHumeCredentialDTO", - "mistral": "#/components/schemas/CreateMistralCredentialDTO", - "speechmatics": "#/components/schemas/CreateSpeechmaticsCredentialDTO", - "trieve": "#/components/schemas/CreateTrieveCredentialDTO", - "google.calendar.oauth2-client": "#/components/schemas/CreateGoogleCalendarOAuth2ClientCredentialDTO", - "google.calendar.oauth2-authorization": "#/components/schemas/CreateGoogleCalendarOAuth2AuthorizationCredentialDTO", - "google.sheets.oauth2-authorization": "#/components/schemas/CreateGoogleSheetsOAuth2AuthorizationCredentialDTO", - "slack.oauth2-authorization": "#/components/schemas/CreateSlackOAuth2AuthorizationCredentialDTO", - "ghl.oauth2-authorization": "#/components/schemas/CreateGoHighLevelMCPCredentialDTO", - "inworld": "#/components/schemas/CreateInworldCredentialDTO", - "minimax": "#/components/schemas/CreateMinimaxCredentialDTO" + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" } - } + ] } }, - "name": { + "type": { "type": "string", - "maxLength": 80 + "enum": [ + "transferSuccessful" + ], + "description": "The type of tool. \"transferSuccessful\" for Transfer Successful tool. This tool can only be used during warm-transfer-experimental by the transfer assistant to confirm that the transfer should proceed and finalize the handoff to the destination." }, - "edges": { + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "allOf": [ + { + "$ref": "#/components/schemas/ToolRejectionPlan" + } + ] + } + }, + "required": [ + "type" + ] + }, + "SummaryPlan": { + "type": "object", + "properties": { + "messages": { + "description": "These are the messages used to generate the summary.\n\n@default: ```\n[\n {\n \"role\": \"system\",\n \"content\": \"You are an expert note-taker. You will be given a transcript of a call. Summarize the call in 2-3 sentences. DO NOT return anything except the summary.\"\n },\n {\n \"role\": \"user\",\n \"content\": \"Here is the transcript:\\n\\n{{transcript}}\\n\\n. Here is the ended reason of the call:\\n\\n{{endedReason}}\\n\\n\"\n }\n]```\n\nYou can customize by providing any messages you want.\n\nHere are the template variables available:\n- {{transcript}}: The transcript of the call from `call.artifact.transcript` \n- {{systemPrompt}}: The system prompt of the call from `assistant.model.messages[type=system].content` \n- {{messages}}: The messages of the call from `assistant.model.messages` \n- {{endedReason}}: The ended reason of the call from `call.endedReason`", "type": "array", "items": { - "$ref": "#/components/schemas/Edge" + "type": "object" } }, - "globalPrompt": { + "enabled": { + "type": "boolean", + "description": "This determines whether a summary is generated and stored in `call.analysis.summary`. Defaults to true.\n\nUsage:\n- If you want to disable the summary, set this to false.\n\n@default true" + }, + "timeoutSeconds": { + "type": "number", + "description": "This is how long the request is tried before giving up. When request times out, `call.analysis.summary` will be empty.\n\nUsage:\n- To guarantee the summary is generated, set this value high. Note, this will delay the end of call report in cases where model is slow to respond.\n\n@default 5 seconds", + "minimum": 1, + "maximum": 60 + } + } + }, + "TransferPlan": { + "type": "object", + "properties": { + "mode": { "type": "string", - "maxLength": 5000 + "description": "This configures how transfer is executed and the experience of the destination party receiving the call.\n\nUsage:\n- `blind-transfer`: The assistant forwards the call to the destination without any message or summary.\n- `blind-transfer-add-summary-to-sip-header`: The assistant forwards the call to the destination and adds a SIP header X-Transfer-Summary to the call to include the summary.\n- `warm-transfer-say-message`: The assistant dials the destination, delivers the `message` to the destination party, connects the customer, and leaves the call.\n- `warm-transfer-say-summary`: The assistant dials the destination, provides a summary of the call to the destination party, connects the customer, and leaves the call.\n- `warm-transfer-wait-for-operator-to-speak-first-and-then-say-message`: The assistant dials the destination, waits for the operator to speak, delivers the `message` to the destination party, and then connects the customer.\n- `warm-transfer-wait-for-operator-to-speak-first-and-then-say-summary`: The assistant dials the destination, waits for the operator to speak, provides a summary of the call to the destination party, and then connects the customer.\n- `warm-transfer-twiml`: The assistant dials the destination, executes the twiml instructions on the destination call leg, connects the customer, and leaves the call.\n- `warm-transfer-experimental`: The assistant puts the customer on hold, dials the destination, and if the destination answers (and is human), delivers a message or summary before connecting the customer. If the destination is unreachable or not human (e.g., with voicemail detection), the assistant delivers the `fallbackMessage` to the customer and optionally ends the call.\n\n@default 'blind-transfer'", + "enum": [ + "blind-transfer", + "blind-transfer-add-summary-to-sip-header", + "warm-transfer-say-message", + "warm-transfer-say-summary", + "warm-transfer-twiml", + "warm-transfer-wait-for-operator-to-speak-first-and-then-say-message", + "warm-transfer-wait-for-operator-to-speak-first-and-then-say-summary", + "warm-transfer-experimental" + ] }, - "server": { - "description": "This is where Vapi will send webhooks. You can find all webhooks available along with their shape in ServerMessage schema.\n\nThe order of precedence is:\n\n1. tool.server\n2. workflow.server / assistant.server\n3. phoneNumber.server\n4. org.server", - "allOf": [ + "message": { + "description": "This is the message the assistant will deliver to the destination party before connecting the customer.\n\nUsage:\n- Used only when `mode` is `blind-transfer-add-summary-to-sip-header`, `warm-transfer-say-message`, `warm-transfer-wait-for-operator-to-speak-first-and-then-say-message`, or `warm-transfer-experimental`.", + "oneOf": [ { - "$ref": "#/components/schemas/Server" + "type": "string" + }, + { + "$ref": "#/components/schemas/CustomMessage" } ] }, - "compliancePlan": { - "description": "This is the compliance plan for the workflow. It allows you to configure HIPAA and other compliance settings.", - "allOf": [ - { - "$ref": "#/components/schemas/CompliancePlan" - } + "timeout": { + "type": "number", + "description": "This is the timeout in seconds for the warm-transfer-wait-for-operator-to-speak-first-and-then-say-message/summary\n\n@default 60", + "minimum": 1, + "maximum": 600, + "default": 60 + }, + "sipVerb": { + "type": "object", + "description": "This specifies the SIP verb to use while transferring the call.\n- 'refer': Uses SIP REFER to transfer the call (default)\n- 'bye': Ends current call with SIP BYE\n- 'dial': Uses SIP DIAL to transfer the call", + "default": "refer", + "enum": [ + "refer", + "bye", + "dial" ] }, - "analysisPlan": { - "description": "This is the plan for analysis of workflow's calls. Stored in `call.analysis`.", - "allOf": [ + "dialTimeout": { + "type": "number", + "description": "This sets the timeout for the dial operation in seconds. This is the duration the call will ring before timing out.\n\nOnly applicable when `sipVerb='dial'`. Not applicable for SIP REFER or BYE.\n\n@default 60", + "minimum": 1, + "maximum": 600, + "default": 60 + }, + "holdAudioUrl": { + "type": "string", + "description": "This is the URL to an audio file played while the customer is on hold during transfer.\n\nUsage:\n- Used only when `mode` is `warm-transfer-experimental`.\n- Used when transferring calls to play hold audio for the customer.\n- Must be a publicly accessible URL to an audio file.\n- Supported formats: MP3 and WAV.\n- If not provided, the default hold audio will be used." + }, + "transferCompleteAudioUrl": { + "type": "string", + "description": "This is the URL to an audio file played after the warm transfer message or summary is delivered to the destination party.\nIt can be used to play a custom sound like 'beep' to notify that the transfer is complete.\n\nUsage:\n- Used only when `mode` is `warm-transfer-experimental`.\n- Used when transferring calls to play hold audio for the destination party.\n- Must be a publicly accessible URL to an audio file.\n- Supported formats: MP3 and WAV." + }, + "contextEngineeringPlan": { + "description": "This is the plan for manipulating the message context before initiating the warm transfer.\nUsage:\n- Used only when `mode` is `warm-transfer-experimental`.\n- These messages will automatically be added to the transferAssistant's system message.\n- If 'none', we will not add any transcript to the transferAssistant's system message.\n- If you want to provide your own messages, use transferAssistant.model.messages instead.\n\n@default { type: 'all' }", + "oneOf": [ { - "$ref": "#/components/schemas/AnalysisPlan" + "$ref": "#/components/schemas/ContextEngineeringPlanLastNMessages", + "title": "Last N Messages" + }, + { + "$ref": "#/components/schemas/ContextEngineeringPlanNone", + "title": "None" + }, + { + "$ref": "#/components/schemas/ContextEngineeringPlanAll", + "title": "All" } ] }, - "artifactPlan": { - "description": "This is the plan for artifacts generated during workflow's calls. Stored in `call.artifact`.", + "twiml": { + "type": "string", + "description": "This is the TwiML instructions to execute on the destination call leg before connecting the customer.\n\nUsage:\n- Used only when `mode` is `warm-transfer-twiml`.\n- Supports only `Play`, `Say`, `Gather`, `Hangup` and `Pause` verbs.\n- Maximum length is 4096 characters.\n\nExample:\n```\nHello, transferring a customer to you.\n\nThey called about billing questions.\n```", + "maxLength": 4096 + }, + "summaryPlan": { + "description": "This is the plan for generating a summary of the call to present to the destination party.\n\nUsage:\n- Used only when `mode` is `blind-transfer-add-summary-to-sip-header` or `warm-transfer-say-summary` or `warm-transfer-wait-for-operator-to-speak-first-and-then-say-summary` or `warm-transfer-experimental`.", "allOf": [ { - "$ref": "#/components/schemas/ArtifactPlan" + "$ref": "#/components/schemas/SummaryPlan" } ] }, - "startSpeakingPlan": { - "description": "This is the plan for when the workflow nodes should start talking.\n\nYou should configure this if you're running into these issues:\n- The assistant is too slow to start talking after the customer is done speaking.\n- The assistant is too fast to start talking after the customer is done speaking.\n- The assistant is so fast that it's actually interrupting the customer.", + "sipHeadersInReferToEnabled": { + "type": "boolean", + "description": "This flag includes the sipHeaders from above in the refer to sip uri as url encoded query params.\n\n@default false" + }, + "fallbackPlan": { + "description": "This configures the fallback plan when the transfer fails (destination unreachable, busy, or not human).\n\nUsage:\n- Used when `mode` is `warm-transfer-experimental`. If not provided, a default message will be used.\n- Used for SIP cold transfers (`blind-transfer` modes) when transfer outcome detection and fallback\n are enabled for the organization: on a failed transfer, the assistant speaks `message`, then ends\n the call or continues with the customer per `endCallEnabled`.", "allOf": [ { - "$ref": "#/components/schemas/StartSpeakingPlan" + "$ref": "#/components/schemas/TransferFallbackPlan" } ] - }, - "stopSpeakingPlan": { - "description": "This is the plan for when workflow nodes should stop talking on customer interruption.\n\nYou should configure this if you're running into these issues:\n- The assistant is too slow to recognize customer's interruption.\n- The assistant is too fast to recognize customer's interruption.\n- The assistant is getting interrupted by phrases that are just acknowledgments.\n- The assistant is getting interrupted by background noises.\n- The assistant is not properly stopping -- it starts talking right after getting interrupted.", - "allOf": [ + } + }, + "required": [ + "mode" + ] + }, + "TransferDestinationNumber": { + "type": "object", + "properties": { + "message": { + "description": "This is spoken to the customer before connecting them to the destination.\n\nUsage:\n- If this is not provided and transfer tool messages is not provided, default is \"Transferring the call now\".\n- If set to \"\", nothing is spoken. This is useful when you want to silently transfer. This is especially useful when transferring between assistants in a squad. In this scenario, you likely also want to set `assistant.firstMessageMode=assistant-speaks-first-with-model-generated-message` for the destination assistant.\n\nThis accepts a string or a ToolMessageStart class. Latter is useful if you want to specify multiple messages for different languages through the `contents` field.", + "oneOf": [ { - "$ref": "#/components/schemas/StopSpeakingPlan" + "type": "string" + }, + { + "$ref": "#/components/schemas/CustomMessage" } ] }, - "monitorPlan": { - "description": "This is the plan for real-time monitoring of the workflow's calls.\n\nUsage:\n- To enable live listening of the workflow's calls, set `monitorPlan.listenEnabled` to `true`.\n- To enable live control of the workflow's calls, set `monitorPlan.controlEnabled` to `true`.", + "type": { + "type": "string", + "enum": [ + "number" + ] + }, + "numberE164CheckEnabled": { + "type": "boolean", + "description": "This is the flag to toggle the E164 check for the `number` field. This is an advanced property which should be used if you know your use case requires it.\n\nUse cases:\n- `false`: To allow non-E164 numbers like `+001234567890`, `1234`, or `abc`. This is useful for dialing out to non-E164 numbers on your SIP trunks.\n- `true` (default): To allow only E164 numbers like `+14155551234`. This is standard for PSTN calls.\n\nIf `false`, the `number` is still required to only contain alphanumeric characters (regex: `/^\\+?[a-zA-Z0-9]+$/`).\n\n@default true (E164 check is enabled)", + "default": true + }, + "number": { + "type": "string", + "description": "This is the phone number to transfer the call to.", + "minLength": 3, + "maxLength": 40 + }, + "extension": { + "type": "string", + "description": "This is the extension to dial after transferring the call to the `number`.", + "minLength": 1, + "maxLength": 10 + }, + "callerId": { + "type": "string", + "description": "This is the caller ID to use when transferring the call to the `number`.\n\nUsage:\n- If not provided, the caller ID will be the number the call is coming **from**.\n Example: a customer with number +14151111111 calls in to and the assistant transfers out to +16470000000. +16470000000 will see +14151111111 as the caller.\n For inbound calls, the caller ID is the customer's number. For outbound calls, the caller ID is the phone number of the assistant.\n- To change this behavior, provide a `callerId`.\n- Set to '{{customer.number}}' to always use the customer's number as the caller ID.\n- Set to '{{phoneNumber.number}}' to always use the phone number of the assistant as the caller ID.\n- Set to any E164 number to always use that number as the caller ID. This needs to be a number that is owned or verified by your Transport provider like Twilio.\n\nFor Twilio, you can read up more here: https://www.twilio.com/docs/voice/twiml/dial#callerid", + "maxLength": 40 + }, + "transferPlan": { + "description": "This configures how transfer is executed and the experience of the destination party receiving the call. Defaults to `blind-transfer`.\n\n@default `transferPlan.mode='blind-transfer'`", "allOf": [ { - "$ref": "#/components/schemas/MonitorPlan" + "$ref": "#/components/schemas/TransferPlan" } ] }, - "backgroundSpeechDenoisingPlan": { - "description": "This enables filtering of noise and background speech while the user is talking.\n\nFeatures:\n- Smart denoising using Krisp\n- Fourier denoising\n\nBoth can be used together. Order of precedence:\n- Smart denoising\n- Fourier denoising", - "allOf": [ + "name": { + "type": "string", + "description": "This is the name of the transfer destination. This is just for your own reference.\n\nUsage:\n- Optional. Stored with the destination wherever it is supplied. For `number`\n and `sip` destinations it is also persisted on the transfer record in the\n call artifact after a transfer and displayed in the dashboard call log (on\n the transfer divider in the transcript view) alongside the destination.\n When omitted, everything behaves exactly as before.\n- Display-only. Unlike `description`, it is never included in prompts or tool\n descriptions and has no effect on model behavior or destination choice.", + "maxLength": 40 + }, + "description": { + "type": "string", + "description": "This is the description of the destination, used by the AI to choose when and how to transfer the call." + } + }, + "required": [ + "type", + "number" + ] + }, + "TransferDestinationSip": { + "type": "object", + "properties": { + "message": { + "description": "This is spoken to the customer before connecting them to the destination.\n\nUsage:\n- If this is not provided and transfer tool messages is not provided, default is \"Transferring the call now\".\n- If set to \"\", nothing is spoken. This is useful when you want to silently transfer. This is especially useful when transferring between assistants in a squad. In this scenario, you likely also want to set `assistant.firstMessageMode=assistant-speaks-first-with-model-generated-message` for the destination assistant.\n\nThis accepts a string or a ToolMessageStart class. Latter is useful if you want to specify multiple messages for different languages through the `contents` field.", + "oneOf": [ { - "$ref": "#/components/schemas/BackgroundSpeechDenoisingPlan" + "type": "string" + }, + { + "$ref": "#/components/schemas/CustomMessage" } ] }, - "credentialIds": { - "description": "These are the credentials that will be used for the workflow calls. By default, all the credentials are available for use in the call but you can provide a subset using this.", - "type": "array", - "items": { - "type": "string" - } + "type": { + "type": "string", + "enum": [ + "sip" + ] }, - "keypadInputPlan": { - "description": "This is the plan for keypad input handling during workflow calls.", + "sipUri": { + "type": "string", + "description": "This is the SIP URI to transfer the call to." + }, + "callerId": { + "type": "string", + "description": "This is the caller ID to use when transferring the call to the `sipUri`.\n\nUsage:\n- If not provided, the caller ID will be determined by the SIP infrastructure.\n- Set to '{{customer.number}}' to always use the customer's number as the caller ID.\n- Set to '{{phoneNumber.number}}' to always use the phone number of the assistant as the caller ID.\n- Set to any E164 number to always use that number as the caller ID.\n\nOnly applicable when `transferPlan.sipVerb='dial'`. Not applicable for SIP REFER.", + "maxLength": 40 + }, + "transferPlan": { + "description": "This configures how transfer is executed and the experience of the destination party receiving the call. Defaults to `blind-transfer`.\n\n@default `transferPlan.mode='blind-transfer'`", "allOf": [ { - "$ref": "#/components/schemas/KeypadInputPlan" + "$ref": "#/components/schemas/TransferPlan" } ] + }, + "sipHeaders": { + "type": "object", + "description": "These are custom headers to be added to SIP refer during transfer call." + }, + "name": { + "type": "string", + "description": "This is the name of the transfer destination. This is just for your own reference.\n\nUsage:\n- Optional. Stored with the destination wherever it is supplied. For `number`\n and `sip` destinations it is also persisted on the transfer record in the\n call artifact after a transfer and displayed in the dashboard call log (on\n the transfer divider in the transcript view) alongside the destination.\n When omitted, everything behaves exactly as before.\n- Display-only. Unlike `description`, it is never included in prompts or tool\n descriptions and has no effect on model behavior or destination choice.", + "maxLength": 40 + }, + "description": { + "type": "string", + "description": "This is the description of the destination, used by the AI to choose when and how to transfer the call." } }, "required": [ - "nodes", - "name", - "edges" + "type", + "sipUri" ] }, - "VapiModel": { + "CreateTransferCallToolDTO": { "type": "object", "properties": { "messages": { - "description": "This is the starting state for the conversation.", - "type": "array", - "items": { - "$ref": "#/components/schemas/OpenAIMessage" - } - }, - "tools": { "type": "array", - "description": "These are the tools that the assistant can use during the call. To use existing tools, use `toolIds`.\n\nBoth `tools` and `toolIds` can be used together.", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", "items": { "oneOf": [ { - "$ref": "#/components/schemas/CreateApiRequestToolDTO", - "title": "ApiRequestTool" - }, - { - "$ref": "#/components/schemas/CreateBashToolDTO", - "title": "BashTool" - }, - { - "$ref": "#/components/schemas/CreateComputerToolDTO", - "title": "ComputerTool" - }, - { - "$ref": "#/components/schemas/CreateDtmfToolDTO", - "title": "DtmfTool" - }, - { - "$ref": "#/components/schemas/CreateEndCallToolDTO", - "title": "EndCallTool" - }, - { - "$ref": "#/components/schemas/CreateFunctionToolDTO", - "title": "FunctionTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelCalendarAvailabilityToolDTO", - "title": "GoHighLevelCalendarAvailabilityTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelCalendarEventCreateToolDTO", - "title": "GoHighLevelCalendarEventCreateTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelContactCreateToolDTO", - "title": "GoHighLevelContactCreateTool" + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" }, { - "$ref": "#/components/schemas/CreateGoHighLevelContactGetToolDTO", - "title": "GoHighLevelContactGetTool" + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" }, { - "$ref": "#/components/schemas/CreateGoogleCalendarCheckAvailabilityToolDTO", - "title": "GoogleCalendarCheckAvailabilityTool" + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" }, { - "$ref": "#/components/schemas/CreateGoogleCalendarCreateEventToolDTO", - "title": "GoogleCalendarCreateEventTool" - }, + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] + } + }, + "type": { + "type": "string", + "enum": [ + "transferCall" + ] + }, + "destinations": { + "type": "array", + "description": "These are the destinations that the call can be transferred to. If no destinations are provided, server.url will be used to get the transfer destination once the tool is called.", + "items": { + "oneOf": [ { - "$ref": "#/components/schemas/CreateGoogleSheetsRowAppendToolDTO", - "title": "GoogleSheetsRowAppendTool" + "$ref": "#/components/schemas/TransferDestinationAssistant", + "title": "Assistant" }, { - "$ref": "#/components/schemas/CreateHandoffToolDTO", - "title": "HandoffTool" + "$ref": "#/components/schemas/TransferDestinationNumber", + "title": "Number" }, { - "$ref": "#/components/schemas/CreateMcpToolDTO", - "title": "McpTool" - }, - { - "$ref": "#/components/schemas/CreateQueryToolDTO", - "title": "QueryTool" - }, - { - "$ref": "#/components/schemas/CreateSlackSendMessageToolDTO", - "title": "SlackSendMessageTool" - }, - { - "$ref": "#/components/schemas/CreateSmsToolDTO", - "title": "SmsTool" - }, - { - "$ref": "#/components/schemas/CreateTextEditorToolDTO", - "title": "TextEditorTool" - }, - { - "$ref": "#/components/schemas/CreateTransferCallToolDTO", - "title": "TransferCallTool" + "$ref": "#/components/schemas/TransferDestinationSip", + "title": "Sip" } ] } }, - "toolIds": { - "description": "These are the tools that the assistant can use during the call. To use transient tools, use `tools`.\n\nBoth `tools` and `toolIds` can be used together.", - "type": "array", - "items": { - "type": "string" - } - }, - "knowledgeBase": { - "description": "These are the options for the knowledge base.", - "oneOf": [ + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "allOf": [ { - "$ref": "#/components/schemas/CreateCustomKnowledgeBaseDTO", - "title": "Custom" + "$ref": "#/components/schemas/ToolRejectionPlan" } ] - }, - "knowledgeBaseId": { + } + }, + "required": [ + "type" + ] + }, + "ContextEngineeringPlanLastNMessages": { + "type": "object", + "properties": { + "type": { "type": "string", - "description": "This is the ID of the knowledge base the model will use." + "enum": [ + "lastNMessages" + ] }, - "provider": { + "maxMessages": { + "type": "number", + "description": "This is the maximum number of messages to include in the context engineering plan.", + "minimum": 0 + } + }, + "required": [ + "type", + "maxMessages" + ] + }, + "ContextEngineeringPlanNone": { + "type": "object", + "properties": { + "type": { "type": "string", "enum": [ - "vapi" + "none" + ] + } + }, + "required": [ + "type" + ] + }, + "ContextEngineeringPlanAll": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "all" + ] + } + }, + "required": [ + "type" + ] + }, + "ContextEngineeringPlanUserAndAssistantMessages": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "userAndAssistantMessages" + ] + } + }, + "required": [ + "type" + ] + }, + "ContextEngineeringPlanPreviousAssistantMessages": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "previousAssistantMessages" + ] + } + }, + "required": [ + "type" + ] + }, + "HandoffDestinationAssistant": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "assistant" ] }, - "workflowId": { + "contextEngineeringPlan": { + "description": "This is the plan for manipulating the message context before handing off the call to the next assistant.", + "oneOf": [ + { + "$ref": "#/components/schemas/ContextEngineeringPlanLastNMessages", + "title": "Last N Messages" + }, + { + "$ref": "#/components/schemas/ContextEngineeringPlanNone", + "title": "None" + }, + { + "$ref": "#/components/schemas/ContextEngineeringPlanAll", + "title": "All" + }, + { + "$ref": "#/components/schemas/ContextEngineeringPlanUserAndAssistantMessages", + "title": "User And Assistant Messages" + }, + { + "$ref": "#/components/schemas/ContextEngineeringPlanPreviousAssistantMessages", + "title": "Previous Assistant Messages" + } + ] + }, + "assistantName": { "type": "string", - "description": "This is the workflow that will be used for the call. To use a transient workflow, use `workflow` instead." + "description": "This is the assistant to transfer the call to. You must provide either assistantName or assistantId." }, - "workflow": { - "description": "This is the workflow that will be used for the call. To use an existing workflow, use `workflowId` instead.", + "assistantId": { + "type": "string", + "description": "This is the assistant id to transfer the call to. You must provide either assistantName or assistantId." + }, + "assistant": { + "description": "This is a transient assistant to transfer the call to. You may provide a transient assistant in the response `handoff-destination-request` in a dynamic handoff.", "allOf": [ { - "$ref": "#/components/schemas/WorkflowUserEditable" + "$ref": "#/components/schemas/CreateAssistantDTO" } ] }, - "model": { - "type": "string", - "description": "This is the name of the model. Ex. cognitivecomputations/dolphin-mixtral-8x7b" + "variableExtractionPlan": { + "description": "This is the variable extraction plan for the handoff tool.", + "allOf": [ + { + "$ref": "#/components/schemas/VariableExtractionPlan" + } + ] }, - "temperature": { - "type": "number", - "description": "This is the temperature that will be used for calls. Default is 0 to leverage caching for lower latency.", - "minimum": 0, - "maximum": 2 + "assistantOverrides": { + "description": "These are the assistant overrides to apply to the destination assistant.", + "allOf": [ + { + "$ref": "#/components/schemas/AssistantOverrides" + } + ] }, - "maxTokens": { - "type": "number", - "description": "This is the max number of tokens that the assistant will be allowed to generate in each turn of the conversation. Default is 250.", - "minimum": 50, - "maximum": 10000 + "description": { + "type": "string", + "description": "This is the description of the destination, used by the AI to choose when and how to transfer the call." + } + }, + "required": [ + "type" + ] + }, + "HandoffDestinationDynamic": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "dynamic" + ] }, - "emotionRecognitionEnabled": { - "type": "boolean", - "description": "This determines whether we detect user's emotion while they speak and send it as an additional info to model.\n\nDefault `false` because the model is usually are good at understanding the user's emotion from text.\n\n@default false" + "server": { + "description": "This is where Vapi will send the handoff-destination-request webhook in a dynamic handoff.\n\nThe order of precedence is:\n\n1. tool.server.url\n2. assistant.server.url\n3. phoneNumber.server.url\n4. org.server.url", + "allOf": [ + { + "$ref": "#/components/schemas/Server" + } + ] }, - "numFastTurns": { - "type": "number", - "description": "This sets how many turns at the start of the conversation to use a smaller, faster model from the same provider before switching to the primary model. Example, gpt-3.5-turbo if provider is openai.\n\nDefault is 0.\n\n@default 0", - "minimum": 0 + "description": { + "type": "string", + "description": "This is the description of the destination, used by the AI to choose when and how to transfer the call." } }, "required": [ - "provider", - "model" + "type" ] }, - "XaiModel": { + "SquadMemberDTO": { "type": "object", "properties": { - "messages": { - "description": "This is the starting state for the conversation.", - "type": "array", - "items": { - "$ref": "#/components/schemas/OpenAIMessage" - } + "assistantVersion": { + "type": "string", + "nullable": true, + "description": "This is the assistant version (e.g. `v3`) to pin for this squad member. When set, the call uses\nthe snapshot from `assistant_version` (by `(assistantId, version)`) instead of the latest. Valid\nonly with `assistantId`; rejected with inline `assistant`. Omit to follow the latest version." }, - "tools": { + "assistantDestinations": { "type": "array", - "description": "These are the tools that the assistant can use during the call. To use existing tools, use `toolIds`.\n\nBoth `tools` and `toolIds` can be used together.", "items": { "oneOf": [ { - "$ref": "#/components/schemas/CreateApiRequestToolDTO", - "title": "ApiRequestTool" - }, - { - "$ref": "#/components/schemas/CreateBashToolDTO", - "title": "BashTool" - }, - { - "$ref": "#/components/schemas/CreateComputerToolDTO", - "title": "ComputerTool" - }, - { - "$ref": "#/components/schemas/CreateDtmfToolDTO", - "title": "DtmfTool" - }, - { - "$ref": "#/components/schemas/CreateEndCallToolDTO", - "title": "EndCallTool" - }, - { - "$ref": "#/components/schemas/CreateFunctionToolDTO", - "title": "FunctionTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelCalendarAvailabilityToolDTO", - "title": "GoHighLevelCalendarAvailabilityTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelCalendarEventCreateToolDTO", - "title": "GoHighLevelCalendarEventCreateTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelContactCreateToolDTO", - "title": "GoHighLevelContactCreateTool" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelContactGetToolDTO", - "title": "GoHighLevelContactGetTool" - }, - { - "$ref": "#/components/schemas/CreateGoogleCalendarCheckAvailabilityToolDTO", - "title": "GoogleCalendarCheckAvailabilityTool" - }, - { - "$ref": "#/components/schemas/CreateGoogleCalendarCreateEventToolDTO", - "title": "GoogleCalendarCreateEventTool" - }, - { - "$ref": "#/components/schemas/CreateGoogleSheetsRowAppendToolDTO", - "title": "GoogleSheetsRowAppendTool" - }, - { - "$ref": "#/components/schemas/CreateHandoffToolDTO", - "title": "HandoffTool" - }, - { - "$ref": "#/components/schemas/CreateMcpToolDTO", - "title": "McpTool" - }, - { - "$ref": "#/components/schemas/CreateQueryToolDTO", - "title": "QueryTool" - }, - { - "$ref": "#/components/schemas/CreateSlackSendMessageToolDTO", - "title": "SlackSendMessageTool" - }, - { - "$ref": "#/components/schemas/CreateSmsToolDTO", - "title": "SmsTool" - }, - { - "$ref": "#/components/schemas/CreateTextEditorToolDTO", - "title": "TextEditorTool" + "$ref": "#/components/schemas/TransferDestinationAssistant", + "title": "Transfer Destination" }, { - "$ref": "#/components/schemas/CreateTransferCallToolDTO", - "title": "TransferCallTool" + "$ref": "#/components/schemas/HandoffDestinationAssistant", + "title": "Handoff Destination" } ] } }, - "toolIds": { - "description": "These are the tools that the assistant can use during the call. To use transient tools, use `tools`.\n\nBoth `tools` and `toolIds` can be used together.", - "type": "array", - "items": { - "type": "string" - } + "assistantId": { + "type": "string", + "nullable": true, + "description": "This is the assistant that will be used for the call. To use a transient assistant, use `assistant` instead." }, - "knowledgeBase": { - "description": "These are the options for the knowledge base.", - "oneOf": [ + "assistant": { + "description": "This is the assistant that will be used for the call. To use an existing assistant, use `assistantId` instead.", + "allOf": [ { - "$ref": "#/components/schemas/CreateCustomKnowledgeBaseDTO", - "title": "Custom" + "$ref": "#/components/schemas/CreateAssistantDTO" } ] }, - "knowledgeBaseId": { - "type": "string", - "description": "This is the ID of the knowledge base the model will use." - }, - "model": { - "type": "string", - "description": "This is the name of the model. Ex. cognitivecomputations/dolphin-mixtral-8x7b", - "enum": [ - "grok-beta", - "grok-2", - "grok-3" + "assistantOverrides": { + "description": "This can be used to override the assistant's settings and provide values for it's template variables.", + "allOf": [ + { + "$ref": "#/components/schemas/AssistantOverrides" + } ] - }, - "provider": { + } + } + }, + "CreateSquadDTO": { + "type": "object", + "properties": { + "name": { "type": "string", - "enum": [ - "xai" - ] - }, - "temperature": { - "type": "number", - "description": "This is the temperature that will be used for calls. Default is 0 to leverage caching for lower latency.", - "minimum": 0, - "maximum": 2 - }, - "maxTokens": { - "type": "number", - "description": "This is the max number of tokens that the assistant will be allowed to generate in each turn of the conversation. Default is 250.", - "minimum": 50, - "maximum": 10000 + "description": "This is the name of the squad." }, - "emotionRecognitionEnabled": { - "type": "boolean", - "description": "This determines whether we detect user's emotion while they speak and send it as an additional info to model.\n\nDefault `false` because the model is usually are good at understanding the user's emotion from text.\n\n@default false" + "members": { + "description": "This is the list of assistants that make up the squad.\n\nThe call will start with the first assistant in the list.", + "type": "array", + "items": { + "$ref": "#/components/schemas/SquadMemberDTO" + } }, - "numFastTurns": { - "type": "number", - "description": "This sets how many turns at the start of the conversation to use a smaller, faster model from the same provider before switching to the primary model. Example, gpt-3.5-turbo if provider is openai.\n\nDefault is 0.\n\n@default 0", - "minimum": 0 + "membersOverrides": { + "description": "This can be used to override all the assistants' settings and provide values for their template variables.\n\nBoth `membersOverrides` and `members[n].assistantOverrides` can be used together. First, `members[n].assistantOverrides` is applied. Then, `membersOverrides` is applied as a global override.", + "allOf": [ + { + "$ref": "#/components/schemas/AssistantOverrides" + } + ] } }, "required": [ - "model", - "provider" + "members" ] }, - "ExactReplacement": { + "HandoffDestinationSquad": { "type": "object", "properties": { "type": { "type": "string", - "description": "This is the exact replacement type. You can use this to replace a specific word or phrase with a different word or phrase.\n\nUsage:\n- Replace \"hello\" with \"hi\": { type: 'exact', key: 'hello', value: 'hi' }\n- Replace \"good morning\" with \"good day\": { type: 'exact', key: 'good morning', value: 'good day' }\n- Replace a specific name: { type: 'exact', key: 'John Doe', value: 'Jane Smith' }\n- Replace an acronym: { type: 'exact', key: 'AI', value: 'Artificial Intelligence' }\n- Replace a company name with its phonetic pronunciation: { type: 'exact', key: 'Vapi', value: 'Vappy' }", "enum": [ - "exact" + "squad" ] }, - "replaceAllEnabled": { - "type": "boolean", - "description": "This option let's you control whether to replace all instances of the key or only the first one. By default, it only replaces the first instance.\nExamples:\n- For { type: 'exact', key: 'hello', value: 'hi', replaceAllEnabled: false }. Before: \"hello world, hello universe\" | After: \"hi world, hello universe\"\n- For { type: 'exact', key: 'hello', value: 'hi', replaceAllEnabled: true }. Before: \"hello world, hello universe\" | After: \"hi world, hi universe\"\n@default false", - "default": false + "contextEngineeringPlan": { + "description": "This is the plan for manipulating the message context before handing off the call to the squad.", + "oneOf": [ + { + "$ref": "#/components/schemas/ContextEngineeringPlanLastNMessages", + "title": "Last N Messages" + }, + { + "$ref": "#/components/schemas/ContextEngineeringPlanNone", + "title": "None" + }, + { + "$ref": "#/components/schemas/ContextEngineeringPlanAll", + "title": "All" + }, + { + "$ref": "#/components/schemas/ContextEngineeringPlanUserAndAssistantMessages", + "title": "User And Assistant Messages" + }, + { + "$ref": "#/components/schemas/ContextEngineeringPlanPreviousAssistantMessages", + "title": "Previous Assistant Messages" + } + ] }, - "key": { + "squadId": { "type": "string", - "description": "This is the key to replace." + "description": "This is the squad id to transfer the call to." }, - "value": { - "type": "string", - "description": "This is the value that will replace the match.", - "maxLength": 1000 - } - }, - "required": [ - "type", - "key", - "value" - ] - }, - "RegexReplacement": { - "type": "object", - "properties": { - "type": { - "type": "string", - "description": "This is the regex replacement type. You can use this to replace a word or phrase that matches a pattern.\n\nUsage:\n- Replace all numbers with \"some number\": { type: 'regex', regex: '\\\\d+', value: 'some number' }\n- Replace email addresses with \"[EMAIL]\": { type: 'regex', regex: '\\\\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\\\.[A-Z|a-z]{2,}\\\\b', value: '[EMAIL]' }\n- Replace phone numbers with a formatted version: { type: 'regex', regex: '(\\\\d{3})(\\\\d{3})(\\\\d{4})', value: '($1) $2-$3' }\n- Replace all instances of \"color\" or \"colour\" with \"hue\": { type: 'regex', regex: 'colou?r', value: 'hue' }\n- Capitalize the first letter of every sentence: { type: 'regex', regex: '(?<=\\\\. |^)[a-z]', value: (match) => match.toUpperCase() }", - "enum": [ - "regex" + "squad": { + "description": "This is a transient squad to transfer the call to.", + "allOf": [ + { + "$ref": "#/components/schemas/CreateSquadDTO" + } ] }, - "regex": { + "entryAssistantName": { "type": "string", - "description": "This is the regex pattern to replace.\n\nNote:\n- This works by using the `string.replace` method in Node.JS. Eg. `\"hello there\".replace(/hello/g, \"hi\")` will return `\"hi there\"`.\n\nHot tip:\n- In JavaScript, escape `\\` when sending the regex pattern. Eg. `\"hello\\sthere\"` will be sent over the wire as `\"hellosthere\"`. Send `\"hello\\\\sthere\"` instead." + "description": "This is the name of the entry assistant to start with when handing off to the squad.\nIf not provided, the first member of the squad will be used." }, - "options": { - "description": "These are the options for the regex replacement. Defaults to all disabled.\n\n@default []", - "type": "array", - "items": { - "$ref": "#/components/schemas/RegexOption" - } + "variableExtractionPlan": { + "description": "This is the variable extraction plan for the handoff tool.", + "allOf": [ + { + "$ref": "#/components/schemas/VariableExtractionPlan" + } + ] }, - "value": { + "squadOverrides": { + "description": "These are the overrides to apply to the squad configuration.\nMaps to squad-level membersOverrides.", + "allOf": [ + { + "$ref": "#/components/schemas/AssistantOverrides" + } + ] + }, + "description": { "type": "string", - "description": "This is the value that will replace the match.", - "maxLength": 1000 + "description": "This is the description of the destination, used by the AI to choose when and how to transfer the call." } }, "required": [ - "type", - "regex", - "value" + "type" ] }, - "FormatPlan": { + "CreateHandoffToolDTO": { "type": "object", "properties": { - "enabled": { - "type": "boolean", - "description": "This determines whether the chunk is formatted before being sent to the voice provider. This helps with enunciation. This includes phone numbers, emails and addresses. Default `true`.\n\nUsage:\n- To rely on the voice provider's formatting logic, set this to `false`.\n\nIf `voice.chunkPlan.enabled` is `false`, this is automatically `false` since there's no chunk to format.\n\n@default true", - "example": true - }, - "numberToDigitsCutoff": { - "type": "number", - "description": "This is the cutoff after which a number is converted to individual digits instead of being spoken as words.\n\nExample:\n- If cutoff 2025, \"12345\" is converted to \"1 2 3 4 5\" while \"1200\" is converted to \"twelve hundred\".\n\nUsage:\n- If your use case doesn't involve IDs like zip codes, set this to a high value.\n- If your use case involves IDs that are shorter than 5 digits, set this to a lower value.\n\n@default 2025", - "minimum": 0, - "example": 2025 - }, - "replacements": { + "messages": { "type": "array", - "description": "These are the custom replacements you can make to the chunk before it is sent to the voice provider.\n\nUsage:\n- To replace a specific word or phrase with a different word or phrase, use the `ExactReplacement` type. Eg. `{ type: 'exact', key: 'hello', value: 'hi' }`\n- To replace a word or phrase that matches a pattern, use the `RegexReplacement` type. Eg. `{ type: 'regex', regex: '\\\\b[a-zA-Z]{5}\\\\b', value: 'hi' }`\n\n@default []", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", "items": { "oneOf": [ { - "$ref": "#/components/schemas/ExactReplacement", - "title": "ExactReplacement" + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" }, { - "$ref": "#/components/schemas/RegexReplacement", - "title": "RegexReplacement" + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" } ] } }, - "formattersEnabled": { - "type": "array", - "description": "List of formatters to apply. If not provided, all default formatters will be applied.\nIf provided, only the specified formatters will be applied.\nNote: Some essential formatters like angle bracket removal will always be applied.\n@default undefined", - "enum": [ - "markdown", - "asterisk", - "quote", - "dash", - "newline", - "colon", - "acronym", - "dollarAmount", - "email", - "date", - "time", - "distance", - "unit", - "percentage", - "phoneNumber", - "number", - "stripAsterisk" - ], + "type": { + "type": "string", + "description": "This is the type of the tool.\nWhen you're using handoff tool, we recommend adding this to your system prompt\n---\n# System context\n\nYou are part of a multi-agent system designed to make agent coordination and execution easy. Agents uses two primary abstraction: **Agents** and **Handoffs**. An agent encompasses instructions and tools and can hand off a conversation to another agent when appropriate. Handoffs are achieved by calling a handoff function, generally named `handoff_to_`. Handoffs between agents are handled seamlessly in the background; do not mention or draw attention to these handoffs in your conversation with the user.\n\n# Agent context\n\n{put your agent system prompt here}\n---", + "enum": [ + "handoff" + ] + }, + "defaultResult": { + "type": "string", + "description": "This is the default local tool result message used when no runtime handoff result override is returned." + }, + "destinations": { + "type": "array", + "description": "These are the destinations that the call can be handed off to.\n\nUsage:\n1. Single destination\n\nUse `assistantId` to handoff the call to a saved assistant, or `assistantName` to handoff the call to an assistant in the same squad.\n\n```json\n{\n \"tools\": [\n {\n \"type\": \"handoff\",\n \"destinations\": [\n {\n \"type\": \"assistant\",\n \"assistantId\": \"assistant-123\", // or \"assistantName\": \"Assistant123\"\n \"description\": \"customer wants to be handed off to assistant-123\",\n \"contextEngineeringPlan\": {\n \"type\": \"all\"\n }\n }\n ],\n }\n ]\n}\n```\n\n2. Multiple destinations\n\n2.1. Multiple Tools, Each With One Destination (OpenAI recommended)\n\n```json\n{\n \"tools\": [\n {\n \"type\": \"handoff\",\n \"destinations\": [\n {\n \"type\": \"assistant\",\n \"assistantId\": \"assistant-123\",\n \"description\": \"customer wants to be handed off to assistant-123\",\n \"contextEngineeringPlan\": {\n \"type\": \"all\"\n }\n },\n ],\n },\n {\n \"type\": \"handoff\",\n \"destinations\": [\n {\n \"type\": \"assistant\",\n \"assistantId\": \"assistant-456\",\n \"description\": \"customer wants to be handed off to assistant-456\",\n \"contextEngineeringPlan\": {\n \"type\": \"all\"\n }\n }\n ],\n }\n ]\n}\n```\n\n2.2. One Tool, Multiple Destinations (Anthropic recommended)\n\n```json\n{\n \"tools\": [\n {\n \"type\": \"handoff\",\n \"destinations\": [\n {\n \"type\": \"assistant\",\n \"assistantId\": \"assistant-123\",\n \"description\": \"customer wants to be handed off to assistant-123\",\n \"contextEngineeringPlan\": {\n \"type\": \"all\"\n }\n },\n {\n \"type\": \"assistant\",\n \"assistantId\": \"assistant-456\",\n \"description\": \"customer wants to be handed off to assistant-456\",\n \"contextEngineeringPlan\": {\n \"type\": \"all\"\n }\n }\n ],\n }\n ]\n}\n```\n\n3. Dynamic destination\n\n3.1 To determine the destination dynamically, supply a `dynamic` handoff destination type and a `server` object.\n VAPI will send a handoff-destination-request webhook to the `server.url`.\n The response from the server will be used as the destination (if valid).\n\n```json\n{\n \"tools\": [\n {\n \"type\": \"handoff\",\n \"destinations\": [\n {\n \"type\": \"dynamic\",\n \"server\": {\n \"url\": \"https://example.com\"\n }\n }\n ],\n }\n ]\n}\n```\n\n3.2. To pass custom parameters to the server, you can use the `function` object.\n\n```json\n{\n \"tools\": [\n {\n \"type\": \"handoff\",\n \"destinations\": [\n {\n \"type\": \"dynamic\",\n \"server\": {\n \"url\": \"https://example.com\"\n },\n }\n ],\n \"function\": {\n \"name\": \"handoff\",\n \"description\": \"Call this function when the customer is ready to be handed off to the next assistant\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"destination\": {\n \"type\": \"string\",\n \"description\": \"Use dynamic when customer is ready to be handed off to the next assistant\",\n \"enum\": [\"dynamic\"]\n },\n \"customerAreaCode\": {\n \"type\": \"number\",\n \"description\": \"Area code of the customer\"\n },\n \"customerIntent\": {\n \"type\": \"string\",\n \"enum\": [\"new-customer\", \"existing-customer\"],\n \"description\": \"Use new-customer when customer is a new customer, existing-customer when customer is an existing customer\"\n },\n \"customerSentiment\": {\n \"type\": \"string\",\n \"enum\": [\"positive\", \"negative\", \"neutral\"],\n \"description\": \"Use positive when customer is happy, negative when customer is unhappy, neutral when customer is neutral\"\n }\n }\n }\n }\n }\n ]\n}\n```\n\nThe properties `customerAreaCode`, `customerIntent`, and `customerSentiment` will be passed to the server in the webhook request body.", "items": { - "type": "string", - "enum": [ - "markdown", - "asterisk", - "quote", - "dash", - "newline", - "colon", - "acronym", - "dollarAmount", - "email", - "date", - "time", - "distance", - "unit", - "percentage", - "phoneNumber", - "number", - "stripAsterisk" + "oneOf": [ + { + "$ref": "#/components/schemas/HandoffDestinationAssistant", + "title": "Assistant" + }, + { + "$ref": "#/components/schemas/HandoffDestinationDynamic", + "title": "Dynamic" + }, + { + "$ref": "#/components/schemas/HandoffDestinationSquad", + "title": "Squad" + } ] } + }, + "function": { + "description": "This is the optional function definition that will be passed to the LLM.\nIf this is not defined, we will construct this based on the other properties.\n\nFor example, given the following tools definition:\n```json\n{\n \"tools\": [\n {\n \"type\": \"handoff\",\n \"destinations\": [\n {\n \"type\": \"assistant\",\n \"assistantId\": \"assistant-123\",\n \"description\": \"customer wants to be handed off to assistant-123\",\n \"contextEngineeringPlan\": {\n \"type\": \"all\"\n }\n },\n {\n \"type\": \"assistant\",\n \"assistantId\": \"assistant-456\",\n \"description\": \"customer wants to be handed off to assistant-456\",\n \"contextEngineeringPlan\": {\n \"type\": \"all\"\n }\n }\n ],\n }\n ]\n}\n```\n\nWe will construct the following function definition:\n```json\n{\n \"function\": {\n \"name\": \"handoff_to_assistant-123\",\n \"description\": \"\n Use this function to handoff the call to the next assistant.\n Only use it when instructions explicitly ask you to use the handoff_to_assistant function.\n DO NOT call this function unless you are instructed to do so.\n Here are the destinations you can handoff the call to:\n 1. assistant-123. When: customer wants to be handed off to assistant-123\n 2. assistant-456. When: customer wants to be handed off to assistant-456\n \",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"destination\": {\n \"type\": \"string\",\n \"description\": \"Options: assistant-123 (customer wants to be handed off to assistant-123), assistant-456 (customer wants to be handed off to assistant-456)\",\n \"enum\": [\"assistant-123\", \"assistant-456\"]\n },\n },\n \"required\": [\"destination\"]\n }\n }\n}\n```\n\nTo override this function, please provide an OpenAI function definition and refer to it in the system prompt.\nYou may override parts of the function definition (i.e. you may only want to change the function name for your prompt).\nIf you choose to override the function parameters, it must include `destination` as a required parameter, and it must evaluate to either an assistantId, assistantName, or a the string literal `dynamic`.\n\nTo pass custom parameters to the server in a dynamic handoff, you can use the function parameters, with `dynamic` as the destination.\n```json\n{\n \"function\": {\n \"name\": \"dynamic_handoff\",\n \"description\": \"\n Call this function when the customer is ready to be handed off to the next assistant\n \",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"destination\": {\n \"type\": \"string\",\n \"enum\": [\"dynamic\"]\n },\n \"customerAreaCode\": {\n \"type\": \"number\",\n \"description\": \"Area code of the customer\"\n },\n \"customerIntent\": {\n \"type\": \"string\",\n \"enum\": [\"new-customer\", \"existing-customer\"],\n \"description\": \"Use new-customer when customer is a new customer, existing-customer when customer is an existing customer\"\n },\n \"customerSentiment\": {\n \"type\": \"string\",\n \"enum\": [\"positive\", \"negative\", \"neutral\"],\n \"description\": \"Use positive when customer is happy, negative when customer is unhappy, neutral when customer is neutral\"\n }\n },\n \"required\": [\"destination\", \"customerAreaCode\", \"customerIntent\", \"customerSentiment\"]\n }\n }\n}\n```", + "allOf": [ + { + "$ref": "#/components/schemas/OpenAIFunction" + } + ] + }, + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "allOf": [ + { + "$ref": "#/components/schemas/ToolRejectionPlan" + } + ] } - } + }, + "required": [ + "type" + ] }, - "ChunkPlan": { + "CreateCustomKnowledgeBaseDTO": { "type": "object", "properties": { - "enabled": { - "type": "boolean", - "description": "This determines whether the model output is chunked before being sent to the voice provider. Default `true`.\n\nUsage:\n- To rely on the voice provider's audio generation logic, set this to `false`.\n- If seeing issues with quality, set this to `true`.\n\nIf disabled, Vapi-provided audio control tokens like will not work.\n\n@default true", - "example": true - }, - "minCharacters": { - "type": "number", - "description": "This is the minimum number of characters in a chunk.\n\nUsage:\n- To increase quality, set this to a higher value.\n- To decrease latency, set this to a lower value.\n\n@default 30", - "minimum": 1, - "maximum": 80, - "example": 30 - }, - "punctuationBoundaries": { - "type": "array", - "description": "These are the punctuations that are considered valid boundaries for a chunk to be created.\n\nUsage:\n- To increase quality, constrain to fewer boundaries.\n- To decrease latency, enable all.\n\nDefault is automatically set to balance the trade-off between quality and latency based on the provider.", + "provider": { + "type": "string", + "description": "This knowledge base is bring your own knowledge base implementation.", "enum": [ - "。", - ",", - ".", - "!", - "?", - ";", - ")", - "،", - "۔", - "।", - "॥", - "|", - "||", - ",", - ":" - ], - "example": [ - "。", - ",", - ".", - "!", - "?", - ";", - "،", - "۔", - "।", - "॥", - "|", - "||", - ",", - ":" - ], - "items": { - "type": "string", - "enum": [ - "。", - ",", - ".", - "!", - "?", - ";", - ")", - "،", - "۔", - "।", - "॥", - "|", - "||", - ",", - ":" - ] - } + "custom-knowledge-base" + ] }, - "formatPlan": { - "description": "This is the plan for formatting the chunk before it is sent to the voice provider.", + "server": { + "description": "This is where the knowledge base request will be sent.\n\nRequest Example:\n\nPOST https://{server.url}\nContent-Type: application/json\n\n{\n \"messsage\": {\n \"type\": \"knowledge-base-request\",\n \"messages\": [\n {\n \"role\": \"user\",\n \"content\": \"Why is ocean blue?\"\n }\n ],\n ...other metadata about the call...\n }\n}\n\nResponse Expected:\n```\n{\n \"message\": {\n \"role\": \"assistant\",\n \"content\": \"The ocean is blue because water absorbs everything but blue.\",\n }, // YOU CAN RETURN THE EXACT RESPONSE TO SPEAK\n \"documents\": [\n {\n \"content\": \"The ocean is blue primarily because water absorbs colors in the red part of the light spectrum and scatters the blue light, making it more visible to our eyes.\",\n \"similarity\": 1\n },\n {\n \"content\": \"Blue light is scattered more by the water molecules than other colors, enhancing the blue appearance of the ocean.\",\n \"similarity\": .5\n }\n ] // OR, YOU CAN RETURN AN ARRAY OF DOCUMENTS THAT WILL BE SENT TO THE MODEL\n}\n```", "allOf": [ { - "$ref": "#/components/schemas/FormatPlan" + "$ref": "#/components/schemas/Server" } ] } - } + }, + "required": [ + "provider", + "server" + ] }, - "FallbackPlan": { + "KnowledgeBase": { "type": "object", "properties": { - "voices": { + "name": { + "type": "string", + "description": "The name of the knowledge base", + "example": "My Knowledge Base" + }, + "provider": { + "type": "string", + "description": "The provider of the knowledge base", + "enum": [ + "google" + ], + "example": "google" + }, + "model": { + "type": "string", + "description": "The model to use for the knowledge base", + "enum": [ + "gemini-3.5-flash", + "gemini-3.1-flash-lite", + "gemini-3-flash-preview", + "gemini-2.5-pro", + "gemini-2.5-flash", + "gemini-2.5-flash-lite", + "gemini-2.0-flash-thinking-exp", + "gemini-2.0-pro-exp-02-05", + "gemini-2.0-flash", + "gemini-2.0-flash-lite", + "gemini-2.0-flash-exp", + "gemini-2.0-flash-realtime-exp", + "gemini-1.5-flash", + "gemini-1.5-flash-002", + "gemini-1.5-pro", + "gemini-1.5-pro-002", + "gemini-1.0-pro" + ] + }, + "description": { + "type": "string", + "description": "A description of the knowledge base" + }, + "fileIds": { + "description": "The file IDs associated with this knowledge base", "type": "array", - "description": "This is the list of voices to fallback to in the event that the primary voice provider fails.", + "items": { + "type": "string" + } + } + }, + "required": [ + "name", + "provider", + "description", + "fileIds" + ] + }, + "CreateQueryToolDTO": { + "type": "object", + "properties": { + "messages": { + "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", "items": { "oneOf": [ { - "$ref": "#/components/schemas/FallbackAzureVoice", - "title": "Azure" + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" }, { - "$ref": "#/components/schemas/FallbackCartesiaVoice", - "title": "Cartesia" + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" }, { - "$ref": "#/components/schemas/FallbackHumeVoice", - "title": "Hume" + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" }, { - "$ref": "#/components/schemas/FallbackCustomVoice", - "title": "CustomVoice" - }, + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] + } + }, + "type": { + "type": "string", + "enum": [ + "query" + ], + "description": "The type of tool. \"query\" for Query tool." + }, + "knowledgeBases": { + "description": "The knowledge bases to query", + "type": "array", + "items": { + "$ref": "#/components/schemas/KnowledgeBase" + } + }, + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "allOf": [ + { + "$ref": "#/components/schemas/ToolRejectionPlan" + } + ] + } + }, + "required": [ + "type" + ] + }, + "CreateGoogleCalendarCreateEventToolDTO": { + "type": "object", + "properties": { + "messages": { + "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", + "items": { + "oneOf": [ { - "$ref": "#/components/schemas/FallbackDeepgramVoice", - "title": "Deepgram" + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" }, { - "$ref": "#/components/schemas/FallbackElevenLabsVoice", - "title": "ElevenLabs" + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" }, { - "$ref": "#/components/schemas/FallbackVapiVoice", - "title": "Vapi" + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" }, { - "$ref": "#/components/schemas/FallbackLMNTVoice", - "title": "LMNT" - }, + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] + } + }, + "type": { + "type": "string", + "enum": [ + "google.calendar.event.create" + ], + "description": "The type of tool. \"google.calendar.event.create\" for Google Calendar Create Event tool." + }, + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "allOf": [ + { + "$ref": "#/components/schemas/ToolRejectionPlan" + } + ] + } + }, + "required": [ + "type" + ] + }, + "CreateGoogleSheetsRowAppendToolDTO": { + "type": "object", + "properties": { + "messages": { + "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", + "items": { + "oneOf": [ { - "$ref": "#/components/schemas/FallbackOpenAIVoice", - "title": "OpenAI" + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" }, { - "$ref": "#/components/schemas/FallbackPlayHTVoice", - "title": "PlayHT" + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" }, { - "$ref": "#/components/schemas/FallbackRimeAIVoice", - "title": "RimeAI" + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" }, { - "$ref": "#/components/schemas/FallbackSmallestAIVoice", - "title": "Smallest AI" - }, + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] + } + }, + "type": { + "type": "string", + "enum": [ + "google.sheets.row.append" + ], + "description": "The type of tool. \"google.sheets.row.append\" for Google Sheets Row Append tool." + }, + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "allOf": [ + { + "$ref": "#/components/schemas/ToolRejectionPlan" + } + ] + } + }, + "required": [ + "type" + ] + }, + "CreateGoogleCalendarCheckAvailabilityToolDTO": { + "type": "object", + "properties": { + "messages": { + "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", + "items": { + "oneOf": [ { - "$ref": "#/components/schemas/FallbackTavusVoice", - "title": "TavusVoice" + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" }, { - "$ref": "#/components/schemas/FallbackNeuphonicVoice", - "title": "Neuphonic" + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" }, { - "$ref": "#/components/schemas/FallbackSesameVoice", - "title": "Sesame" + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" }, { - "$ref": "#/components/schemas/FallbackInworldVoice", - "title": "Inworld" + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" } ] } + }, + "type": { + "type": "string", + "enum": [ + "google.calendar.availability.check" + ], + "description": "The type of tool. \"google.calendar.availability.check\" for Google Calendar Check Availability tool." + }, + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "allOf": [ + { + "$ref": "#/components/schemas/ToolRejectionPlan" + } + ] } }, "required": [ - "voices" + "type" ] }, - "AzureVoice": { + "CreateSlackSendMessageToolDTO": { "type": "object", "properties": { - "cachingEnabled": { - "type": "boolean", - "description": "This is the flag to toggle voice caching for the assistant.", - "example": true, - "default": true + "messages": { + "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" + }, + { + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] + } }, - "provider": { + "type": { "type": "string", - "description": "This is the voice provider that will be used.", "enum": [ - "azure" - ] - }, - "voiceId": { - "description": "This is the provider-specific ID that will be used.", - "oneOf": [ - { - "type": "string", - "enum": [ - "andrew", - "brian", - "emma" - ], - "title": "Preset Voice Options" - }, - { - "type": "string", - "title": "Azure Voice ID" - } - ] - }, - "chunkPlan": { - "description": "This is the plan for chunking the model output before it is sent to the voice provider.", - "allOf": [ - { - "$ref": "#/components/schemas/ChunkPlan" - } - ] - }, - "speed": { - "type": "number", - "description": "This is the speed multiplier that will be used.", - "minimum": 0.5, - "maximum": 2 + "slack.message.send" + ], + "description": "The type of tool. \"slack.message.send\" for Slack Send Message tool." }, - "fallbackPlan": { - "description": "This is the plan for voice provider fallbacks in the event that the primary voice provider fails.", + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", "allOf": [ { - "$ref": "#/components/schemas/FallbackPlan" + "$ref": "#/components/schemas/ToolRejectionPlan" } ] } }, "required": [ - "provider", - "voiceId" + "type" ] }, - "CartesiaExperimentalControls": { + "McpToolMessages": { "type": "object", "properties": { - "speed": { - "oneOf": [ - { - "type": "string", - "enum": [ - "slowest", - "slow", - "normal", - "fast", - "fastest" - ], - "example": "normal" - }, - { - "type": "number", - "minimum": -1, - "maximum": 1, - "example": 0.5 - } - ] - }, - "emotion": { + "name": { "type": "string", - "enum": [ - "anger:lowest", - "anger:low", - "anger:high", - "anger:highest", - "positivity:lowest", - "positivity:low", - "positivity:high", - "positivity:highest", - "surprise:lowest", - "surprise:low", - "surprise:high", - "surprise:highest", - "sadness:lowest", - "sadness:low", - "sadness:high", - "sadness:highest", - "curiosity:lowest", - "curiosity:low", - "curiosity:high", - "curiosity:highest" - ], - "example": [ - "happiness:high" - ] + "description": "The name of the tool from the MCP server." + }, + "messages": { + "type": "array", + "description": "Custom messages for this specific tool. Set to an empty array to suppress all messages for this tool. If not provided, the tool will use the default messages from the parent MCP tool configuration. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" + }, + { + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] + } } - } + }, + "required": [ + "name" + ] }, - "CartesiaVoice": { + "McpToolMetadata": { "type": "object", "properties": { - "cachingEnabled": { - "type": "boolean", - "description": "This is the flag to toggle voice caching for the assistant.", - "example": true, - "default": true - }, - "provider": { - "type": "string", - "description": "This is the voice provider that will be used.", - "enum": [ - "cartesia" - ] - }, - "voiceId": { - "type": "string", - "description": "The ID of the particular voice you want to use." - }, - "model": { + "protocol": { "type": "string", - "description": "This is the model that will be used. This is optional and will default to the correct model for the voiceId.", "enum": [ - "sonic-2", - "sonic-english", - "sonic-multilingual", - "sonic-preview", - "sonic" + "sse", + "shttp" ], - "example": "sonic-english" + "description": "This is the protocol used for MCP communication. Defaults to Streamable HTTP." + } + } + }, + "CreateMcpToolDTO": { + "type": "object", + "properties": { + "messages": { + "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" + }, + { + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] + } }, - "language": { + "type": { "type": "string", - "description": "This is the language that will be used. This is optional and will default to the correct language for the voiceId.", "enum": [ - "en", - "de", - "es", - "fr", - "ja", - "pt", - "zh", - "hi", - "it", - "ko", - "nl", - "pl", - "ru", - "sv", - "tr" + "mcp" ], - "example": "en" + "description": "The type of tool. \"mcp\" for MCP tool." }, - "experimentalControls": { - "description": "Experimental controls for Cartesia voice generation", + "server": { + "description": "\n This is the server where a `tool-calls` webhook will be sent.\n\n Notes:\n - Webhook is sent to this server when a tool call is made.\n - Webhook contains the call, assistant, and phone number objects.\n - Webhook contains the variables set on the assistant.\n - Webhook is sent to the first available URL in this order: {{tool.server.url}}, {{assistant.server.url}}, {{phoneNumber.server.url}}, {{org.server.url}}.\n - Webhook expects a response with tool call result.", "allOf": [ { - "$ref": "#/components/schemas/CartesiaExperimentalControls" + "$ref": "#/components/schemas/Server" } ] }, - "chunkPlan": { - "description": "This is the plan for chunking the model output before it is sent to the voice provider.", - "allOf": [ - { - "$ref": "#/components/schemas/ChunkPlan" - } - ] + "toolMessages": { + "description": "Per-tool message overrides for individual tools loaded from the MCP server. Set messages to an empty array to suppress messages for a specific tool. Tools not listed here will use the default messages from the parent tool.", + "type": "array", + "items": { + "$ref": "#/components/schemas/McpToolMessages" + } }, - "fallbackPlan": { - "description": "This is the plan for voice provider fallbacks in the event that the primary voice provider fails.", + "metadata": { + "$ref": "#/components/schemas/McpToolMetadata" + }, + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", "allOf": [ { - "$ref": "#/components/schemas/FallbackPlan" + "$ref": "#/components/schemas/ToolRejectionPlan" } ] } }, "required": [ - "provider", - "voiceId" + "type" ] }, - "CustomVoice": { + "CreateGoHighLevelCalendarAvailabilityToolDTO": { "type": "object", "properties": { - "cachingEnabled": { - "type": "boolean", - "description": "This is the flag to toggle voice caching for the assistant.", - "example": true, - "default": true + "messages": { + "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" + }, + { + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] + } }, - "provider": { + "type": { "type": "string", - "description": "This is the voice provider that will be used. Use `custom-voice` for providers that are not natively supported.", "enum": [ - "custom-voice" - ] + "gohighlevel.calendar.availability.check" + ], + "description": "The type of tool. \"gohighlevel.calendar.availability.check\" for GoHighLevel Calendar Availability Check tool." }, - "chunkPlan": { - "description": "This is the plan for chunking the model output before it is sent to the voice provider.", + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", "allOf": [ { - "$ref": "#/components/schemas/ChunkPlan" + "$ref": "#/components/schemas/ToolRejectionPlan" } ] + } + }, + "required": [ + "type" + ] + }, + "CreateGoHighLevelCalendarEventCreateToolDTO": { + "type": "object", + "properties": { + "messages": { + "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" + }, + { + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] + } }, - "server": { - "description": "This is where the voice request will be sent.\n\nRequest Example:\n\nPOST https://{server.url}\nContent-Type: application/json\n\n{\n \"message\": {\n \"type\": \"voice-request\",\n \"text\": \"Hello, world!\",\n \"sampleRate\": 24000,\n ...other metadata about the call...\n }\n}\n\nResponse Expected: 1-channel 16-bit raw PCM audio at the sample rate specified in the request. Here is how the response will be piped to the transport:\n```\nresponse.on('data', (chunk: Buffer) => {\n outputStream.write(chunk);\n});\n```", - "allOf": [ - { - "$ref": "#/components/schemas/Server" - } - ] + "type": { + "type": "string", + "enum": [ + "gohighlevel.calendar.event.create" + ], + "description": "The type of tool. \"gohighlevel.calendar.event.create\" for GoHighLevel Calendar Event Create tool." }, - "fallbackPlan": { - "description": "This is the plan for voice provider fallbacks in the event that the primary voice provider fails.", + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", "allOf": [ { - "$ref": "#/components/schemas/FallbackPlan" + "$ref": "#/components/schemas/ToolRejectionPlan" } ] } }, "required": [ - "provider", - "server" + "type" ] }, - "DeepgramVoice": { + "CreateGoHighLevelContactCreateToolDTO": { "type": "object", "properties": { - "cachingEnabled": { - "type": "boolean", - "description": "This is the flag to toggle voice caching for the assistant.", - "example": true, - "default": true - }, - "provider": { - "type": "string", - "description": "This is the voice provider that will be used.", - "enum": [ - "deepgram" - ] - }, - "voiceId": { - "type": "string", - "description": "This is the provider-specific ID that will be used.", - "enum": [ - "asteria", - "luna", - "stella", - "athena", - "hera", - "orion", - "arcas", - "perseus", - "angus", - "orpheus", - "helios", - "zeus", - "thalia", - "andromeda", - "helena", - "apollo", - "arcas", - "aries", - "amalthea", - "asteria", - "athena", - "atlas", - "aurora", - "callista", - "cora", - "cordelia", - "delia", - "draco", - "electra", - "harmonia", - "hera", - "hermes", - "hyperion", - "iris", - "janus", - "juno", - "jupiter", - "luna", - "mars", - "minerva", - "neptune", - "odysseus", - "ophelia", - "orion", - "orpheus", - "pandora", - "phoebe", - "pluto", - "saturn", - "selene", - "theia", - "vesta", - "zeus" - ], - "title": "This is the Deepgram Voice ID" + "messages": { + "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" + }, + { + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] + } }, - "model": { + "type": { "type": "string", - "description": "This is the model that will be used. Defaults to 'aura-2' when not specified.", "enum": [ - "aura", - "aura-2" + "gohighlevel.contact.create" ], - "example": "aura-2" - }, - "mipOptOut": { - "type": "boolean", - "description": "If set to true, this will add mip_opt_out=true as a query parameter of all API requests. See https://developers.deepgram.com/docs/the-deepgram-model-improvement-partnership-program#want-to-opt-out\n\nThis will only be used if you are using your own Deepgram API key.\n\n@default false", - "example": false, - "default": false + "description": "The type of tool. \"gohighlevel.contact.create\" for GoHighLevel Contact Create tool." }, - "chunkPlan": { - "description": "This is the plan for chunking the model output before it is sent to the voice provider.", + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", "allOf": [ { - "$ref": "#/components/schemas/ChunkPlan" + "$ref": "#/components/schemas/ToolRejectionPlan" } ] + } + }, + "required": [ + "type" + ] + }, + "CreateGoHighLevelContactGetToolDTO": { + "type": "object", + "properties": { + "messages": { + "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" + }, + { + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] + } }, - "fallbackPlan": { - "description": "This is the plan for voice provider fallbacks in the event that the primary voice provider fails.", + "type": { + "type": "string", + "enum": [ + "gohighlevel.contact.get" + ], + "description": "The type of tool. \"gohighlevel.contact.get\" for GoHighLevel Contact Get tool." + }, + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", "allOf": [ { - "$ref": "#/components/schemas/FallbackPlan" + "$ref": "#/components/schemas/ToolRejectionPlan" } ] } }, "required": [ - "provider", - "voiceId" + "type" ] }, - "ElevenLabsPronunciationDictionaryLocator": { + "OpenAIMessage": { "type": "object", "properties": { - "pronunciationDictionaryId": { + "content": { "type": "string", - "description": "This is the ID of the pronunciation dictionary to use.", - "title": "This is the ElevenLabs Pronunciation Dictionary ID" + "nullable": true, + "maxLength": 100000000 }, - "versionId": { + "role": { "type": "string", - "description": "This is the version ID of the pronunciation dictionary to use.", - "title": "This is the ElevenLabs Pronunciation Dictionary Version ID" + "enum": [ + "assistant", + "function", + "user", + "system", + "tool" + ] } }, "required": [ - "pronunciationDictionaryId", - "versionId" + "content", + "role" ] }, - "ElevenLabsVoice": { + "ToolRef": { "type": "object", "properties": { - "cachingEnabled": { - "type": "boolean", - "description": "This is the flag to toggle voice caching for the assistant.", - "example": true, - "default": true - }, - "provider": { + "toolId": { "type": "string", - "description": "This is the voice provider that will be used.", - "enum": [ - "11labs" - ] - }, - "voiceId": { - "description": "This is the provider-specific ID that will be used. Ensure the Voice is present in your 11Labs Voice Library.", - "oneOf": [ - { - "type": "string", - "enum": [ - "burt", - "marissa", - "andrea", - "sarah", - "phillip", - "steve", - "joseph", - "myra", - "paula", - "ryan", - "drew", - "paul", - "mrb", - "matilda", - "mark" - ], - "title": "Preset Voice Options" - }, - { - "type": "string", - "title": "11Labs Voice ID" - } - ] - }, - "stability": { - "type": "number", - "description": "Defines the stability for voice settings.", - "minimum": 0, - "maximum": 1, - "example": 0.5 + "description": "This is the unique identifier of the tool whose version is being pinned.", + "format": "uuid" }, - "similarityBoost": { - "type": "number", - "description": "Defines the similarity boost for voice settings.", - "minimum": 0, - "maximum": 1, - "example": 0.75 + "version": { + "type": "string", + "description": "Public version label of the tool, e.g. \"v3\"" + } + }, + "required": [ + "toolId", + "version" + ] + }, + "AnyscaleModel": { + "type": "object", + "properties": { + "messages": { + "description": "This is the starting state for the conversation.", + "type": "array", + "items": { + "$ref": "#/components/schemas/OpenAIMessage" + } }, - "style": { - "type": "number", - "description": "Defines the style for voice settings.", - "minimum": 0, - "maximum": 1, - "example": 0 - }, - "useSpeakerBoost": { - "type": "boolean", - "description": "Defines the use speaker boost for voice settings.", - "example": false - }, - "speed": { - "type": "number", - "description": "Defines the speed for voice settings.", - "minimum": 0.7, - "maximum": 1.2, - "example": 0.9 + "tools": { + "type": "array", + "description": "These are the tools that the assistant can use during the call. To use existing tools, use `toolIds`.\n\nBoth `tools` and `toolIds` can be used together.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/CreateApiRequestToolDTO", + "title": "ApiRequestTool" + }, + { + "$ref": "#/components/schemas/CreateBashToolDTO", + "title": "BashTool" + }, + { + "$ref": "#/components/schemas/CreateCodeToolDTO", + "title": "CodeTool" + }, + { + "$ref": "#/components/schemas/CreateComputerToolDTO", + "title": "ComputerTool" + }, + { + "$ref": "#/components/schemas/CreateDtmfToolDTO", + "title": "DtmfTool" + }, + { + "$ref": "#/components/schemas/CreateEndCallToolDTO", + "title": "EndCallTool" + }, + { + "$ref": "#/components/schemas/CreateFunctionToolDTO", + "title": "FunctionTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelCalendarAvailabilityToolDTO", + "title": "GoHighLevelCalendarAvailabilityTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelCalendarEventCreateToolDTO", + "title": "GoHighLevelCalendarEventCreateTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelContactCreateToolDTO", + "title": "GoHighLevelContactCreateTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelContactGetToolDTO", + "title": "GoHighLevelContactGetTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarCheckAvailabilityToolDTO", + "title": "GoogleCalendarCheckAvailabilityTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarCreateEventToolDTO", + "title": "GoogleCalendarCreateEventTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleSheetsRowAppendToolDTO", + "title": "GoogleSheetsRowAppendTool" + }, + { + "$ref": "#/components/schemas/CreateHandoffToolDTO", + "title": "HandoffTool" + }, + { + "$ref": "#/components/schemas/CreateMcpToolDTO", + "title": "McpTool" + }, + { + "$ref": "#/components/schemas/CreateQueryToolDTO", + "title": "QueryTool" + }, + { + "$ref": "#/components/schemas/CreateSlackSendMessageToolDTO", + "title": "SlackSendMessageTool" + }, + { + "$ref": "#/components/schemas/CreateSmsToolDTO", + "title": "SmsTool" + }, + { + "$ref": "#/components/schemas/CreateTextEditorToolDTO", + "title": "TextEditorTool" + }, + { + "$ref": "#/components/schemas/CreateTransferCallToolDTO", + "title": "TransferCallTool" + }, + { + "$ref": "#/components/schemas/CreateSipRequestToolDTO", + "title": "SipRequestTool" + }, + { + "$ref": "#/components/schemas/CreateVoicemailToolDTO", + "title": "VoicemailTool" + } + ] + } }, - "optimizeStreamingLatency": { - "type": "number", - "description": "Defines the optimize streaming latency for voice settings. Defaults to 3.", - "minimum": 0, - "maximum": 4, - "example": 3 + "toolIds": { + "description": "These are the tools that the assistant can use during the call. To use transient tools, use `tools`.\n\nBoth `tools` and `toolIds` can be used together.", + "type": "array", + "items": { + "type": "string" + } }, - "enableSsmlParsing": { - "type": "boolean", - "description": "This enables the use of https://elevenlabs.io/docs/speech-synthesis/prompting#pronunciation. Defaults to false to save latency.\n\n@default false", - "example": false + "toolRefs": { + "description": "These are version-pinned references to tools. Each entry pins a specific\nversion of a tool by `(toolId, version)`. When the same `toolId` appears\nin both `toolIds` and `toolRefs[]`, the `toolRefs` pin wins (the\n`toolIds` entry is dropped at write time).", + "type": "array", + "items": { + "$ref": "#/components/schemas/ToolRef" + } }, - "autoMode": { - "type": "boolean", - "description": "Defines the auto mode for voice settings. Defaults to false.", - "example": false + "knowledgeBase": { + "description": "These are the options for the knowledge base.", + "oneOf": [ + { + "$ref": "#/components/schemas/CreateCustomKnowledgeBaseDTO", + "title": "Custom" + } + ] }, - "model": { + "provider": { "type": "string", - "description": "This is the model that will be used. Defaults to 'eleven_turbo_v2' if not specified.", "enum": [ - "eleven_multilingual_v2", - "eleven_turbo_v2", - "eleven_turbo_v2_5", - "eleven_flash_v2", - "eleven_flash_v2_5", - "eleven_monolingual_v1" - ], - "example": "eleven_turbo_v2_5" + "anyscale" + ] }, - "language": { + "model": { "type": "string", - "description": "This is the language (ISO 639-1) that is enforced for the model. Currently only Turbo v2.5 supports language enforcement. For other models, an error will be returned if language code is provided." + "description": "This is the name of the model. Ex. cognitivecomputations/dolphin-mixtral-8x7b" }, - "chunkPlan": { - "description": "This is the plan for chunking the model output before it is sent to the voice provider.", - "allOf": [ - { - "$ref": "#/components/schemas/ChunkPlan" - } - ] + "temperature": { + "type": "number", + "description": "This is the temperature that will be used for calls. Default is 0.5.", + "minimum": 0, + "maximum": 2 }, - "pronunciationDictionaryLocators": { - "description": "This is the pronunciation dictionary locators to use.", - "type": "array", - "items": { - "$ref": "#/components/schemas/ElevenLabsPronunciationDictionaryLocator" - } + "maxTokens": { + "type": "number", + "description": "This is the max number of tokens that the assistant will be allowed to generate in each turn of the conversation. Default is 250.", + "minimum": 50, + "maximum": 10000 }, - "fallbackPlan": { - "description": "This is the plan for voice provider fallbacks in the event that the primary voice provider fails.", - "allOf": [ - { - "$ref": "#/components/schemas/FallbackPlan" - } - ] + "emotionRecognitionEnabled": { + "type": "boolean", + "description": "This determines whether we detect user's emotion while they speak and send it as an additional info to model.\n\nDefault `false` because the model is usually are good at understanding the user's emotion from text.\n\n@default false" + }, + "numFastTurns": { + "type": "number", + "description": "This sets how many turns at the start of the conversation to use a smaller, faster model from the same provider before switching to the primary model. Example, gpt-3.5-turbo if provider is openai.\n\nDefault is 0.\n\n@default 0", + "minimum": 0 } }, "required": [ "provider", - "voiceId" + "model" ] }, - "HumeVoice": { + "AnthropicThinkingConfig": { "type": "object", "properties": { - "cachingEnabled": { - "type": "boolean", - "description": "This is the flag to toggle voice caching for the assistant.", - "example": true, - "default": true - }, - "provider": { + "type": { "type": "string", - "description": "This is the voice provider that will be used.", "enum": [ - "hume" + "enabled" ] }, - "model": { - "type": "string", - "description": "This is the model that will be used.", - "enum": [ - "octave" - ], - "example": "octave" + "budgetTokens": { + "type": "number", + "description": "The maximum number of tokens to allocate for thinking.\nMust be between 1024 and 100000 tokens.", + "minimum": 1024, + "maximum": 100000 + } + }, + "required": [ + "type", + "budgetTokens" + ] + }, + "AnthropicModel": { + "type": "object", + "properties": { + "messages": { + "description": "This is the starting state for the conversation.", + "type": "array", + "items": { + "$ref": "#/components/schemas/OpenAIMessage" + } }, - "voiceId": { - "type": "string", - "description": "The ID of the particular voice you want to use." + "tools": { + "type": "array", + "description": "These are the tools that the assistant can use during the call. To use existing tools, use `toolIds`.\n\nBoth `tools` and `toolIds` can be used together.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/CreateApiRequestToolDTO", + "title": "ApiRequestTool" + }, + { + "$ref": "#/components/schemas/CreateBashToolDTO", + "title": "BashTool" + }, + { + "$ref": "#/components/schemas/CreateCodeToolDTO", + "title": "CodeTool" + }, + { + "$ref": "#/components/schemas/CreateComputerToolDTO", + "title": "ComputerTool" + }, + { + "$ref": "#/components/schemas/CreateDtmfToolDTO", + "title": "DtmfTool" + }, + { + "$ref": "#/components/schemas/CreateEndCallToolDTO", + "title": "EndCallTool" + }, + { + "$ref": "#/components/schemas/CreateFunctionToolDTO", + "title": "FunctionTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelCalendarAvailabilityToolDTO", + "title": "GoHighLevelCalendarAvailabilityTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelCalendarEventCreateToolDTO", + "title": "GoHighLevelCalendarEventCreateTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelContactCreateToolDTO", + "title": "GoHighLevelContactCreateTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelContactGetToolDTO", + "title": "GoHighLevelContactGetTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarCheckAvailabilityToolDTO", + "title": "GoogleCalendarCheckAvailabilityTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarCreateEventToolDTO", + "title": "GoogleCalendarCreateEventTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleSheetsRowAppendToolDTO", + "title": "GoogleSheetsRowAppendTool" + }, + { + "$ref": "#/components/schemas/CreateHandoffToolDTO", + "title": "HandoffTool" + }, + { + "$ref": "#/components/schemas/CreateMcpToolDTO", + "title": "McpTool" + }, + { + "$ref": "#/components/schemas/CreateQueryToolDTO", + "title": "QueryTool" + }, + { + "$ref": "#/components/schemas/CreateSlackSendMessageToolDTO", + "title": "SlackSendMessageTool" + }, + { + "$ref": "#/components/schemas/CreateSmsToolDTO", + "title": "SmsTool" + }, + { + "$ref": "#/components/schemas/CreateTextEditorToolDTO", + "title": "TextEditorTool" + }, + { + "$ref": "#/components/schemas/CreateTransferCallToolDTO", + "title": "TransferCallTool" + }, + { + "$ref": "#/components/schemas/CreateSipRequestToolDTO", + "title": "SipRequestTool" + }, + { + "$ref": "#/components/schemas/CreateVoicemailToolDTO", + "title": "VoicemailTool" + } + ] + } }, - "isCustomHumeVoice": { - "type": "boolean", - "description": "Indicates whether the chosen voice is a preset Hume AI voice or a custom voice.", - "example": false + "toolIds": { + "description": "These are the tools that the assistant can use during the call. To use transient tools, use `tools`.\n\nBoth `tools` and `toolIds` can be used together.", + "type": "array", + "items": { + "type": "string" + } }, - "chunkPlan": { - "description": "This is the plan for chunking the model output before it is sent to the voice provider.", - "allOf": [ + "toolRefs": { + "description": "These are version-pinned references to tools. Each entry pins a specific\nversion of a tool by `(toolId, version)`. When the same `toolId` appears\nin both `toolIds` and `toolRefs[]`, the `toolRefs` pin wins (the\n`toolIds` entry is dropped at write time).", + "type": "array", + "items": { + "$ref": "#/components/schemas/ToolRef" + } + }, + "knowledgeBase": { + "description": "These are the options for the knowledge base.", + "oneOf": [ { - "$ref": "#/components/schemas/ChunkPlan" + "$ref": "#/components/schemas/CreateCustomKnowledgeBaseDTO", + "title": "Custom" } ] }, - "description": { + "model": { "type": "string", - "description": "Natural language instructions describing how the synthesized speech should sound, including but not limited to tone, intonation, pacing, and accent (e.g., 'a soft, gentle voice with a strong British accent').\n\nIf a Voice is specified in the request, this description serves as acting instructions.\nIf no Voice is specified, a new voice is generated based on this description." - }, - "fallbackPlan": { - "description": "This is the plan for voice provider fallbacks in the event that the primary voice provider fails.", - "allOf": [ - { - "$ref": "#/components/schemas/FallbackPlan" - } + "description": "The specific Anthropic/Claude model that will be used.", + "enum": [ + "claude-3-opus-20240229", + "claude-3-sonnet-20240229", + "claude-3-haiku-20240307", + "claude-3-5-sonnet-20240620", + "claude-3-5-sonnet-20241022", + "claude-3-5-haiku-20241022", + "claude-3-7-sonnet-20250219", + "claude-opus-4-20250514", + "claude-opus-4-5-20251101", + "claude-opus-4-6", + "claude-sonnet-4-20250514", + "claude-sonnet-4-5-20250929", + "claude-sonnet-4-6", + "claude-sonnet-5", + "claude-haiku-4-5-20251001" ] - } - }, - "required": [ - "provider", - "voiceId" - ] - }, - "LMNTVoice": { - "type": "object", - "properties": { - "cachingEnabled": { - "type": "boolean", - "description": "This is the flag to toggle voice caching for the assistant.", - "example": true, - "default": true }, "provider": { "type": "string", - "description": "This is the voice provider that will be used.", + "description": "The provider identifier for Anthropic.", "enum": [ - "lmnt" + "anthropic" ] }, - "voiceId": { - "description": "This is the provider-specific ID that will be used.", - "oneOf": [ - { - "type": "string", - "enum": [ - "amy", - "ansel", - "autumn", - "ava", - "brandon", - "caleb", - "cassian", - "chloe", - "dalton", - "daniel", - "dustin", - "elowen", - "evander", - "huxley", - "james", - "juniper", - "kennedy", - "lauren", - "leah", - "lily", - "lucas", - "magnus", - "miles", - "morgan", - "natalie", - "nathan", - "noah", - "nyssa", - "oliver", - "paige", - "ryan", - "sadie", - "sophie", - "stella", - "terrence", - "tyler", - "vesper", - "violet", - "warrick", - "zain", - "zeke", - "zoe" - ], - "title": "Preset Voice Options" - }, + "thinking": { + "description": "Optional configuration for Anthropic's thinking feature.\nOnly applicable for claude-3-7-sonnet-20250219 model.\nIf provided, maxTokens must be greater than thinking.budgetTokens.", + "allOf": [ { - "type": "string", - "title": "LMNT Voice ID" + "$ref": "#/components/schemas/AnthropicThinkingConfig" } ] }, - "speed": { + "temperature": { "type": "number", - "description": "This is the speed multiplier that will be used.", - "minimum": 0.25, - "maximum": 2, - "example": null + "description": "This is the temperature that will be used for calls. Default is 0.5.", + "minimum": 0, + "maximum": 2 }, - "language": { - "description": "Two letter ISO 639-1 language code. Use \"auto\" for auto-detection.", - "enum": [ - "aa", - "ab", - "ae", - "af", - "ak", - "am", - "an", - "ar", - "as", - "av", - "ay", - "az", - "ba", - "be", - "bg", - "bh", - "bi", - "bm", - "bn", - "bo", - "br", - "bs", - "ca", - "ce", - "ch", - "co", - "cr", - "cs", - "cu", - "cv", - "cy", - "da", - "de", - "dv", - "dz", - "ee", - "el", - "en", - "eo", - "es", - "et", - "eu", - "fa", - "ff", - "fi", - "fj", - "fo", - "fr", - "fy", - "ga", - "gd", - "gl", - "gn", - "gu", - "gv", - "ha", - "he", - "hi", - "ho", - "hr", - "ht", - "hu", - "hy", - "hz", - "ia", - "id", - "ie", - "ig", - "ii", - "ik", - "io", - "is", - "it", - "iu", - "ja", - "jv", - "ka", - "kg", - "ki", - "kj", - "kk", - "kl", - "km", - "kn", - "ko", - "kr", - "ks", - "ku", - "kv", - "kw", - "ky", - "la", - "lb", - "lg", - "li", - "ln", - "lo", - "lt", - "lu", - "lv", - "mg", - "mh", - "mi", - "mk", - "ml", - "mn", - "mr", - "ms", - "mt", - "my", - "na", - "nb", - "nd", - "ne", - "ng", - "nl", - "nn", - "no", - "nr", - "nv", - "ny", - "oc", - "oj", - "om", - "or", - "os", - "pa", - "pi", - "pl", - "ps", - "pt", - "qu", - "rm", - "rn", - "ro", - "ru", - "rw", - "sa", - "sc", - "sd", - "se", - "sg", - "si", - "sk", - "sl", - "sm", - "sn", - "so", - "sq", - "sr", - "ss", - "st", - "su", - "sv", - "sw", - "ta", - "te", - "tg", - "th", - "ti", - "tk", - "tl", - "tn", - "to", - "tr", - "ts", - "tt", - "tw", - "ty", - "ug", - "uk", - "ur", - "uz", - "ve", - "vi", - "vo", - "wa", - "wo", - "xh", - "yi", - "yue", - "yo", - "za", - "zh", - "zu", - "auto" - ], - "example": "en", - "oneOf": [ - { - "type": "string", - "enum": [ - "aa", - "ab", - "ae", - "af", - "ak", - "am", - "an", - "ar", - "as", - "av", - "ay", - "az", - "ba", - "be", - "bg", - "bh", - "bi", - "bm", - "bn", - "bo", - "br", - "bs", - "ca", - "ce", - "ch", - "co", - "cr", - "cs", - "cu", - "cv", - "cy", - "da", - "de", - "dv", - "dz", - "ee", - "el", - "en", - "eo", - "es", - "et", - "eu", - "fa", - "ff", - "fi", - "fj", - "fo", - "fr", - "fy", - "ga", - "gd", - "gl", - "gn", - "gu", - "gv", - "ha", - "he", - "hi", - "ho", - "hr", - "ht", - "hu", - "hy", - "hz", - "ia", - "id", - "ie", - "ig", - "ii", - "ik", - "io", - "is", - "it", - "iu", - "ja", - "jv", - "ka", - "kg", - "ki", - "kj", - "kk", - "kl", - "km", - "kn", - "ko", - "kr", - "ks", - "ku", - "kv", - "kw", - "ky", - "la", - "lb", - "lg", - "li", - "ln", - "lo", - "lt", - "lu", - "lv", - "mg", - "mh", - "mi", - "mk", - "ml", - "mn", - "mr", - "ms", - "mt", - "my", - "na", - "nb", - "nd", - "ne", - "ng", - "nl", - "nn", - "no", - "nr", - "nv", - "ny", - "oc", - "oj", - "om", - "or", - "os", - "pa", - "pi", - "pl", - "ps", - "pt", - "qu", - "rm", - "rn", - "ro", - "ru", - "rw", - "sa", - "sc", - "sd", - "se", - "sg", - "si", - "sk", - "sl", - "sm", - "sn", - "so", - "sq", - "sr", - "ss", - "st", - "su", - "sv", - "sw", - "ta", - "te", - "tg", - "th", - "ti", - "tk", - "tl", - "tn", - "to", - "tr", - "ts", - "tt", - "tw", - "ty", - "ug", - "uk", - "ur", - "uz", - "ve", - "vi", - "vo", - "wa", - "wo", - "xh", - "yi", - "yue", - "yo", - "za", - "zh", - "zu" - ], - "title": "ISO 639-1 Language Code" - }, - { - "type": "string", - "enum": [ - "auto" - ], - "title": "Auto-detect" - } - ] + "maxTokens": { + "type": "number", + "description": "This is the max number of tokens that the assistant will be allowed to generate in each turn of the conversation. Default is 250.", + "minimum": 50, + "maximum": 10000 }, - "chunkPlan": { - "description": "This is the plan for chunking the model output before it is sent to the voice provider.", - "allOf": [ - { - "$ref": "#/components/schemas/ChunkPlan" - } - ] + "emotionRecognitionEnabled": { + "type": "boolean", + "description": "This determines whether we detect user's emotion while they speak and send it as an additional info to model.\n\nDefault `false` because the model is usually are good at understanding the user's emotion from text.\n\n@default false" }, - "fallbackPlan": { - "description": "This is the plan for voice provider fallbacks in the event that the primary voice provider fails.", - "allOf": [ - { - "$ref": "#/components/schemas/FallbackPlan" - } - ] + "numFastTurns": { + "type": "number", + "description": "This sets how many turns at the start of the conversation to use a smaller, faster model from the same provider before switching to the primary model. Example, gpt-3.5-turbo if provider is openai.\n\nDefault is 0.\n\n@default 0", + "minimum": 0 } }, "required": [ - "provider", - "voiceId" + "model", + "provider" ] }, - "NeuphonicVoice": { + "AnthropicBedrockModel": { "type": "object", "properties": { - "cachingEnabled": { - "type": "boolean", - "description": "This is the flag to toggle voice caching for the assistant.", - "example": true, - "default": true + "messages": { + "description": "This is the starting state for the conversation.", + "type": "array", + "items": { + "$ref": "#/components/schemas/OpenAIMessage" + } }, - "provider": { - "type": "string", - "description": "This is the voice provider that will be used.", - "enum": [ - "neuphonic" - ] + "tools": { + "type": "array", + "description": "These are the tools that the assistant can use during the call. To use existing tools, use `toolIds`.\n\nBoth `tools` and `toolIds` can be used together.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/CreateApiRequestToolDTO", + "title": "ApiRequestTool" + }, + { + "$ref": "#/components/schemas/CreateBashToolDTO", + "title": "BashTool" + }, + { + "$ref": "#/components/schemas/CreateCodeToolDTO", + "title": "CodeTool" + }, + { + "$ref": "#/components/schemas/CreateComputerToolDTO", + "title": "ComputerTool" + }, + { + "$ref": "#/components/schemas/CreateDtmfToolDTO", + "title": "DtmfTool" + }, + { + "$ref": "#/components/schemas/CreateEndCallToolDTO", + "title": "EndCallTool" + }, + { + "$ref": "#/components/schemas/CreateFunctionToolDTO", + "title": "FunctionTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelCalendarAvailabilityToolDTO", + "title": "GoHighLevelCalendarAvailabilityTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelCalendarEventCreateToolDTO", + "title": "GoHighLevelCalendarEventCreateTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelContactCreateToolDTO", + "title": "GoHighLevelContactCreateTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelContactGetToolDTO", + "title": "GoHighLevelContactGetTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarCheckAvailabilityToolDTO", + "title": "GoogleCalendarCheckAvailabilityTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarCreateEventToolDTO", + "title": "GoogleCalendarCreateEventTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleSheetsRowAppendToolDTO", + "title": "GoogleSheetsRowAppendTool" + }, + { + "$ref": "#/components/schemas/CreateHandoffToolDTO", + "title": "HandoffTool" + }, + { + "$ref": "#/components/schemas/CreateMcpToolDTO", + "title": "McpTool" + }, + { + "$ref": "#/components/schemas/CreateQueryToolDTO", + "title": "QueryTool" + }, + { + "$ref": "#/components/schemas/CreateSlackSendMessageToolDTO", + "title": "SlackSendMessageTool" + }, + { + "$ref": "#/components/schemas/CreateSmsToolDTO", + "title": "SmsTool" + }, + { + "$ref": "#/components/schemas/CreateTextEditorToolDTO", + "title": "TextEditorTool" + }, + { + "$ref": "#/components/schemas/CreateTransferCallToolDTO", + "title": "TransferCallTool" + }, + { + "$ref": "#/components/schemas/CreateSipRequestToolDTO", + "title": "SipRequestTool" + }, + { + "$ref": "#/components/schemas/CreateVoicemailToolDTO", + "title": "VoicemailTool" + } + ] + } }, - "voiceId": { - "description": "This is the provider-specific ID that will be used.", + "toolIds": { + "description": "These are the tools that the assistant can use during the call. To use transient tools, use `tools`.\n\nBoth `tools` and `toolIds` can be used together.", + "type": "array", + "items": { + "type": "string" + } + }, + "toolRefs": { + "description": "These are version-pinned references to tools. Each entry pins a specific\nversion of a tool by `(toolId, version)`. When the same `toolId` appears\nin both `toolIds` and `toolRefs[]`, the `toolRefs` pin wins (the\n`toolIds` entry is dropped at write time).", + "type": "array", + "items": { + "$ref": "#/components/schemas/ToolRef" + } + }, + "knowledgeBase": { + "description": "These are the options for the knowledge base.", "oneOf": [ { - "type": "string", - "enum": [], - "title": "Preset Voice Options" - }, - { - "type": "string", - "title": "Neuphonic Voice ID" + "$ref": "#/components/schemas/CreateCustomKnowledgeBaseDTO", + "title": "Custom" } ] }, - "model": { + "provider": { "type": "string", - "description": "This is the model that will be used. Defaults to 'neu_fast' if not specified.", + "description": "The provider identifier for Anthropic via AWS Bedrock.", "enum": [ - "neu_hq", - "neu_fast" - ], - "example": "neu_fast" + "anthropic-bedrock" + ] }, - "language": { - "type": "object", - "description": "This is the language (ISO 639-1) that is enforced for the model.", - "example": "en" - }, - "speed": { - "type": "number", - "description": "This is the speed multiplier that will be used.", - "minimum": 0.25, - "maximum": 2, - "example": null - }, - "chunkPlan": { - "description": "This is the plan for chunking the model output before it is sent to the voice provider.", - "allOf": [ - { - "$ref": "#/components/schemas/ChunkPlan" - } + "model": { + "type": "string", + "description": "The specific Anthropic/Claude model that will be used via Bedrock.", + "enum": [ + "claude-3-opus-20240229", + "claude-3-sonnet-20240229", + "claude-3-haiku-20240307", + "claude-3-5-sonnet-20240620", + "claude-3-5-sonnet-20241022", + "claude-3-5-haiku-20241022", + "claude-3-7-sonnet-20250219", + "claude-opus-4-20250514", + "claude-opus-4-5-20251101", + "claude-opus-4-6", + "claude-sonnet-4-20250514", + "claude-sonnet-4-5-20250929", + "claude-sonnet-4-6", + "claude-haiku-4-5-20251001", + "global.anthropic.claude-haiku-4-5-20251001-v1:0" ] }, - "fallbackPlan": { - "description": "This is the plan for voice provider fallbacks in the event that the primary voice provider fails.", + "thinking": { + "description": "Optional configuration for Anthropic's thinking feature.\nOnly applicable for claude-3-7-sonnet-20250219 model.\nIf provided, maxTokens must be greater than thinking.budgetTokens.", "allOf": [ { - "$ref": "#/components/schemas/FallbackPlan" + "$ref": "#/components/schemas/AnthropicThinkingConfig" } ] + }, + "temperature": { + "type": "number", + "description": "This is the temperature that will be used for calls. Default is 0.5.", + "minimum": 0, + "maximum": 2 + }, + "maxTokens": { + "type": "number", + "description": "This is the max number of tokens that the assistant will be allowed to generate in each turn of the conversation. Default is 250.", + "minimum": 50, + "maximum": 10000 + }, + "emotionRecognitionEnabled": { + "type": "boolean", + "description": "This determines whether we detect user's emotion while they speak and send it as an additional info to model.\n\nDefault `false` because the model is usually are good at understanding the user's emotion from text.\n\n@default false" + }, + "numFastTurns": { + "type": "number", + "description": "This sets how many turns at the start of the conversation to use a smaller, faster model from the same provider before switching to the primary model. Example, gpt-3.5-turbo if provider is openai.\n\nDefault is 0.\n\n@default 0", + "minimum": 0 } }, "required": [ "provider", - "voiceId", - "language" + "model" ] }, - "OpenAIVoice": { + "CerebrasModel": { "type": "object", "properties": { - "cachingEnabled": { - "type": "boolean", - "description": "This is the flag to toggle voice caching for the assistant.", - "example": true, - "default": true + "messages": { + "description": "This is the starting state for the conversation.", + "type": "array", + "items": { + "$ref": "#/components/schemas/OpenAIMessage" + } }, - "provider": { - "type": "string", - "description": "This is the voice provider that will be used.", - "enum": [ - "openai" - ] + "tools": { + "type": "array", + "description": "These are the tools that the assistant can use during the call. To use existing tools, use `toolIds`.\n\nBoth `tools` and `toolIds` can be used together.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/CreateApiRequestToolDTO", + "title": "ApiRequestTool" + }, + { + "$ref": "#/components/schemas/CreateBashToolDTO", + "title": "BashTool" + }, + { + "$ref": "#/components/schemas/CreateCodeToolDTO", + "title": "CodeTool" + }, + { + "$ref": "#/components/schemas/CreateComputerToolDTO", + "title": "ComputerTool" + }, + { + "$ref": "#/components/schemas/CreateDtmfToolDTO", + "title": "DtmfTool" + }, + { + "$ref": "#/components/schemas/CreateEndCallToolDTO", + "title": "EndCallTool" + }, + { + "$ref": "#/components/schemas/CreateFunctionToolDTO", + "title": "FunctionTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelCalendarAvailabilityToolDTO", + "title": "GoHighLevelCalendarAvailabilityTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelCalendarEventCreateToolDTO", + "title": "GoHighLevelCalendarEventCreateTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelContactCreateToolDTO", + "title": "GoHighLevelContactCreateTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelContactGetToolDTO", + "title": "GoHighLevelContactGetTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarCheckAvailabilityToolDTO", + "title": "GoogleCalendarCheckAvailabilityTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarCreateEventToolDTO", + "title": "GoogleCalendarCreateEventTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleSheetsRowAppendToolDTO", + "title": "GoogleSheetsRowAppendTool" + }, + { + "$ref": "#/components/schemas/CreateHandoffToolDTO", + "title": "HandoffTool" + }, + { + "$ref": "#/components/schemas/CreateMcpToolDTO", + "title": "McpTool" + }, + { + "$ref": "#/components/schemas/CreateQueryToolDTO", + "title": "QueryTool" + }, + { + "$ref": "#/components/schemas/CreateSlackSendMessageToolDTO", + "title": "SlackSendMessageTool" + }, + { + "$ref": "#/components/schemas/CreateSmsToolDTO", + "title": "SmsTool" + }, + { + "$ref": "#/components/schemas/CreateTextEditorToolDTO", + "title": "TextEditorTool" + }, + { + "$ref": "#/components/schemas/CreateTransferCallToolDTO", + "title": "TransferCallTool" + }, + { + "$ref": "#/components/schemas/CreateSipRequestToolDTO", + "title": "SipRequestTool" + }, + { + "$ref": "#/components/schemas/CreateVoicemailToolDTO", + "title": "VoicemailTool" + } + ] + } }, - "voiceId": { - "description": "This is the provider-specific ID that will be used.\nPlease note that ash, ballad, coral, sage, and verse may only be used with realtime models.", + "toolIds": { + "description": "These are the tools that the assistant can use during the call. To use transient tools, use `tools`.\n\nBoth `tools` and `toolIds` can be used together.", + "type": "array", + "items": { + "type": "string" + } + }, + "toolRefs": { + "description": "These are version-pinned references to tools. Each entry pins a specific\nversion of a tool by `(toolId, version)`. When the same `toolId` appears\nin both `toolIds` and `toolRefs[]`, the `toolRefs` pin wins (the\n`toolIds` entry is dropped at write time).", + "type": "array", + "items": { + "$ref": "#/components/schemas/ToolRef" + } + }, + "knowledgeBase": { + "description": "These are the options for the knowledge base.", "oneOf": [ { - "type": "string", - "enum": [ - "alloy", - "echo", - "fable", - "onyx", - "nova", - "shimmer" - ], - "title": "Preset Voice Options" - }, - { - "type": "string", - "title": "OpenAI Voice ID" + "$ref": "#/components/schemas/CreateCustomKnowledgeBaseDTO", + "title": "Custom" } ] }, "model": { "type": "string", - "description": "This is the model that will be used for text-to-speech.", + "description": "This is the name of the model. Ex. cognitivecomputations/dolphin-mixtral-8x7b", "enum": [ - "tts-1", - "tts-1-hd", - "gpt-4o-mini-tts" + "llama3.1-8b", + "llama-3.3-70b" ] }, - "instructions": { + "provider": { "type": "string", - "description": "This is a prompt that allows you to control the voice of your generated audio.\nDoes not work with 'tts-1' or 'tts-1-hd' models.", - "maxLength": 10000 + "enum": [ + "cerebras" + ] }, - "speed": { + "temperature": { "type": "number", - "description": "This is the speed multiplier that will be used.", - "minimum": 0.25, - "maximum": 4, - "example": null + "description": "This is the temperature that will be used for calls. Default is 0.5.", + "minimum": 0, + "maximum": 2 }, - "chunkPlan": { - "description": "This is the plan for chunking the model output before it is sent to the voice provider.", - "allOf": [ - { - "$ref": "#/components/schemas/ChunkPlan" - } - ] + "maxTokens": { + "type": "number", + "description": "This is the max number of tokens that the assistant will be allowed to generate in each turn of the conversation. Default is 250.", + "minimum": 50, + "maximum": 10000 }, - "fallbackPlan": { - "description": "This is the plan for voice provider fallbacks in the event that the primary voice provider fails.", - "allOf": [ - { - "$ref": "#/components/schemas/FallbackPlan" - } - ] + "emotionRecognitionEnabled": { + "type": "boolean", + "description": "This determines whether we detect user's emotion while they speak and send it as an additional info to model.\n\nDefault `false` because the model is usually are good at understanding the user's emotion from text.\n\n@default false" + }, + "numFastTurns": { + "type": "number", + "description": "This sets how many turns at the start of the conversation to use a smaller, faster model from the same provider before switching to the primary model. Example, gpt-3.5-turbo if provider is openai.\n\nDefault is 0.\n\n@default 0", + "minimum": 0 } }, "required": [ - "provider", - "voiceId" + "model", + "provider" ] }, - "PlayHTVoice": { + "CustomLLMModel": { "type": "object", "properties": { - "cachingEnabled": { - "type": "boolean", - "description": "This is the flag to toggle voice caching for the assistant.", - "example": true, - "default": true + "messages": { + "description": "This is the starting state for the conversation.", + "type": "array", + "items": { + "$ref": "#/components/schemas/OpenAIMessage" + } + }, + "tools": { + "type": "array", + "description": "These are the tools that the assistant can use during the call. To use existing tools, use `toolIds`.\n\nBoth `tools` and `toolIds` can be used together.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/CreateApiRequestToolDTO", + "title": "ApiRequestTool" + }, + { + "$ref": "#/components/schemas/CreateBashToolDTO", + "title": "BashTool" + }, + { + "$ref": "#/components/schemas/CreateCodeToolDTO", + "title": "CodeTool" + }, + { + "$ref": "#/components/schemas/CreateComputerToolDTO", + "title": "ComputerTool" + }, + { + "$ref": "#/components/schemas/CreateDtmfToolDTO", + "title": "DtmfTool" + }, + { + "$ref": "#/components/schemas/CreateEndCallToolDTO", + "title": "EndCallTool" + }, + { + "$ref": "#/components/schemas/CreateFunctionToolDTO", + "title": "FunctionTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelCalendarAvailabilityToolDTO", + "title": "GoHighLevelCalendarAvailabilityTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelCalendarEventCreateToolDTO", + "title": "GoHighLevelCalendarEventCreateTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelContactCreateToolDTO", + "title": "GoHighLevelContactCreateTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelContactGetToolDTO", + "title": "GoHighLevelContactGetTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarCheckAvailabilityToolDTO", + "title": "GoogleCalendarCheckAvailabilityTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarCreateEventToolDTO", + "title": "GoogleCalendarCreateEventTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleSheetsRowAppendToolDTO", + "title": "GoogleSheetsRowAppendTool" + }, + { + "$ref": "#/components/schemas/CreateHandoffToolDTO", + "title": "HandoffTool" + }, + { + "$ref": "#/components/schemas/CreateMcpToolDTO", + "title": "McpTool" + }, + { + "$ref": "#/components/schemas/CreateQueryToolDTO", + "title": "QueryTool" + }, + { + "$ref": "#/components/schemas/CreateSlackSendMessageToolDTO", + "title": "SlackSendMessageTool" + }, + { + "$ref": "#/components/schemas/CreateSmsToolDTO", + "title": "SmsTool" + }, + { + "$ref": "#/components/schemas/CreateTextEditorToolDTO", + "title": "TextEditorTool" + }, + { + "$ref": "#/components/schemas/CreateTransferCallToolDTO", + "title": "TransferCallTool" + }, + { + "$ref": "#/components/schemas/CreateSipRequestToolDTO", + "title": "SipRequestTool" + }, + { + "$ref": "#/components/schemas/CreateVoicemailToolDTO", + "title": "VoicemailTool" + } + ] + } + }, + "toolIds": { + "description": "These are the tools that the assistant can use during the call. To use transient tools, use `tools`.\n\nBoth `tools` and `toolIds` can be used together.", + "type": "array", + "items": { + "type": "string" + } + }, + "toolRefs": { + "description": "These are version-pinned references to tools. Each entry pins a specific\nversion of a tool by `(toolId, version)`. When the same `toolId` appears\nin both `toolIds` and `toolRefs[]`, the `toolRefs` pin wins (the\n`toolIds` entry is dropped at write time).", + "type": "array", + "items": { + "$ref": "#/components/schemas/ToolRef" + } + }, + "knowledgeBase": { + "description": "These are the options for the knowledge base.", + "oneOf": [ + { + "$ref": "#/components/schemas/CreateCustomKnowledgeBaseDTO", + "title": "Custom" + } + ] }, "provider": { "type": "string", - "description": "This is the voice provider that will be used.", + "description": "This is the provider that will be used for the model. Any service, including your own server, that is compatible with the OpenAI API can be used.", "enum": [ - "playht" + "custom-llm" ] }, - "voiceId": { - "description": "This is the provider-specific ID that will be used.", - "oneOf": [ - { - "type": "string", - "enum": [ - "jennifer", - "melissa", - "will", - "chris", - "matt", - "jack", - "ruby", - "davis", - "donna", - "michael" - ], - "title": "Preset Voice Options" - }, - { - "type": "string", - "title": "PlayHT Voice ID" - } + "metadataSendMode": { + "type": "string", + "description": "This determines whether metadata is sent in requests to the custom provider.\n\n- `off` will not send any metadata. payload will look like `{ messages }`\n- `variable` will send `assistant.metadata` as a variable on the payload. payload will look like `{ messages, metadata }`\n- `destructured` will send `assistant.metadata` fields directly on the payload. payload will look like `{ messages, ...metadata }`\n\nFurther, `variable` and `destructured` will send `call`, `phoneNumber`, and `customer` objects in the payload.\n\nDefault is `variable`.", + "enum": [ + "off", + "variable", + "destructured" ] }, - "speed": { - "type": "number", - "description": "This is the speed multiplier that will be used.", - "minimum": 0.1, - "maximum": 5, - "example": null + "headers": { + "type": "object", + "description": "Custom headers to send with requests. These headers can override default OpenAI headers except for Authorization (which should be specified using a custom-llm credential).", + "additionalProperties": { + "type": "string" + }, + "example": { + "X-Custom-Header": "value" + } }, - "temperature": { + "url": { + "type": "string", + "description": "These is the URL we'll use for the OpenAI client's `baseURL`. Ex. https://openrouter.ai/api/v1" + }, + "wordLevelConfidenceEnabled": { + "type": "boolean", + "description": "This determines whether the transcriber's word level confidence is sent in requests to the custom provider. Default is false.\nThis only works for Deepgram transcribers." + }, + "timeoutSeconds": { "type": "number", - "description": "A floating point number between 0, exclusive, and 2, inclusive. If equal to null or not provided, the model's default temperature will be used. The temperature parameter controls variance. Lower temperatures result in more predictable results, higher temperatures allow each run to vary more, so the voice may sound less like the baseline voice.", - "minimum": 0.1, - "maximum": 2, - "example": null + "description": "This sets the timeout for the connection to the custom provider without needing to stream any tokens back. Default is 20 seconds.", + "minimum": 0, + "maximum": 300 }, - "emotion": { + "model": { "type": "string", - "description": "An emotion to be applied to the speech.", - "enum": [ - "female_happy", - "female_sad", - "female_angry", - "female_fearful", - "female_disgust", - "female_surprised", - "male_happy", - "male_sad", - "male_angry", - "male_fearful", - "male_disgust", - "male_surprised" - ], - "example": null + "description": "This is the name of the model. Ex. cognitivecomputations/dolphin-mixtral-8x7b" }, - "voiceGuidance": { + "temperature": { "type": "number", - "description": "A number between 1 and 6. Use lower numbers to reduce how unique your chosen voice will be compared to other voices.", - "minimum": 1, - "maximum": 6, - "example": null + "description": "This is the temperature that will be used for calls. Default is 0.5.", + "minimum": 0, + "maximum": 2 }, - "styleGuidance": { + "maxTokens": { "type": "number", - "description": "A number between 1 and 30. Use lower numbers to to reduce how strong your chosen emotion will be. Higher numbers will create a very emotional performance.", - "minimum": 1, - "maximum": 30, - "example": null + "description": "This is the max number of tokens that the assistant will be allowed to generate in each turn of the conversation. Default is 250.", + "minimum": 50, + "maximum": 10000 }, - "textGuidance": { + "emotionRecognitionEnabled": { + "type": "boolean", + "description": "This determines whether we detect user's emotion while they speak and send it as an additional info to model.\n\nDefault `false` because the model is usually are good at understanding the user's emotion from text.\n\n@default false" + }, + "numFastTurns": { "type": "number", - "description": "A number between 1 and 2. This number influences how closely the generated speech adheres to the input text. Use lower values to create more fluid speech, but with a higher chance of deviating from the input text. Higher numbers will make the generated speech more accurate to the input text, ensuring that the words spoken align closely with the provided text.", - "minimum": 1, - "maximum": 2, - "example": null + "description": "This sets how many turns at the start of the conversation to use a smaller, faster model from the same provider before switching to the primary model. Example, gpt-3.5-turbo if provider is openai.\n\nDefault is 0.\n\n@default 0", + "minimum": 0 + } + }, + "required": [ + "provider", + "url", + "model" + ] + }, + "DeepInfraModel": { + "type": "object", + "properties": { + "messages": { + "description": "This is the starting state for the conversation.", + "type": "array", + "items": { + "$ref": "#/components/schemas/OpenAIMessage" + } }, - "model": { - "type": "string", - "description": "Playht voice model/engine to use.", - "enum": [ - "PlayHT2.0", - "PlayHT2.0-turbo", - "Play3.0-mini", - "PlayDialog" - ] + "tools": { + "type": "array", + "description": "These are the tools that the assistant can use during the call. To use existing tools, use `toolIds`.\n\nBoth `tools` and `toolIds` can be used together.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/CreateApiRequestToolDTO", + "title": "ApiRequestTool" + }, + { + "$ref": "#/components/schemas/CreateBashToolDTO", + "title": "BashTool" + }, + { + "$ref": "#/components/schemas/CreateCodeToolDTO", + "title": "CodeTool" + }, + { + "$ref": "#/components/schemas/CreateComputerToolDTO", + "title": "ComputerTool" + }, + { + "$ref": "#/components/schemas/CreateDtmfToolDTO", + "title": "DtmfTool" + }, + { + "$ref": "#/components/schemas/CreateEndCallToolDTO", + "title": "EndCallTool" + }, + { + "$ref": "#/components/schemas/CreateFunctionToolDTO", + "title": "FunctionTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelCalendarAvailabilityToolDTO", + "title": "GoHighLevelCalendarAvailabilityTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelCalendarEventCreateToolDTO", + "title": "GoHighLevelCalendarEventCreateTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelContactCreateToolDTO", + "title": "GoHighLevelContactCreateTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelContactGetToolDTO", + "title": "GoHighLevelContactGetTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarCheckAvailabilityToolDTO", + "title": "GoogleCalendarCheckAvailabilityTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarCreateEventToolDTO", + "title": "GoogleCalendarCreateEventTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleSheetsRowAppendToolDTO", + "title": "GoogleSheetsRowAppendTool" + }, + { + "$ref": "#/components/schemas/CreateHandoffToolDTO", + "title": "HandoffTool" + }, + { + "$ref": "#/components/schemas/CreateMcpToolDTO", + "title": "McpTool" + }, + { + "$ref": "#/components/schemas/CreateQueryToolDTO", + "title": "QueryTool" + }, + { + "$ref": "#/components/schemas/CreateSlackSendMessageToolDTO", + "title": "SlackSendMessageTool" + }, + { + "$ref": "#/components/schemas/CreateSmsToolDTO", + "title": "SmsTool" + }, + { + "$ref": "#/components/schemas/CreateTextEditorToolDTO", + "title": "TextEditorTool" + }, + { + "$ref": "#/components/schemas/CreateTransferCallToolDTO", + "title": "TransferCallTool" + }, + { + "$ref": "#/components/schemas/CreateSipRequestToolDTO", + "title": "SipRequestTool" + }, + { + "$ref": "#/components/schemas/CreateVoicemailToolDTO", + "title": "VoicemailTool" + } + ] + } }, - "language": { - "type": "string", - "description": "The language to use for the speech.", - "enum": [ - "afrikaans", - "albanian", - "amharic", - "arabic", - "bengali", - "bulgarian", - "catalan", - "croatian", - "czech", - "danish", - "dutch", - "english", - "french", - "galician", - "german", - "greek", - "hebrew", - "hindi", - "hungarian", - "indonesian", - "italian", - "japanese", - "korean", - "malay", - "mandarin", - "polish", - "portuguese", - "russian", - "serbian", - "spanish", - "swedish", - "tagalog", - "thai", - "turkish", - "ukrainian", - "urdu", - "xhosa" - ] + "toolIds": { + "description": "These are the tools that the assistant can use during the call. To use transient tools, use `tools`.\n\nBoth `tools` and `toolIds` can be used together.", + "type": "array", + "items": { + "type": "string" + } }, - "chunkPlan": { - "description": "This is the plan for chunking the model output before it is sent to the voice provider.", - "allOf": [ + "toolRefs": { + "description": "These are version-pinned references to tools. Each entry pins a specific\nversion of a tool by `(toolId, version)`. When the same `toolId` appears\nin both `toolIds` and `toolRefs[]`, the `toolRefs` pin wins (the\n`toolIds` entry is dropped at write time).", + "type": "array", + "items": { + "$ref": "#/components/schemas/ToolRef" + } + }, + "knowledgeBase": { + "description": "These are the options for the knowledge base.", + "oneOf": [ { - "$ref": "#/components/schemas/ChunkPlan" + "$ref": "#/components/schemas/CreateCustomKnowledgeBaseDTO", + "title": "Custom" } ] }, - "fallbackPlan": { - "description": "This is the plan for voice provider fallbacks in the event that the primary voice provider fails.", - "allOf": [ - { - "$ref": "#/components/schemas/FallbackPlan" - } + "provider": { + "type": "string", + "enum": [ + "deepinfra" ] + }, + "model": { + "type": "string", + "description": "This is the name of the model. Ex. cognitivecomputations/dolphin-mixtral-8x7b" + }, + "temperature": { + "type": "number", + "description": "This is the temperature that will be used for calls. Default is 0.5.", + "minimum": 0, + "maximum": 2 + }, + "maxTokens": { + "type": "number", + "description": "This is the max number of tokens that the assistant will be allowed to generate in each turn of the conversation. Default is 250.", + "minimum": 50, + "maximum": 10000 + }, + "emotionRecognitionEnabled": { + "type": "boolean", + "description": "This determines whether we detect user's emotion while they speak and send it as an additional info to model.\n\nDefault `false` because the model is usually are good at understanding the user's emotion from text.\n\n@default false" + }, + "numFastTurns": { + "type": "number", + "description": "This sets how many turns at the start of the conversation to use a smaller, faster model from the same provider before switching to the primary model. Example, gpt-3.5-turbo if provider is openai.\n\nDefault is 0.\n\n@default 0", + "minimum": 0 } }, "required": [ "provider", - "voiceId" + "model" ] }, - "RimeAIVoice": { + "DeepSeekModel": { "type": "object", "properties": { - "cachingEnabled": { - "type": "boolean", - "description": "This is the flag to toggle voice caching for the assistant.", - "example": true, - "default": true + "messages": { + "description": "This is the starting state for the conversation.", + "type": "array", + "items": { + "$ref": "#/components/schemas/OpenAIMessage" + } }, - "provider": { - "type": "string", - "description": "This is the voice provider that will be used.", - "enum": [ - "rime-ai" - ] + "tools": { + "type": "array", + "description": "These are the tools that the assistant can use during the call. To use existing tools, use `toolIds`.\n\nBoth `tools` and `toolIds` can be used together.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/CreateApiRequestToolDTO", + "title": "ApiRequestTool" + }, + { + "$ref": "#/components/schemas/CreateBashToolDTO", + "title": "BashTool" + }, + { + "$ref": "#/components/schemas/CreateCodeToolDTO", + "title": "CodeTool" + }, + { + "$ref": "#/components/schemas/CreateComputerToolDTO", + "title": "ComputerTool" + }, + { + "$ref": "#/components/schemas/CreateDtmfToolDTO", + "title": "DtmfTool" + }, + { + "$ref": "#/components/schemas/CreateEndCallToolDTO", + "title": "EndCallTool" + }, + { + "$ref": "#/components/schemas/CreateFunctionToolDTO", + "title": "FunctionTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelCalendarAvailabilityToolDTO", + "title": "GoHighLevelCalendarAvailabilityTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelCalendarEventCreateToolDTO", + "title": "GoHighLevelCalendarEventCreateTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelContactCreateToolDTO", + "title": "GoHighLevelContactCreateTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelContactGetToolDTO", + "title": "GoHighLevelContactGetTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarCheckAvailabilityToolDTO", + "title": "GoogleCalendarCheckAvailabilityTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarCreateEventToolDTO", + "title": "GoogleCalendarCreateEventTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleSheetsRowAppendToolDTO", + "title": "GoogleSheetsRowAppendTool" + }, + { + "$ref": "#/components/schemas/CreateHandoffToolDTO", + "title": "HandoffTool" + }, + { + "$ref": "#/components/schemas/CreateMcpToolDTO", + "title": "McpTool" + }, + { + "$ref": "#/components/schemas/CreateQueryToolDTO", + "title": "QueryTool" + }, + { + "$ref": "#/components/schemas/CreateSlackSendMessageToolDTO", + "title": "SlackSendMessageTool" + }, + { + "$ref": "#/components/schemas/CreateSmsToolDTO", + "title": "SmsTool" + }, + { + "$ref": "#/components/schemas/CreateTextEditorToolDTO", + "title": "TextEditorTool" + }, + { + "$ref": "#/components/schemas/CreateTransferCallToolDTO", + "title": "TransferCallTool" + }, + { + "$ref": "#/components/schemas/CreateSipRequestToolDTO", + "title": "SipRequestTool" + }, + { + "$ref": "#/components/schemas/CreateVoicemailToolDTO", + "title": "VoicemailTool" + } + ] + } }, - "voiceId": { - "description": "This is the provider-specific ID that will be used.", + "toolIds": { + "description": "These are the tools that the assistant can use during the call. To use transient tools, use `tools`.\n\nBoth `tools` and `toolIds` can be used together.", + "type": "array", + "items": { + "type": "string" + } + }, + "toolRefs": { + "description": "These are version-pinned references to tools. Each entry pins a specific\nversion of a tool by `(toolId, version)`. When the same `toolId` appears\nin both `toolIds` and `toolRefs[]`, the `toolRefs` pin wins (the\n`toolIds` entry is dropped at write time).", + "type": "array", + "items": { + "$ref": "#/components/schemas/ToolRef" + } + }, + "knowledgeBase": { + "description": "These are the options for the knowledge base.", "oneOf": [ { - "type": "string", - "enum": [ - "abbie", - "allison", - "ally", - "alona", - "amber", - "ana", - "antoine", - "armon", - "brenda", - "brittany", - "carol", - "colin", - "courtney", - "elena", - "elliot", - "eva", - "geoff", - "gerald", - "hank", - "helen", - "hera", - "jen", - "joe", - "joy", - "juan", - "kendra", - "kendrick", - "kenneth", - "kevin", - "kris", - "linda", - "madison", - "marge", - "marina", - "marissa", - "marta", - "maya", - "nicholas", - "nyles", - "phil", - "reba", - "rex", - "rick", - "ritu", - "rob", - "rodney", - "rohan", - "rosco", - "samantha", - "sandy", - "selena", - "seth", - "sharon", - "stan", - "tamra", - "tanya", - "tibur", - "tj", - "tyler", - "viv", - "yadira", - "marsh", - "bayou", - "creek", - "brook", - "flower", - "spore", - "glacier", - "gulch", - "alpine", - "cove", - "lagoon", - "tundra", - "steppe", - "mesa", - "grove", - "rainforest", - "moraine", - "wildflower", - "peak", - "boulder", - "gypsum", - "zest", - "luna", - "celeste", - "orion", - "ursa", - "astra", - "esther", - "estelle", - "andromeda" - ], - "title": "Preset Voice Options" - }, - { - "type": "string", - "title": "RimeAI Voice ID" + "$ref": "#/components/schemas/CreateCustomKnowledgeBaseDTO", + "title": "Custom" } ] }, "model": { "type": "string", - "description": "This is the model that will be used. Defaults to 'arcana' when not specified.", + "description": "This is the name of the model. Ex. cognitivecomputations/dolphin-mixtral-8x7b", "enum": [ - "arcana", - "mistv2", - "mist" - ], - "example": "arcana" + "deepseek-chat", + "deepseek-reasoner" + ] }, - "speed": { - "type": "number", - "description": "This is the speed multiplier that will be used.", - "minimum": 0.1, - "example": null + "provider": { + "type": "string", + "enum": [ + "deep-seek" + ] }, - "pauseBetweenBrackets": { - "type": "boolean", - "description": "This is a flag that controls whether to add slight pauses using angle brackets. Example: \"Hi. <200> I'd love to have a conversation with you.\" adds a 200ms pause between the first and second sentences.", - "example": false + "temperature": { + "type": "number", + "description": "This is the temperature that will be used for calls. Default is 0.5.", + "minimum": 0, + "maximum": 2 }, - "phonemizeBetweenBrackets": { - "type": "boolean", - "description": "This is a flag that controls whether text inside brackets should be phonemized (converted to phonetic pronunciation) - Example: \"{h'El.o} World\" will pronounce \"Hello\" as expected.", - "example": false + "maxTokens": { + "type": "number", + "description": "This is the max number of tokens that the assistant will be allowed to generate in each turn of the conversation. Default is 250.", + "minimum": 50, + "maximum": 10000 }, - "reduceLatency": { + "emotionRecognitionEnabled": { "type": "boolean", - "description": "This is a flag that controls whether to optimize for reduced latency in streaming. https://docs.rime.ai/api-reference/endpoint/websockets#param-reduce-latency", - "example": false - }, - "inlineSpeedAlpha": { - "type": "string", - "description": "This is a string that allows inline speed control using alpha notation. https://docs.rime.ai/api-reference/endpoint/websockets#param-inline-speed-alpha", - "example": null - }, - "chunkPlan": { - "description": "This is the plan for chunking the model output before it is sent to the voice provider.", - "allOf": [ - { - "$ref": "#/components/schemas/ChunkPlan" - } - ] + "description": "This determines whether we detect user's emotion while they speak and send it as an additional info to model.\n\nDefault `false` because the model is usually are good at understanding the user's emotion from text.\n\n@default false" }, - "fallbackPlan": { - "description": "This is the plan for voice provider fallbacks in the event that the primary voice provider fails.", - "allOf": [ - { - "$ref": "#/components/schemas/FallbackPlan" - } - ] + "numFastTurns": { + "type": "number", + "description": "This sets how many turns at the start of the conversation to use a smaller, faster model from the same provider before switching to the primary model. Example, gpt-3.5-turbo if provider is openai.\n\nDefault is 0.\n\n@default 0", + "minimum": 0 } }, "required": [ - "provider", - "voiceId" + "model", + "provider" ] }, - "SesameVoice": { + "GeminiMultimodalLivePrebuiltVoiceConfig": { "type": "object", "properties": { - "cachingEnabled": { - "type": "boolean", - "description": "This is the flag to toggle voice caching for the assistant.", - "example": true, - "default": true - }, - "provider": { + "voiceName": { "type": "string", - "description": "This is the voice provider that will be used.", "enum": [ - "sesame" + "Puck", + "Charon", + "Kore", + "Fenrir", + "Aoede" ] + } + }, + "required": [ + "voiceName" + ] + }, + "GeminiMultimodalLiveVoiceConfig": { + "type": "object", + "properties": { + "prebuiltVoiceConfig": { + "$ref": "#/components/schemas/GeminiMultimodalLivePrebuiltVoiceConfig" + } + }, + "required": [ + "prebuiltVoiceConfig" + ] + }, + "GeminiMultimodalLiveSpeechConfig": { + "type": "object", + "properties": { + "voiceConfig": { + "$ref": "#/components/schemas/GeminiMultimodalLiveVoiceConfig" + } + }, + "required": [ + "voiceConfig" + ] + }, + "GoogleRealtimeConfig": { + "type": "object", + "properties": { + "topP": { + "type": "number", + "description": "This is the nucleus sampling parameter that controls the cumulative probability of tokens considered during text generation.\nOnly applicable with the Gemini Flash 2.0 Multimodal Live API." }, - "voiceId": { - "type": "string", - "description": "This is the provider-specific ID that will be used.", - "title": "Sesame Voice ID. This should be either a name (a built-in voice) or a UUID (a custom voice)." + "topK": { + "type": "number", + "description": "This is the top-k sampling parameter that limits the number of highest probability tokens considered during text generation.\nOnly applicable with the Gemini Flash 2.0 Multimodal Live API." }, - "model": { - "type": "string", - "description": "This is the model that will be used.", - "enum": [ - "csm-1b" - ] + "presencePenalty": { + "type": "number", + "description": "This is the presence penalty parameter that influences the model's likelihood to repeat information by penalizing tokens based on their presence in the text.\nOnly applicable with the Gemini Flash 2.0 Multimodal Live API." }, - "chunkPlan": { - "description": "This is the plan for chunking the model output before it is sent to the voice provider.", - "allOf": [ - { - "$ref": "#/components/schemas/ChunkPlan" - } - ] + "frequencyPenalty": { + "type": "number", + "description": "This is the frequency penalty parameter that influences the model's likelihood to repeat tokens by penalizing them based on their frequency in the text.\nOnly applicable with the Gemini Flash 2.0 Multimodal Live API." }, - "fallbackPlan": { - "description": "This is the plan for voice provider fallbacks in the event that the primary voice provider fails.", + "speechConfig": { + "description": "This is the speech configuration object that defines the voice settings to be used for the model's speech output.\nOnly applicable with the Gemini Flash 2.0 Multimodal Live API.", "allOf": [ { - "$ref": "#/components/schemas/FallbackPlan" + "$ref": "#/components/schemas/GeminiMultimodalLiveSpeechConfig" } ] } - }, - "required": [ - "provider", - "voiceId", - "model" - ] + } }, - "SmallestAIVoice": { + "GoogleModel": { "type": "object", "properties": { - "cachingEnabled": { - "type": "boolean", - "description": "This is the flag to toggle voice caching for the assistant.", - "example": true, - "default": true + "messages": { + "description": "This is the starting state for the conversation.", + "type": "array", + "items": { + "$ref": "#/components/schemas/OpenAIMessage" + } }, - "provider": { - "type": "string", - "description": "This is the voice provider that will be used.", - "enum": [ - "smallest-ai" - ] + "tools": { + "type": "array", + "description": "These are the tools that the assistant can use during the call. To use existing tools, use `toolIds`.\n\nBoth `tools` and `toolIds` can be used together.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/CreateApiRequestToolDTO", + "title": "ApiRequestTool" + }, + { + "$ref": "#/components/schemas/CreateBashToolDTO", + "title": "BashTool" + }, + { + "$ref": "#/components/schemas/CreateCodeToolDTO", + "title": "CodeTool" + }, + { + "$ref": "#/components/schemas/CreateComputerToolDTO", + "title": "ComputerTool" + }, + { + "$ref": "#/components/schemas/CreateDtmfToolDTO", + "title": "DtmfTool" + }, + { + "$ref": "#/components/schemas/CreateEndCallToolDTO", + "title": "EndCallTool" + }, + { + "$ref": "#/components/schemas/CreateFunctionToolDTO", + "title": "FunctionTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelCalendarAvailabilityToolDTO", + "title": "GoHighLevelCalendarAvailabilityTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelCalendarEventCreateToolDTO", + "title": "GoHighLevelCalendarEventCreateTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelContactCreateToolDTO", + "title": "GoHighLevelContactCreateTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelContactGetToolDTO", + "title": "GoHighLevelContactGetTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarCheckAvailabilityToolDTO", + "title": "GoogleCalendarCheckAvailabilityTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarCreateEventToolDTO", + "title": "GoogleCalendarCreateEventTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleSheetsRowAppendToolDTO", + "title": "GoogleSheetsRowAppendTool" + }, + { + "$ref": "#/components/schemas/CreateHandoffToolDTO", + "title": "HandoffTool" + }, + { + "$ref": "#/components/schemas/CreateMcpToolDTO", + "title": "McpTool" + }, + { + "$ref": "#/components/schemas/CreateQueryToolDTO", + "title": "QueryTool" + }, + { + "$ref": "#/components/schemas/CreateSlackSendMessageToolDTO", + "title": "SlackSendMessageTool" + }, + { + "$ref": "#/components/schemas/CreateSmsToolDTO", + "title": "SmsTool" + }, + { + "$ref": "#/components/schemas/CreateTextEditorToolDTO", + "title": "TextEditorTool" + }, + { + "$ref": "#/components/schemas/CreateTransferCallToolDTO", + "title": "TransferCallTool" + }, + { + "$ref": "#/components/schemas/CreateSipRequestToolDTO", + "title": "SipRequestTool" + }, + { + "$ref": "#/components/schemas/CreateVoicemailToolDTO", + "title": "VoicemailTool" + } + ] + } }, - "voiceId": { - "description": "This is the provider-specific ID that will be used.", + "toolIds": { + "description": "These are the tools that the assistant can use during the call. To use transient tools, use `tools`.\n\nBoth `tools` and `toolIds` can be used together.", + "type": "array", + "items": { + "type": "string" + } + }, + "toolRefs": { + "description": "These are version-pinned references to tools. Each entry pins a specific\nversion of a tool by `(toolId, version)`. When the same `toolId` appears\nin both `toolIds` and `toolRefs[]`, the `toolRefs` pin wins (the\n`toolIds` entry is dropped at write time).", + "type": "array", + "items": { + "$ref": "#/components/schemas/ToolRef" + } + }, + "knowledgeBase": { + "description": "These are the options for the knowledge base.", "oneOf": [ { - "type": "string", - "enum": [ - "emily", - "jasmine", - "arman", - "james", - "mithali", - "aravind", - "raj", - "diya", - "raman", - "ananya", - "isha", - "william", - "aarav", - "monika", - "niharika", - "deepika", - "raghav", - "kajal", - "radhika", - "mansi", - "nisha", - "saurabh", - "pooja", - "saina", - "sanya" - ], - "title": "Preset Voice Options" - }, - { - "type": "string", - "title": "Smallest AI Voice ID" + "$ref": "#/components/schemas/CreateCustomKnowledgeBaseDTO", + "title": "Custom" } ] }, "model": { "type": "string", - "description": "Smallest AI voice model to use. Defaults to 'lightning' when not specified.", + "description": "This is the Google model that will be used.", "enum": [ - "lightning" + "gemini-3.5-flash", + "gemini-3.1-flash-lite", + "gemini-3-flash-preview", + "gemini-2.5-pro", + "gemini-2.5-flash", + "gemini-2.5-flash-lite", + "gemini-2.0-flash-thinking-exp", + "gemini-2.0-pro-exp-02-05", + "gemini-2.0-flash", + "gemini-2.0-flash-lite", + "gemini-2.0-flash-exp", + "gemini-2.0-flash-realtime-exp", + "gemini-1.5-flash", + "gemini-1.5-flash-002", + "gemini-1.5-pro", + "gemini-1.5-pro-002", + "gemini-1.0-pro" ] }, - "speed": { - "type": "number", - "description": "This is the speed multiplier that will be used.", - "example": null - }, - "chunkPlan": { - "description": "This is the plan for chunking the model output before it is sent to the voice provider.", - "allOf": [ - { - "$ref": "#/components/schemas/ChunkPlan" - } + "provider": { + "type": "string", + "enum": [ + "google" ] }, - "fallbackPlan": { - "description": "This is the plan for voice provider fallbacks in the event that the primary voice provider fails.", + "realtimeConfig": { + "description": "This is the session configuration for the Gemini Flash 2.0 Multimodal Live API.\nOnly applicable if the model `gemini-2.0-flash-realtime-exp` is selected.", "allOf": [ { - "$ref": "#/components/schemas/FallbackPlan" + "$ref": "#/components/schemas/GoogleRealtimeConfig" } ] - } - }, - "required": [ - "provider", - "voiceId" - ] - }, - "TavusConversationProperties": { - "type": "object", - "properties": { - "maxCallDuration": { - "type": "number", - "description": "The maximum duration of the call in seconds. The default `maxCallDuration` is 3600 seconds (1 hour).\nOnce the time limit specified by this parameter has been reached, the conversation will automatically shut down." }, - "participantLeftTimeout": { + "temperature": { "type": "number", - "description": "The duration in seconds after which the call will be automatically shut down once the last participant leaves." + "description": "This is the temperature that will be used for calls. Default is 0.5.", + "minimum": 0, + "maximum": 2 }, - "participantAbsentTimeout": { + "maxTokens": { "type": "number", - "description": "Starting from conversation creation, the duration in seconds after which the call will be automatically shut down if no participant joins the call.\nDefault is 300 seconds (5 minutes)." - }, - "enableRecording": { - "type": "boolean", - "description": "If true, the user will be able to record the conversation." - }, - "enableTranscription": { - "type": "boolean", - "description": "If true, the user will be able to transcribe the conversation.\nYou can find more instructions on displaying transcriptions if you are using your custom DailyJS components here.\nYou need to have an event listener on Daily that listens for `app-messages`." + "description": "This is the max number of tokens that the assistant will be allowed to generate in each turn of the conversation. Default is 250.", + "minimum": 50, + "maximum": 10000 }, - "applyGreenscreen": { + "emotionRecognitionEnabled": { "type": "boolean", - "description": "If true, the background will be replaced with a greenscreen (RGB values: `[0, 255, 155]`).\nYou can use WebGL on the frontend to make the greenscreen transparent or change its color." - }, - "language": { - "type": "string", - "description": "The language of the conversation. Please provide the **full language name**, not the two-letter code.\nIf you are using your own TTS voice, please ensure it supports the language you provide.\nIf you are using a stock replica or default persona, please note that only ElevenLabs and Cartesia supported languages are available.\nYou can find a full list of supported languages for Cartesia here, for ElevenLabs here, and for PlayHT here." - }, - "recordingS3BucketName": { - "type": "string", - "description": "The name of the S3 bucket where the recording will be stored." - }, - "recordingS3BucketRegion": { - "type": "string", - "description": "The region of the S3 bucket where the recording will be stored." + "description": "This determines whether we detect user's emotion while they speak and send it as an additional info to model.\n\nDefault `false` because the model is usually are good at understanding the user's emotion from text.\n\n@default false" }, - "awsAssumeRoleArn": { - "type": "string", - "description": "The ARN of the role that will be assumed to access the S3 bucket." + "numFastTurns": { + "type": "number", + "description": "This sets how many turns at the start of the conversation to use a smaller, faster model from the same provider before switching to the primary model. Example, gpt-3.5-turbo if provider is openai.\n\nDefault is 0.\n\n@default 0", + "minimum": 0 } - } + }, + "required": [ + "model", + "provider" + ] }, - "TavusVoice": { + "GroqModel": { "type": "object", "properties": { - "cachingEnabled": { - "type": "boolean", - "description": "This is the flag to toggle voice caching for the assistant.", - "example": true, - "default": true + "messages": { + "description": "This is the starting state for the conversation.", + "type": "array", + "items": { + "$ref": "#/components/schemas/OpenAIMessage" + } }, - "provider": { - "type": "string", - "description": "This is the voice provider that will be used.", - "enum": [ - "tavus" - ] + "tools": { + "type": "array", + "description": "These are the tools that the assistant can use during the call. To use existing tools, use `toolIds`.\n\nBoth `tools` and `toolIds` can be used together.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/CreateApiRequestToolDTO", + "title": "ApiRequestTool" + }, + { + "$ref": "#/components/schemas/CreateBashToolDTO", + "title": "BashTool" + }, + { + "$ref": "#/components/schemas/CreateCodeToolDTO", + "title": "CodeTool" + }, + { + "$ref": "#/components/schemas/CreateComputerToolDTO", + "title": "ComputerTool" + }, + { + "$ref": "#/components/schemas/CreateDtmfToolDTO", + "title": "DtmfTool" + }, + { + "$ref": "#/components/schemas/CreateEndCallToolDTO", + "title": "EndCallTool" + }, + { + "$ref": "#/components/schemas/CreateFunctionToolDTO", + "title": "FunctionTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelCalendarAvailabilityToolDTO", + "title": "GoHighLevelCalendarAvailabilityTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelCalendarEventCreateToolDTO", + "title": "GoHighLevelCalendarEventCreateTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelContactCreateToolDTO", + "title": "GoHighLevelContactCreateTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelContactGetToolDTO", + "title": "GoHighLevelContactGetTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarCheckAvailabilityToolDTO", + "title": "GoogleCalendarCheckAvailabilityTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarCreateEventToolDTO", + "title": "GoogleCalendarCreateEventTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleSheetsRowAppendToolDTO", + "title": "GoogleSheetsRowAppendTool" + }, + { + "$ref": "#/components/schemas/CreateHandoffToolDTO", + "title": "HandoffTool" + }, + { + "$ref": "#/components/schemas/CreateMcpToolDTO", + "title": "McpTool" + }, + { + "$ref": "#/components/schemas/CreateQueryToolDTO", + "title": "QueryTool" + }, + { + "$ref": "#/components/schemas/CreateSlackSendMessageToolDTO", + "title": "SlackSendMessageTool" + }, + { + "$ref": "#/components/schemas/CreateSmsToolDTO", + "title": "SmsTool" + }, + { + "$ref": "#/components/schemas/CreateTextEditorToolDTO", + "title": "TextEditorTool" + }, + { + "$ref": "#/components/schemas/CreateTransferCallToolDTO", + "title": "TransferCallTool" + }, + { + "$ref": "#/components/schemas/CreateSipRequestToolDTO", + "title": "SipRequestTool" + }, + { + "$ref": "#/components/schemas/CreateVoicemailToolDTO", + "title": "VoicemailTool" + } + ] + } }, - "voiceId": { - "description": "This is the provider-specific ID that will be used.", - "oneOf": [ - { - "type": "string", - "enum": [ - "r52da2535a" - ], - "title": "Preset Voice Options" - }, - { - "type": "string", - "title": "Tavus Voice ID" - } - ] + "toolIds": { + "description": "These are the tools that the assistant can use during the call. To use transient tools, use `tools`.\n\nBoth `tools` and `toolIds` can be used together.", + "type": "array", + "items": { + "type": "string" + } }, - "chunkPlan": { - "description": "This is the plan for chunking the model output before it is sent to the voice provider.", - "allOf": [ + "toolRefs": { + "description": "These are version-pinned references to tools. Each entry pins a specific\nversion of a tool by `(toolId, version)`. When the same `toolId` appears\nin both `toolIds` and `toolRefs[]`, the `toolRefs` pin wins (the\n`toolIds` entry is dropped at write time).", + "type": "array", + "items": { + "$ref": "#/components/schemas/ToolRef" + } + }, + "knowledgeBase": { + "description": "These are the options for the knowledge base.", + "oneOf": [ { - "$ref": "#/components/schemas/ChunkPlan" + "$ref": "#/components/schemas/CreateCustomKnowledgeBaseDTO", + "title": "Custom" } ] }, - "personaId": { - "type": "string", - "description": "This is the unique identifier for the persona that the replica will use in the conversation." - }, - "callbackUrl": { + "model": { "type": "string", - "description": "This is the url that will receive webhooks with updates regarding the conversation state." + "description": "This is the name of the model. Ex. cognitivecomputations/dolphin-mixtral-8x7b", + "enum": [ + "openai/gpt-oss-20b", + "openai/gpt-oss-120b", + "deepseek-r1-distill-llama-70b", + "llama-3.3-70b-versatile", + "llama-3.1-405b-reasoning", + "llama-3.1-8b-instant", + "llama3-8b-8192", + "llama3-70b-8192", + "gemma2-9b-it", + "moonshotai/kimi-k2-instruct-0905", + "meta-llama/llama-4-scout-17b-16e-instruct", + "mistral-saba-24b", + "compound-beta", + "compound-beta-mini" + ] }, - "conversationName": { + "provider": { "type": "string", - "description": "This is the name for the conversation." + "enum": [ + "groq" + ] }, - "conversationalContext": { - "type": "string", - "description": "This is the context that will be appended to any context provided in the persona, if one is provided." + "temperature": { + "type": "number", + "description": "This is the temperature that will be used for calls. Default is 0.5.", + "minimum": 0, + "maximum": 2 }, - "customGreeting": { - "type": "string", - "description": "This is the custom greeting that the replica will give once a participant joines the conversation." + "maxTokens": { + "type": "number", + "description": "This is the max number of tokens that the assistant will be allowed to generate in each turn of the conversation. Default is 250.", + "minimum": 50, + "maximum": 10000 }, - "properties": { - "description": "These are optional properties used to customize the conversation.", - "allOf": [ - { - "$ref": "#/components/schemas/TavusConversationProperties" - } - ] + "emotionRecognitionEnabled": { + "type": "boolean", + "description": "This determines whether we detect user's emotion while they speak and send it as an additional info to model.\n\nDefault `false` because the model is usually are good at understanding the user's emotion from text.\n\n@default false" }, - "fallbackPlan": { - "description": "This is the plan for voice provider fallbacks in the event that the primary voice provider fails.", - "allOf": [ - { - "$ref": "#/components/schemas/FallbackPlan" - } - ] + "numFastTurns": { + "type": "number", + "description": "This sets how many turns at the start of the conversation to use a smaller, faster model from the same provider before switching to the primary model. Example, gpt-3.5-turbo if provider is openai.\n\nDefault is 0.\n\n@default 0", + "minimum": 0 } }, "required": [ - "provider", - "voiceId" + "model", + "provider" ] }, - "VapiVoice": { + "InflectionAIModel": { "type": "object", "properties": { - "cachingEnabled": { - "type": "boolean", - "description": "This is the flag to toggle voice caching for the assistant.", - "example": true, - "default": true - }, - "provider": { - "type": "string", - "description": "This is the voice provider that will be used.", - "enum": [ - "vapi" - ] - }, - "voiceId": { - "type": "string", - "description": "The voices provided by Vapi", - "enum": [ - "Elliot", - "Kylie", - "Rohan", - "Lily", - "Savannah", - "Hana", - "Neha", - "Cole", - "Harry", - "Paige", - "Spencer" - ] - }, - "speed": { - "type": "number", - "description": "This is the speed multiplier that will be used.\n\n@default 1", - "minimum": 0.25, - "maximum": 2, - "default": 1 + "messages": { + "description": "This is the starting state for the conversation.", + "type": "array", + "items": { + "$ref": "#/components/schemas/OpenAIMessage" + } }, - "chunkPlan": { - "description": "This is the plan for chunking the model output before it is sent to the voice provider.", - "allOf": [ - { - "$ref": "#/components/schemas/ChunkPlan" - } - ] + "tools": { + "type": "array", + "description": "These are the tools that the assistant can use during the call. To use existing tools, use `toolIds`.\n\nBoth `tools` and `toolIds` can be used together.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/CreateApiRequestToolDTO", + "title": "ApiRequestTool" + }, + { + "$ref": "#/components/schemas/CreateBashToolDTO", + "title": "BashTool" + }, + { + "$ref": "#/components/schemas/CreateCodeToolDTO", + "title": "CodeTool" + }, + { + "$ref": "#/components/schemas/CreateComputerToolDTO", + "title": "ComputerTool" + }, + { + "$ref": "#/components/schemas/CreateDtmfToolDTO", + "title": "DtmfTool" + }, + { + "$ref": "#/components/schemas/CreateEndCallToolDTO", + "title": "EndCallTool" + }, + { + "$ref": "#/components/schemas/CreateFunctionToolDTO", + "title": "FunctionTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelCalendarAvailabilityToolDTO", + "title": "GoHighLevelCalendarAvailabilityTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelCalendarEventCreateToolDTO", + "title": "GoHighLevelCalendarEventCreateTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelContactCreateToolDTO", + "title": "GoHighLevelContactCreateTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelContactGetToolDTO", + "title": "GoHighLevelContactGetTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarCheckAvailabilityToolDTO", + "title": "GoogleCalendarCheckAvailabilityTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarCreateEventToolDTO", + "title": "GoogleCalendarCreateEventTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleSheetsRowAppendToolDTO", + "title": "GoogleSheetsRowAppendTool" + }, + { + "$ref": "#/components/schemas/CreateHandoffToolDTO", + "title": "HandoffTool" + }, + { + "$ref": "#/components/schemas/CreateMcpToolDTO", + "title": "McpTool" + }, + { + "$ref": "#/components/schemas/CreateQueryToolDTO", + "title": "QueryTool" + }, + { + "$ref": "#/components/schemas/CreateSlackSendMessageToolDTO", + "title": "SlackSendMessageTool" + }, + { + "$ref": "#/components/schemas/CreateSmsToolDTO", + "title": "SmsTool" + }, + { + "$ref": "#/components/schemas/CreateTextEditorToolDTO", + "title": "TextEditorTool" + }, + { + "$ref": "#/components/schemas/CreateTransferCallToolDTO", + "title": "TransferCallTool" + }, + { + "$ref": "#/components/schemas/CreateSipRequestToolDTO", + "title": "SipRequestTool" + }, + { + "$ref": "#/components/schemas/CreateVoicemailToolDTO", + "title": "VoicemailTool" + } + ] + } }, - "fallbackPlan": { - "description": "This is the plan for voice provider fallbacks in the event that the primary voice provider fails.", - "allOf": [ + "toolIds": { + "description": "These are the tools that the assistant can use during the call. To use transient tools, use `tools`.\n\nBoth `tools` and `toolIds` can be used together.", + "type": "array", + "items": { + "type": "string" + } + }, + "toolRefs": { + "description": "These are version-pinned references to tools. Each entry pins a specific\nversion of a tool by `(toolId, version)`. When the same `toolId` appears\nin both `toolIds` and `toolRefs[]`, the `toolRefs` pin wins (the\n`toolIds` entry is dropped at write time).", + "type": "array", + "items": { + "$ref": "#/components/schemas/ToolRef" + } + }, + "knowledgeBase": { + "description": "These are the options for the knowledge base.", + "oneOf": [ { - "$ref": "#/components/schemas/FallbackPlan" + "$ref": "#/components/schemas/CreateCustomKnowledgeBaseDTO", + "title": "Custom" } ] - } - }, - "required": [ - "provider", - "voiceId" - ] - }, - "InworldVoice": { - "type": "object", - "properties": { - "cachingEnabled": { - "type": "boolean", - "description": "This is the flag to toggle voice caching for the assistant.", - "example": true, - "default": true }, - "provider": { + "model": { "type": "string", - "description": "This is the voice provider that will be used.", + "description": "This is the name of the model. Ex. cognitivecomputations/dolphin-mixtral-8x7b", "enum": [ - "inworld" + "inflection_3_pi" ] }, - "voiceId": { + "provider": { "type": "string", - "description": "Available voices by language:\n• en: Alex, Ashley, Craig, Deborah, Dennis, Edward, Elizabeth, Hades, Julia, Pixie, Mark, Olivia, Priya, Ronald, Sarah, Shaun, Theodore, Timothy, Wendy, Dominus\n• zh: Yichen, Xiaoyin, Xinyi, Jing\n• nl: Erik, Katrien, Lennart, Lore\n• fr: Alain, Hélène, Mathieu, Étienne\n• de: Johanna, Josef\n• it: Gianni, Orietta\n• ja: Asuka, Satoshi\n• ko: Hyunwoo, Minji, Seojun, Yoona\n• pl: Szymon, Wojciech\n• pt: Heitor, Maitê\n• es: Diego, Lupita, Miguel, Rafael", - "maxLength": 120, - "title": "Inworld Voice ID", "enum": [ - "Alex", - "Ashley", - "Craig", - "Deborah", - "Dennis", - "Edward", - "Elizabeth", - "Hades", - "Julia", - "Pixie", - "Mark", - "Olivia", - "Priya", - "Ronald", - "Sarah", - "Shaun", - "Theodore", - "Timothy", - "Wendy", - "Dominus", - "Yichen", - "Xiaoyin", - "Xinyi", - "Jing", - "Erik", - "Katrien", - "Lennart", - "Lore", - "Alain", - "Hélène", - "Mathieu", - "Étienne", - "Johanna", - "Josef", - "Gianni", - "Orietta", - "Asuka", - "Satoshi", - "Hyunwoo", - "Minji", - "Seojun", - "Yoona", - "Szymon", - "Wojciech", - "Heitor", - "Maitê", - "Diego", - "Lupita", - "Miguel", - "Rafael" - ], - "example": "Alex" + "inflection-ai" + ] }, - "model": { - "type": "string", - "description": "This is the model that will be used.", - "enum": [ - "inworld-tts-1" - ], - "default": "inworld-tts-1" + "temperature": { + "type": "number", + "description": "This is the temperature that will be used for calls. Default is 0.5.", + "minimum": 0, + "maximum": 2 }, - "languageCode": { - "type": "string", - "description": "Language code for Inworld TTS synthesis", - "default": "en", - "enum": [ - "en", - "zh", - "ko", - "nl", - "fr", - "es", - "ja", - "de", - "it", - "pl", - "pt" - ] + "maxTokens": { + "type": "number", + "description": "This is the max number of tokens that the assistant will be allowed to generate in each turn of the conversation. Default is 250.", + "minimum": 50, + "maximum": 10000 }, - "chunkPlan": { - "description": "This is the plan for chunking the model output before it is sent to the voice provider.", - "allOf": [ - { - "$ref": "#/components/schemas/ChunkPlan" - } - ] + "emotionRecognitionEnabled": { + "type": "boolean", + "description": "This determines whether we detect user's emotion while they speak and send it as an additional info to model.\n\nDefault `false` because the model is usually are good at understanding the user's emotion from text.\n\n@default false" }, - "fallbackPlan": { - "description": "This is the plan for voice provider fallbacks in the event that the primary voice provider fails.", - "allOf": [ - { - "$ref": "#/components/schemas/FallbackPlan" - } - ] + "numFastTurns": { + "type": "number", + "description": "This sets how many turns at the start of the conversation to use a smaller, faster model from the same provider before switching to the primary model. Example, gpt-3.5-turbo if provider is openai.\n\nDefault is 0.\n\n@default 0", + "minimum": 0 } }, "required": [ - "provider", - "voiceId" + "model", + "provider" ] }, - "MinimaxVoice": { + "MinimaxLLMModel": { "type": "object", "properties": { - "cachingEnabled": { - "type": "boolean", - "description": "This is the flag to toggle voice caching for the assistant.", - "example": true, - "default": true - }, - "provider": { - "type": "string", - "description": "This is the voice provider that will be used.", - "enum": [ - "minimax" - ] - }, - "voiceId": { - "type": "string", - "description": "This is the provider-specific ID that will be used. Use a voice from MINIMAX_PREDEFINED_VOICES or a custom cloned voice ID.", - "title": "This is the Minimax Voice ID" - }, - "model": { - "type": "string", - "description": "This is the model that will be used. Options are 'speech-02-hd' and 'speech-02-turbo'.\nspeech-02-hd is optimized for high-fidelity applications like voiceovers and audiobooks.\nspeech-02-turbo is designed for real-time applications with low latency.\n\n@default \"speech-02-turbo\"", - "enum": [ - "speech-02-hd", - "speech-02-turbo" - ], - "example": "speech-02-turbo", - "default": "speech-02-turbo" - }, - "emotion": { - "type": "string", - "description": "The emotion to use for the voice. If not provided, will use auto-detect mode.\nOptions include: 'happy', 'sad', 'angry', 'fearful', 'surprised', 'disgusted', 'neutral'", - "example": "happy" - }, - "pitch": { - "type": "number", - "description": "Voice pitch adjustment. Range from -12 to 12 semitones.\n@default 0", - "minimum": -12, - "maximum": 12, - "example": 0, - "default": 0 - }, - "speed": { - "type": "number", - "description": "Voice speed adjustment. Range from 0.5 to 2.0.\n@default 1.0", - "minimum": 0.5, - "maximum": 2, - "example": 1, - "default": 1 + "messages": { + "description": "This is the starting state for the conversation.", + "type": "array", + "items": { + "$ref": "#/components/schemas/OpenAIMessage" + } }, - "volume": { - "type": "number", - "description": "Voice volume adjustment. Range from 0.5 to 2.0.\n@default 1.0", - "minimum": 0.5, - "maximum": 2, - "example": 1, - "default": 1 + "tools": { + "type": "array", + "description": "These are the tools that the assistant can use during the call. To use existing tools, use `toolIds`.\n\nBoth `tools` and `toolIds` can be used together.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/CreateApiRequestToolDTO", + "title": "ApiRequestTool" + }, + { + "$ref": "#/components/schemas/CreateBashToolDTO", + "title": "BashTool" + }, + { + "$ref": "#/components/schemas/CreateCodeToolDTO", + "title": "CodeTool" + }, + { + "$ref": "#/components/schemas/CreateComputerToolDTO", + "title": "ComputerTool" + }, + { + "$ref": "#/components/schemas/CreateDtmfToolDTO", + "title": "DtmfTool" + }, + { + "$ref": "#/components/schemas/CreateEndCallToolDTO", + "title": "EndCallTool" + }, + { + "$ref": "#/components/schemas/CreateFunctionToolDTO", + "title": "FunctionTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelCalendarAvailabilityToolDTO", + "title": "GoHighLevelCalendarAvailabilityTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelCalendarEventCreateToolDTO", + "title": "GoHighLevelCalendarEventCreateTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelContactCreateToolDTO", + "title": "GoHighLevelContactCreateTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelContactGetToolDTO", + "title": "GoHighLevelContactGetTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarCheckAvailabilityToolDTO", + "title": "GoogleCalendarCheckAvailabilityTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarCreateEventToolDTO", + "title": "GoogleCalendarCreateEventTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleSheetsRowAppendToolDTO", + "title": "GoogleSheetsRowAppendTool" + }, + { + "$ref": "#/components/schemas/CreateHandoffToolDTO", + "title": "HandoffTool" + }, + { + "$ref": "#/components/schemas/CreateMcpToolDTO", + "title": "McpTool" + }, + { + "$ref": "#/components/schemas/CreateQueryToolDTO", + "title": "QueryTool" + }, + { + "$ref": "#/components/schemas/CreateSlackSendMessageToolDTO", + "title": "SlackSendMessageTool" + }, + { + "$ref": "#/components/schemas/CreateSmsToolDTO", + "title": "SmsTool" + }, + { + "$ref": "#/components/schemas/CreateTextEditorToolDTO", + "title": "TextEditorTool" + }, + { + "$ref": "#/components/schemas/CreateTransferCallToolDTO", + "title": "TransferCallTool" + }, + { + "$ref": "#/components/schemas/CreateSipRequestToolDTO", + "title": "SipRequestTool" + }, + { + "$ref": "#/components/schemas/CreateVoicemailToolDTO", + "title": "VoicemailTool" + } + ] + } }, - "region": { - "type": "string", - "description": "The region for Minimax API. Defaults to \"worldwide\".", - "enum": [ - "worldwide", - "china" - ], - "default": "worldwide" + "toolIds": { + "description": "These are the tools that the assistant can use during the call. To use transient tools, use `tools`.\n\nBoth `tools` and `toolIds` can be used together.", + "type": "array", + "items": { + "type": "string" + } }, - "chunkPlan": { - "description": "This is the plan for chunking the model output before it is sent to the voice provider.", - "allOf": [ - { - "$ref": "#/components/schemas/ChunkPlan" - } - ] + "toolRefs": { + "description": "These are version-pinned references to tools. Each entry pins a specific\nversion of a tool by `(toolId, version)`. When the same `toolId` appears\nin both `toolIds` and `toolRefs[]`, the `toolRefs` pin wins (the\n`toolIds` entry is dropped at write time).", + "type": "array", + "items": { + "$ref": "#/components/schemas/ToolRef" + } }, - "fallbackPlan": { - "description": "This is the plan for voice provider fallbacks in the event that the primary voice provider fails.", - "allOf": [ + "knowledgeBase": { + "description": "These are the options for the knowledge base.", + "oneOf": [ { - "$ref": "#/components/schemas/FallbackPlan" + "$ref": "#/components/schemas/CreateCustomKnowledgeBaseDTO", + "title": "Custom" } ] - } - }, - "required": [ - "provider", - "voiceId" - ] - }, - "FallbackAzureVoice": { - "type": "object", - "properties": { - "cachingEnabled": { - "type": "boolean", - "description": "This is the flag to toggle voice caching for the assistant.", - "example": true, - "default": true }, "provider": { "type": "string", - "description": "This is the voice provider that will be used.", "enum": [ - "azure" + "minimax" ] }, - "voiceId": { - "description": "This is the provider-specific ID that will be used.", - "oneOf": [ - { - "type": "string", - "enum": [ - "andrew", - "brian", - "emma" - ], - "title": "Preset Voice Options" - }, - { - "type": "string", - "title": "Azure Voice ID" - } + "model": { + "type": "string", + "description": "This is the name of the model. Ex. cognitivecomputations/dolphin-mixtral-8x7b", + "enum": [ + "MiniMax-M2.7" ] }, - "speed": { + "temperature": { "type": "number", - "description": "This is the speed multiplier that will be used.", - "minimum": 0.5, + "description": "This is the temperature that will be used for calls. Default is 0.5.", + "minimum": 0, "maximum": 2 }, - "chunkPlan": { - "description": "This is the plan for chunking the model output before it is sent to the voice provider.", - "allOf": [ - { - "$ref": "#/components/schemas/ChunkPlan" - } - ] + "maxTokens": { + "type": "number", + "description": "This is the max number of tokens that the assistant will be allowed to generate in each turn of the conversation. Default is 250.", + "minimum": 50, + "maximum": 10000 + }, + "emotionRecognitionEnabled": { + "type": "boolean", + "description": "This determines whether we detect user's emotion while they speak and send it as an additional info to model.\n\nDefault `false` because the model is usually are good at understanding the user's emotion from text.\n\n@default false" + }, + "numFastTurns": { + "type": "number", + "description": "This sets how many turns at the start of the conversation to use a smaller, faster model from the same provider before switching to the primary model. Example, gpt-3.5-turbo if provider is openai.\n\nDefault is 0.\n\n@default 0", + "minimum": 0 } }, "required": [ "provider", - "voiceId" + "model" ] }, - "FallbackCartesiaVoice": { + "OpenAIModel": { "type": "object", "properties": { - "cachingEnabled": { - "type": "boolean", - "description": "This is the flag to toggle voice caching for the assistant.", - "example": true, - "default": true + "messages": { + "description": "This is the starting state for the conversation.", + "type": "array", + "items": { + "$ref": "#/components/schemas/OpenAIMessage" + } + }, + "tools": { + "type": "array", + "description": "These are the tools that the assistant can use during the call. To use existing tools, use `toolIds`.\n\nBoth `tools` and `toolIds` can be used together.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/CreateApiRequestToolDTO", + "title": "ApiRequestTool" + }, + { + "$ref": "#/components/schemas/CreateBashToolDTO", + "title": "BashTool" + }, + { + "$ref": "#/components/schemas/CreateCodeToolDTO", + "title": "CodeTool" + }, + { + "$ref": "#/components/schemas/CreateComputerToolDTO", + "title": "ComputerTool" + }, + { + "$ref": "#/components/schemas/CreateDtmfToolDTO", + "title": "DtmfTool" + }, + { + "$ref": "#/components/schemas/CreateEndCallToolDTO", + "title": "EndCallTool" + }, + { + "$ref": "#/components/schemas/CreateFunctionToolDTO", + "title": "FunctionTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelCalendarAvailabilityToolDTO", + "title": "GoHighLevelCalendarAvailabilityTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelCalendarEventCreateToolDTO", + "title": "GoHighLevelCalendarEventCreateTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelContactCreateToolDTO", + "title": "GoHighLevelContactCreateTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelContactGetToolDTO", + "title": "GoHighLevelContactGetTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarCheckAvailabilityToolDTO", + "title": "GoogleCalendarCheckAvailabilityTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarCreateEventToolDTO", + "title": "GoogleCalendarCreateEventTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleSheetsRowAppendToolDTO", + "title": "GoogleSheetsRowAppendTool" + }, + { + "$ref": "#/components/schemas/CreateHandoffToolDTO", + "title": "HandoffTool" + }, + { + "$ref": "#/components/schemas/CreateMcpToolDTO", + "title": "McpTool" + }, + { + "$ref": "#/components/schemas/CreateQueryToolDTO", + "title": "QueryTool" + }, + { + "$ref": "#/components/schemas/CreateSlackSendMessageToolDTO", + "title": "SlackSendMessageTool" + }, + { + "$ref": "#/components/schemas/CreateSmsToolDTO", + "title": "SmsTool" + }, + { + "$ref": "#/components/schemas/CreateTextEditorToolDTO", + "title": "TextEditorTool" + }, + { + "$ref": "#/components/schemas/CreateTransferCallToolDTO", + "title": "TransferCallTool" + }, + { + "$ref": "#/components/schemas/CreateSipRequestToolDTO", + "title": "SipRequestTool" + }, + { + "$ref": "#/components/schemas/CreateVoicemailToolDTO", + "title": "VoicemailTool" + } + ] + } + }, + "toolIds": { + "description": "These are the tools that the assistant can use during the call. To use transient tools, use `tools`.\n\nBoth `tools` and `toolIds` can be used together.", + "type": "array", + "items": { + "type": "string" + } + }, + "toolRefs": { + "description": "These are version-pinned references to tools. Each entry pins a specific\nversion of a tool by `(toolId, version)`. When the same `toolId` appears\nin both `toolIds` and `toolRefs[]`, the `toolRefs` pin wins (the\n`toolIds` entry is dropped at write time).", + "type": "array", + "items": { + "$ref": "#/components/schemas/ToolRef" + } + }, + "knowledgeBase": { + "description": "These are the options for the knowledge base.", + "oneOf": [ + { + "$ref": "#/components/schemas/CreateCustomKnowledgeBaseDTO", + "title": "Custom" + } + ] }, "provider": { "type": "string", - "description": "This is the voice provider that will be used.", + "description": "This is the provider that will be used for the model.", "enum": [ - "cartesia" + "openai" ] }, - "voiceId": { - "type": "string", - "description": "The ID of the particular voice you want to use." - }, "model": { "type": "string", - "description": "This is the model that will be used. This is optional and will default to the correct model for the voiceId.", + "description": "This is the OpenAI model that will be used.\n\nWhen using Vapi OpenAI or your own Azure Credentials, you have the option to specify the region for the selected model. This shouldn't be specified unless you have a specific reason to do so. Vapi will automatically find the fastest region that make sense.\nThis is helpful when you are required to comply with Data Residency rules. Learn more about Azure regions here https://azure.microsoft.com/en-us/explore/global-infrastructure/data-residency/.\n\n@default undefined", "enum": [ - "sonic-2", - "sonic-english", - "sonic-multilingual", - "sonic-preview", - "sonic" + "gpt-5.6-sol", + "gpt-5.6-terra", + "gpt-5.6-luna", + "gpt-5.5", + "chat-latest", + "gpt-5.4", + "gpt-5.4-mini", + "gpt-5.4-nano", + "gpt-5.2", + "gpt-5.2-chat-latest", + "gpt-5.1", + "gpt-5.1-chat-latest", + "gpt-5", + "gpt-5-chat-latest", + "gpt-5-mini", + "gpt-5-nano", + "gpt-4.1-2025-04-14", + "gpt-4.1-mini-2025-04-14", + "gpt-4.1-nano-2025-04-14", + "gpt-4.1", + "gpt-4.1-mini", + "gpt-4.1-nano", + "chatgpt-4o-latest", + "o3", + "o3-mini", + "o4-mini", + "o1-mini", + "o1-mini-2024-09-12", + "gpt-4o-realtime-preview-2024-10-01", + "gpt-4o-realtime-preview-2024-12-17", + "gpt-4o-mini-realtime-preview-2024-12-17", + "gpt-realtime-2025-08-28", + "gpt-realtime-mini-2025-12-15", + "gpt-realtime-2", + "gpt-4o-mini-2024-07-18", + "gpt-4o-mini", + "gpt-4o", + "gpt-4o-2024-05-13", + "gpt-4o-2024-08-06", + "gpt-4o-2024-11-20", + "gpt-4-turbo", + "gpt-4-turbo-2024-04-09", + "gpt-4-turbo-preview", + "gpt-4-0125-preview", + "gpt-4-1106-preview", + "gpt-4", + "gpt-4-0613", + "gpt-3.5-turbo", + "gpt-3.5-turbo-0125", + "gpt-3.5-turbo-1106", + "gpt-3.5-turbo-16k", + "gpt-3.5-turbo-0613", + "gpt-5.6-luna:westus3", + "gpt-5.6-terra:westus3", + "gpt-5.6-sol:westus3", + "gpt-5.4:eastus2", + "gpt-5.4:swedencentral", + "gpt-5.4-mini:eastus2", + "gpt-5.4-mini:swedencentral", + "gpt-5.4-nano:eastus2", + "gpt-5.4-nano:swedencentral", + "gpt-5.2:eastus2", + "gpt-5.2:swedencentral", + "gpt-5.1:eastus2", + "gpt-5.1:swedencentral", + "gpt-5:eastus2", + "gpt-5:swedencentral", + "gpt-5:canadaeast", + "gpt-5:eastus", + "gpt-5:westeurope", + "gpt-5:germanywestcentral", + "gpt-5:polandcentral", + "gpt-5:spaincentral", + "gpt-5-mini:eastus2", + "gpt-5-mini:swedencentral", + "gpt-5-mini:westeurope", + "gpt-5-mini:germanywestcentral", + "gpt-5-mini:polandcentral", + "gpt-5-mini:spaincentral", + "gpt-5-nano:eastus2", + "gpt-5-nano:swedencentral", + "gpt-4.1-2025-04-14:westus", + "gpt-4.1-2025-04-14:eastus2", + "gpt-4.1-2025-04-14:eastus", + "gpt-4.1-2025-04-14:westus3", + "gpt-4.1-2025-04-14:northcentralus", + "gpt-4.1-2025-04-14:southcentralus", + "gpt-4.1-2025-04-14:westeurope", + "gpt-4.1-2025-04-14:germanywestcentral", + "gpt-4.1-2025-04-14:polandcentral", + "gpt-4.1-2025-04-14:spaincentral", + "gpt-4.1-mini-2025-04-14:westus", + "gpt-4.1-mini-2025-04-14:eastus2", + "gpt-4.1-mini-2025-04-14:eastus", + "gpt-4.1-mini-2025-04-14:westus3", + "gpt-4.1-mini-2025-04-14:northcentralus", + "gpt-4.1-mini-2025-04-14:southcentralus", + "gpt-4.1-mini-2025-04-14:westeurope", + "gpt-4.1-mini-2025-04-14:germanywestcentral", + "gpt-4.1-mini-2025-04-14:polandcentral", + "gpt-4.1-mini-2025-04-14:spaincentral", + "gpt-4.1-nano-2025-04-14:westus", + "gpt-4.1-nano-2025-04-14:eastus2", + "gpt-4.1-nano-2025-04-14:westus3", + "gpt-4.1-nano-2025-04-14:northcentralus", + "gpt-4.1-nano-2025-04-14:southcentralus", + "gpt-4o-2024-11-20:swedencentral", + "gpt-4o-2024-11-20:westus", + "gpt-4o-2024-11-20:eastus2", + "gpt-4o-2024-11-20:eastus", + "gpt-4o-2024-11-20:westus3", + "gpt-4o-2024-11-20:southcentralus", + "gpt-4o-2024-11-20:westeurope", + "gpt-4o-2024-11-20:germanywestcentral", + "gpt-4o-2024-11-20:polandcentral", + "gpt-4o-2024-11-20:spaincentral", + "gpt-4o-2024-08-06:westus", + "gpt-4o-2024-08-06:westus3", + "gpt-4o-2024-08-06:eastus", + "gpt-4o-2024-08-06:eastus2", + "gpt-4o-2024-08-06:northcentralus", + "gpt-4o-2024-08-06:southcentralus", + "gpt-4o-mini-2024-07-18:westus", + "gpt-4o-mini-2024-07-18:westus3", + "gpt-4o-mini-2024-07-18:eastus", + "gpt-4o-mini-2024-07-18:eastus2", + "gpt-4o-mini-2024-07-18:northcentralus", + "gpt-4o-mini-2024-07-18:southcentralus", + "gpt-4o-2024-05-13:eastus2", + "gpt-4o-2024-05-13:eastus", + "gpt-4o-2024-05-13:northcentralus", + "gpt-4o-2024-05-13:southcentralus", + "gpt-4o-2024-05-13:westus3", + "gpt-4o-2024-05-13:westus", + "gpt-4-turbo-2024-04-09:eastus2", + "gpt-4-0125-preview:eastus", + "gpt-4-0125-preview:northcentralus", + "gpt-4-0125-preview:southcentralus", + "gpt-4-1106-preview:australiaeast", + "gpt-4-1106-preview:canadaeast", + "gpt-4-1106-preview:france", + "gpt-4-1106-preview:india", + "gpt-4-1106-preview:norway", + "gpt-4-1106-preview:swedencentral", + "gpt-4-1106-preview:uk", + "gpt-4-1106-preview:westus", + "gpt-4-1106-preview:westus3", + "gpt-4-0613:canadaeast", + "gpt-3.5-turbo-0125:canadaeast", + "gpt-3.5-turbo-0125:northcentralus", + "gpt-3.5-turbo-0125:southcentralus", + "gpt-3.5-turbo-1106:canadaeast", + "gpt-3.5-turbo-1106:westus", + "gpt-4.1:australiaeast", + "gpt-4o:australiaeast", + "gpt-5.4-mini:australiaeast" + ] + }, + "fallbackModels": { + "type": "array", + "description": "These are the fallback models that will be used if the primary model fails. This shouldn't be specified unless you have a specific reason to do so. Vapi will automatically find the fastest fallbacks that make sense.", + "example": [ + "gpt-4-0125-preview", + "gpt-4-0613" ], - "example": "sonic-english" + "items": { + "type": "string", + "enum": [ + "gpt-5.6-sol", + "gpt-5.6-terra", + "gpt-5.6-luna", + "gpt-5.5", + "chat-latest", + "gpt-5.4", + "gpt-5.4-mini", + "gpt-5.4-nano", + "gpt-5.2", + "gpt-5.2-chat-latest", + "gpt-5.1", + "gpt-5.1-chat-latest", + "gpt-5", + "gpt-5-chat-latest", + "gpt-5-mini", + "gpt-5-nano", + "gpt-4.1-2025-04-14", + "gpt-4.1-mini-2025-04-14", + "gpt-4.1-nano-2025-04-14", + "gpt-4.1", + "gpt-4.1-mini", + "gpt-4.1-nano", + "chatgpt-4o-latest", + "o3", + "o3-mini", + "o4-mini", + "o1-mini", + "o1-mini-2024-09-12", + "gpt-4o-realtime-preview-2024-10-01", + "gpt-4o-realtime-preview-2024-12-17", + "gpt-4o-mini-realtime-preview-2024-12-17", + "gpt-realtime-2025-08-28", + "gpt-realtime-mini-2025-12-15", + "gpt-realtime-2", + "gpt-4o-mini-2024-07-18", + "gpt-4o-mini", + "gpt-4o", + "gpt-4o-2024-05-13", + "gpt-4o-2024-08-06", + "gpt-4o-2024-11-20", + "gpt-4-turbo", + "gpt-4-turbo-2024-04-09", + "gpt-4-turbo-preview", + "gpt-4-0125-preview", + "gpt-4-1106-preview", + "gpt-4", + "gpt-4-0613", + "gpt-3.5-turbo", + "gpt-3.5-turbo-0125", + "gpt-3.5-turbo-1106", + "gpt-3.5-turbo-16k", + "gpt-3.5-turbo-0613", + "gpt-5.6-luna:westus3", + "gpt-5.6-terra:westus3", + "gpt-5.6-sol:westus3", + "gpt-5.4:eastus2", + "gpt-5.4:swedencentral", + "gpt-5.4-mini:eastus2", + "gpt-5.4-mini:swedencentral", + "gpt-5.4-nano:eastus2", + "gpt-5.4-nano:swedencentral", + "gpt-5.2:eastus2", + "gpt-5.2:swedencentral", + "gpt-5.1:eastus2", + "gpt-5.1:swedencentral", + "gpt-5:eastus2", + "gpt-5:swedencentral", + "gpt-5:canadaeast", + "gpt-5:eastus", + "gpt-5:westeurope", + "gpt-5:germanywestcentral", + "gpt-5:polandcentral", + "gpt-5:spaincentral", + "gpt-5-mini:eastus2", + "gpt-5-mini:swedencentral", + "gpt-5-mini:westeurope", + "gpt-5-mini:germanywestcentral", + "gpt-5-mini:polandcentral", + "gpt-5-mini:spaincentral", + "gpt-5-nano:eastus2", + "gpt-5-nano:swedencentral", + "gpt-4.1-2025-04-14:westus", + "gpt-4.1-2025-04-14:eastus2", + "gpt-4.1-2025-04-14:eastus", + "gpt-4.1-2025-04-14:westus3", + "gpt-4.1-2025-04-14:northcentralus", + "gpt-4.1-2025-04-14:southcentralus", + "gpt-4.1-2025-04-14:westeurope", + "gpt-4.1-2025-04-14:germanywestcentral", + "gpt-4.1-2025-04-14:polandcentral", + "gpt-4.1-2025-04-14:spaincentral", + "gpt-4.1-mini-2025-04-14:westus", + "gpt-4.1-mini-2025-04-14:eastus2", + "gpt-4.1-mini-2025-04-14:eastus", + "gpt-4.1-mini-2025-04-14:westus3", + "gpt-4.1-mini-2025-04-14:northcentralus", + "gpt-4.1-mini-2025-04-14:southcentralus", + "gpt-4.1-mini-2025-04-14:westeurope", + "gpt-4.1-mini-2025-04-14:germanywestcentral", + "gpt-4.1-mini-2025-04-14:polandcentral", + "gpt-4.1-mini-2025-04-14:spaincentral", + "gpt-4.1-nano-2025-04-14:westus", + "gpt-4.1-nano-2025-04-14:eastus2", + "gpt-4.1-nano-2025-04-14:westus3", + "gpt-4.1-nano-2025-04-14:northcentralus", + "gpt-4.1-nano-2025-04-14:southcentralus", + "gpt-4o-2024-11-20:swedencentral", + "gpt-4o-2024-11-20:westus", + "gpt-4o-2024-11-20:eastus2", + "gpt-4o-2024-11-20:eastus", + "gpt-4o-2024-11-20:westus3", + "gpt-4o-2024-11-20:southcentralus", + "gpt-4o-2024-11-20:westeurope", + "gpt-4o-2024-11-20:germanywestcentral", + "gpt-4o-2024-11-20:polandcentral", + "gpt-4o-2024-11-20:spaincentral", + "gpt-4o-2024-08-06:westus", + "gpt-4o-2024-08-06:westus3", + "gpt-4o-2024-08-06:eastus", + "gpt-4o-2024-08-06:eastus2", + "gpt-4o-2024-08-06:northcentralus", + "gpt-4o-2024-08-06:southcentralus", + "gpt-4o-mini-2024-07-18:westus", + "gpt-4o-mini-2024-07-18:westus3", + "gpt-4o-mini-2024-07-18:eastus", + "gpt-4o-mini-2024-07-18:eastus2", + "gpt-4o-mini-2024-07-18:northcentralus", + "gpt-4o-mini-2024-07-18:southcentralus", + "gpt-4o-2024-05-13:eastus2", + "gpt-4o-2024-05-13:eastus", + "gpt-4o-2024-05-13:northcentralus", + "gpt-4o-2024-05-13:southcentralus", + "gpt-4o-2024-05-13:westus3", + "gpt-4o-2024-05-13:westus", + "gpt-4-turbo-2024-04-09:eastus2", + "gpt-4-0125-preview:eastus", + "gpt-4-0125-preview:northcentralus", + "gpt-4-0125-preview:southcentralus", + "gpt-4-1106-preview:australiaeast", + "gpt-4-1106-preview:canadaeast", + "gpt-4-1106-preview:france", + "gpt-4-1106-preview:india", + "gpt-4-1106-preview:norway", + "gpt-4-1106-preview:swedencentral", + "gpt-4-1106-preview:uk", + "gpt-4-1106-preview:westus", + "gpt-4-1106-preview:westus3", + "gpt-4-0613:canadaeast", + "gpt-3.5-turbo-0125:canadaeast", + "gpt-3.5-turbo-0125:northcentralus", + "gpt-3.5-turbo-0125:southcentralus", + "gpt-3.5-turbo-1106:canadaeast", + "gpt-3.5-turbo-1106:westus", + "gpt-4.1:australiaeast", + "gpt-4o:australiaeast", + "gpt-5.4-mini:australiaeast" + ] + } }, - "language": { + "toolStrictCompatibilityMode": { "type": "string", - "description": "This is the language that will be used. This is optional and will default to the correct language for the voiceId.", + "description": "Azure OpenAI doesn't support `maxLength` right now https://learn.microsoft.com/en-us/azure/ai-services/openai/how-to/structured-outputs?tabs=python-secure%2Cdotnet-entra-id&pivots=programming-language-csharp#unsupported-type-specific-keywords. Need to strip.\n\n- `strip-parameters-with-unsupported-validation` will strip parameters with unsupported validation.\n- `strip-unsupported-validation` will keep the parameters but strip unsupported validation.\n\n@default `strip-unsupported-validation`", "enum": [ - "en", - "de", - "es", - "fr", - "ja", - "pt", - "zh", - "hi", - "it", - "ko", - "nl", - "pl", - "ru", - "sv", - "tr" - ], - "example": "en" - }, - "experimentalControls": { - "description": "Experimental controls for Cartesia voice generation", - "allOf": [ - { - "$ref": "#/components/schemas/CartesiaExperimentalControls" - } + "strip-parameters-with-unsupported-validation", + "strip-unsupported-validation" ] }, - "chunkPlan": { - "description": "This is the plan for chunking the model output before it is sent to the voice provider.", - "allOf": [ - { - "$ref": "#/components/schemas/ChunkPlan" - } + "promptCacheRetention": { + "type": "string", + "description": "This controls the prompt cache retention policy for models that support extended caching (GPT-4.1, GPT-5 series).\n\n- `in_memory`: Default behavior, cache retained in GPU memory only\n- `24h`: Extended caching, keeps cached prefixes active for up to 24 hours by offloading to GPU-local storage\n\nOnly applies to models: gpt-5.6-sol, gpt-5.6-terra, gpt-5.6-luna, gpt-5.5, chat-latest, gpt-5.4, gpt-5.4-mini, gpt-5.4-nano, gpt-5.2, gpt-5.1, gpt-5.1-codex, gpt-5.1-codex-mini, gpt-5.1-chat-latest, gpt-5, gpt-5-codex, gpt-4.1\n\n@default undefined (uses API default which is 'in_memory')", + "enum": [ + "in_memory", + "24h" ] - } - }, - "required": [ - "provider", - "voiceId" - ] - }, - "FallbackCustomVoice": { - "type": "object", - "properties": { - "cachingEnabled": { - "type": "boolean", - "description": "This is the flag to toggle voice caching for the assistant.", - "example": true, - "default": true }, - "provider": { + "promptCacheKey": { "type": "string", - "description": "This is the voice provider that will be used. Use `custom-voice` for providers that are not natively supported.", + "description": "This is the prompt cache key for models that support extended caching (GPT-4.1, GPT-5 series).\n\nProviding a cache key allows you to share cached prefixes across requests.\n\n@default undefined", + "maxLength": 64 + }, + "reasoningEffort": { + "type": "string", + "description": "Reasoning effort for reasoning-capable OpenAI models.\nFor `gpt-realtime-2`: forwarded to V2 stream's session.update as `reasoning.effort`.\nFor non-realtime OpenAI models, model-aware validation limits newly public\nvalues while preserving the existing four-value storage contract.", "enum": [ - "custom-voice" + "minimal", + "none", + "low", + "medium", + "high", + "xhigh" ] }, - "server": { - "description": "This is where the voice request will be sent.\n\nRequest Example:\n\nPOST https://{server.url}\nContent-Type: application/json\n\n{\n \"message\": {\n \"type\": \"voice-request\",\n \"text\": \"Hello, world!\",\n \"sampleRate\": 24000,\n ...other metadata about the call...\n }\n}\n\nResponse Expected: 1-channel 16-bit raw PCM audio at the sample rate specified in the request. Here is how the response will be piped to the transport:\n```\nresponse.on('data', (chunk: Buffer) => {\n outputStream.write(chunk);\n});\n```", - "allOf": [ - { - "$ref": "#/components/schemas/Server" - } - ] + "temperature": { + "type": "number", + "description": "This is the temperature that will be used for calls. Default is 0.5.", + "minimum": 0, + "maximum": 2 }, - "chunkPlan": { - "description": "This is the plan for chunking the model output before it is sent to the voice provider.", - "allOf": [ - { - "$ref": "#/components/schemas/ChunkPlan" - } - ] + "maxTokens": { + "type": "number", + "description": "This is the max number of tokens that the assistant will be allowed to generate in each turn of the conversation. Default is 250.", + "minimum": 50, + "maximum": 10000 + }, + "emotionRecognitionEnabled": { + "type": "boolean", + "description": "This determines whether we detect user's emotion while they speak and send it as an additional info to model.\n\nDefault `false` because the model is usually are good at understanding the user's emotion from text.\n\n@default false" + }, + "numFastTurns": { + "type": "number", + "description": "This sets how many turns at the start of the conversation to use a smaller, faster model from the same provider before switching to the primary model. Example, gpt-3.5-turbo if provider is openai.\n\nDefault is 0.\n\n@default 0", + "minimum": 0 } }, "required": [ "provider", - "server" + "model" ] }, - "FallbackDeepgramVoice": { + "OpenRouterModel": { "type": "object", "properties": { - "cachingEnabled": { - "type": "boolean", - "description": "This is the flag to toggle voice caching for the assistant.", - "example": true, - "default": true - }, - "provider": { - "type": "string", - "description": "This is the voice provider that will be used.", - "enum": [ - "deepgram" - ] - }, - "voiceId": { - "type": "string", - "description": "This is the provider-specific ID that will be used.", - "enum": [ - "asteria", - "luna", - "stella", - "athena", - "hera", - "orion", - "arcas", - "perseus", - "angus", - "orpheus", - "helios", - "zeus", - "thalia", - "andromeda", - "helena", - "apollo", - "arcas", - "aries", - "amalthea", - "asteria", - "athena", - "atlas", - "aurora", - "callista", - "cora", - "cordelia", - "delia", - "draco", - "electra", - "harmonia", - "hera", - "hermes", - "hyperion", - "iris", - "janus", - "juno", - "jupiter", - "luna", - "mars", - "minerva", - "neptune", - "odysseus", - "ophelia", - "orion", - "orpheus", - "pandora", - "phoebe", - "pluto", - "saturn", - "selene", - "theia", - "vesta", - "zeus" - ], - "title": "This is the Deepgram Voice ID" + "messages": { + "description": "This is the starting state for the conversation.", + "type": "array", + "items": { + "$ref": "#/components/schemas/OpenAIMessage" + } }, - "model": { - "type": "string", - "description": "This is the model that will be used. Defaults to 'aura-2' when not specified.", - "enum": [ - "aura", - "aura-2" - ], - "example": "aura-2" + "tools": { + "type": "array", + "description": "These are the tools that the assistant can use during the call. To use existing tools, use `toolIds`.\n\nBoth `tools` and `toolIds` can be used together.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/CreateApiRequestToolDTO", + "title": "ApiRequestTool" + }, + { + "$ref": "#/components/schemas/CreateBashToolDTO", + "title": "BashTool" + }, + { + "$ref": "#/components/schemas/CreateCodeToolDTO", + "title": "CodeTool" + }, + { + "$ref": "#/components/schemas/CreateComputerToolDTO", + "title": "ComputerTool" + }, + { + "$ref": "#/components/schemas/CreateDtmfToolDTO", + "title": "DtmfTool" + }, + { + "$ref": "#/components/schemas/CreateEndCallToolDTO", + "title": "EndCallTool" + }, + { + "$ref": "#/components/schemas/CreateFunctionToolDTO", + "title": "FunctionTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelCalendarAvailabilityToolDTO", + "title": "GoHighLevelCalendarAvailabilityTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelCalendarEventCreateToolDTO", + "title": "GoHighLevelCalendarEventCreateTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelContactCreateToolDTO", + "title": "GoHighLevelContactCreateTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelContactGetToolDTO", + "title": "GoHighLevelContactGetTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarCheckAvailabilityToolDTO", + "title": "GoogleCalendarCheckAvailabilityTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarCreateEventToolDTO", + "title": "GoogleCalendarCreateEventTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleSheetsRowAppendToolDTO", + "title": "GoogleSheetsRowAppendTool" + }, + { + "$ref": "#/components/schemas/CreateHandoffToolDTO", + "title": "HandoffTool" + }, + { + "$ref": "#/components/schemas/CreateMcpToolDTO", + "title": "McpTool" + }, + { + "$ref": "#/components/schemas/CreateQueryToolDTO", + "title": "QueryTool" + }, + { + "$ref": "#/components/schemas/CreateSlackSendMessageToolDTO", + "title": "SlackSendMessageTool" + }, + { + "$ref": "#/components/schemas/CreateSmsToolDTO", + "title": "SmsTool" + }, + { + "$ref": "#/components/schemas/CreateTextEditorToolDTO", + "title": "TextEditorTool" + }, + { + "$ref": "#/components/schemas/CreateTransferCallToolDTO", + "title": "TransferCallTool" + }, + { + "$ref": "#/components/schemas/CreateSipRequestToolDTO", + "title": "SipRequestTool" + }, + { + "$ref": "#/components/schemas/CreateVoicemailToolDTO", + "title": "VoicemailTool" + } + ] + } }, - "mipOptOut": { - "type": "boolean", - "description": "If set to true, this will add mip_opt_out=true as a query parameter of all API requests. See https://developers.deepgram.com/docs/the-deepgram-model-improvement-partnership-program#want-to-opt-out\n\nThis will only be used if you are using your own Deepgram API key.\n\n@default false", - "example": false, - "default": false + "toolIds": { + "description": "These are the tools that the assistant can use during the call. To use transient tools, use `tools`.\n\nBoth `tools` and `toolIds` can be used together.", + "type": "array", + "items": { + "type": "string" + } }, - "chunkPlan": { - "description": "This is the plan for chunking the model output before it is sent to the voice provider.", - "allOf": [ + "toolRefs": { + "description": "These are version-pinned references to tools. Each entry pins a specific\nversion of a tool by `(toolId, version)`. When the same `toolId` appears\nin both `toolIds` and `toolRefs[]`, the `toolRefs` pin wins (the\n`toolIds` entry is dropped at write time).", + "type": "array", + "items": { + "$ref": "#/components/schemas/ToolRef" + } + }, + "knowledgeBase": { + "description": "These are the options for the knowledge base.", + "oneOf": [ { - "$ref": "#/components/schemas/ChunkPlan" + "$ref": "#/components/schemas/CreateCustomKnowledgeBaseDTO", + "title": "Custom" } ] - } - }, - "required": [ - "provider", - "voiceId" - ] - }, - "FallbackElevenLabsVoice": { - "type": "object", - "properties": { - "cachingEnabled": { - "type": "boolean", - "description": "This is the flag to toggle voice caching for the assistant.", - "example": true, - "default": true }, "provider": { "type": "string", - "description": "This is the voice provider that will be used.", "enum": [ - "11labs" - ] - }, - "voiceId": { - "description": "This is the provider-specific ID that will be used. Ensure the Voice is present in your 11Labs Voice Library.", - "oneOf": [ - { - "type": "string", - "enum": [ - "burt", - "marissa", - "andrea", - "sarah", - "phillip", - "steve", - "joseph", - "myra", - "paula", - "ryan", - "drew", - "paul", - "mrb", - "matilda", - "mark" - ], - "title": "Preset Voice Options" - }, - { - "type": "string", - "title": "11Labs Voice ID" - } + "openrouter" ] }, - "stability": { - "type": "number", - "description": "Defines the stability for voice settings.", - "minimum": 0, - "maximum": 1, - "example": 0.5 + "model": { + "type": "string", + "description": "This is the name of the model. Ex. cognitivecomputations/dolphin-mixtral-8x7b" }, - "similarityBoost": { + "temperature": { "type": "number", - "description": "Defines the similarity boost for voice settings.", + "description": "This is the temperature that will be used for calls. Default is 0.5.", "minimum": 0, - "maximum": 1, - "example": 0.75 + "maximum": 2 }, - "style": { + "maxTokens": { "type": "number", - "description": "Defines the style for voice settings.", - "minimum": 0, - "maximum": 1, - "example": 0 + "description": "This is the max number of tokens that the assistant will be allowed to generate in each turn of the conversation. Default is 250.", + "minimum": 50, + "maximum": 10000 }, - "useSpeakerBoost": { + "emotionRecognitionEnabled": { "type": "boolean", - "description": "Defines the use speaker boost for voice settings.", - "example": false - }, - "speed": { - "type": "number", - "description": "Defines the speed for voice settings.", - "minimum": 0.7, - "maximum": 1.2, - "example": 0.9 + "description": "This determines whether we detect user's emotion while they speak and send it as an additional info to model.\n\nDefault `false` because the model is usually are good at understanding the user's emotion from text.\n\n@default false" }, - "optimizeStreamingLatency": { + "numFastTurns": { "type": "number", - "description": "Defines the optimize streaming latency for voice settings. Defaults to 3.", - "minimum": 0, - "maximum": 4, - "example": 3 - }, - "enableSsmlParsing": { - "type": "boolean", - "description": "This enables the use of https://elevenlabs.io/docs/speech-synthesis/prompting#pronunciation. Defaults to false to save latency.\n\n@default false", - "example": false - }, - "autoMode": { - "type": "boolean", - "description": "Defines the auto mode for voice settings. Defaults to false.", - "example": false + "description": "This sets how many turns at the start of the conversation to use a smaller, faster model from the same provider before switching to the primary model. Example, gpt-3.5-turbo if provider is openai.\n\nDefault is 0.\n\n@default 0", + "minimum": 0 + } + }, + "required": [ + "provider", + "model" + ] + }, + "PerplexityAIModel": { + "type": "object", + "properties": { + "messages": { + "description": "This is the starting state for the conversation.", + "type": "array", + "items": { + "$ref": "#/components/schemas/OpenAIMessage" + } }, - "model": { - "type": "string", - "description": "This is the model that will be used. Defaults to 'eleven_turbo_v2' if not specified.", - "enum": [ - "eleven_multilingual_v2", - "eleven_turbo_v2", - "eleven_turbo_v2_5", - "eleven_flash_v2", - "eleven_flash_v2_5", - "eleven_monolingual_v1" - ], - "example": "eleven_turbo_v2_5" + "tools": { + "type": "array", + "description": "These are the tools that the assistant can use during the call. To use existing tools, use `toolIds`.\n\nBoth `tools` and `toolIds` can be used together.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/CreateApiRequestToolDTO", + "title": "ApiRequestTool" + }, + { + "$ref": "#/components/schemas/CreateBashToolDTO", + "title": "BashTool" + }, + { + "$ref": "#/components/schemas/CreateCodeToolDTO", + "title": "CodeTool" + }, + { + "$ref": "#/components/schemas/CreateComputerToolDTO", + "title": "ComputerTool" + }, + { + "$ref": "#/components/schemas/CreateDtmfToolDTO", + "title": "DtmfTool" + }, + { + "$ref": "#/components/schemas/CreateEndCallToolDTO", + "title": "EndCallTool" + }, + { + "$ref": "#/components/schemas/CreateFunctionToolDTO", + "title": "FunctionTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelCalendarAvailabilityToolDTO", + "title": "GoHighLevelCalendarAvailabilityTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelCalendarEventCreateToolDTO", + "title": "GoHighLevelCalendarEventCreateTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelContactCreateToolDTO", + "title": "GoHighLevelContactCreateTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelContactGetToolDTO", + "title": "GoHighLevelContactGetTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarCheckAvailabilityToolDTO", + "title": "GoogleCalendarCheckAvailabilityTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarCreateEventToolDTO", + "title": "GoogleCalendarCreateEventTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleSheetsRowAppendToolDTO", + "title": "GoogleSheetsRowAppendTool" + }, + { + "$ref": "#/components/schemas/CreateHandoffToolDTO", + "title": "HandoffTool" + }, + { + "$ref": "#/components/schemas/CreateMcpToolDTO", + "title": "McpTool" + }, + { + "$ref": "#/components/schemas/CreateQueryToolDTO", + "title": "QueryTool" + }, + { + "$ref": "#/components/schemas/CreateSlackSendMessageToolDTO", + "title": "SlackSendMessageTool" + }, + { + "$ref": "#/components/schemas/CreateSmsToolDTO", + "title": "SmsTool" + }, + { + "$ref": "#/components/schemas/CreateTextEditorToolDTO", + "title": "TextEditorTool" + }, + { + "$ref": "#/components/schemas/CreateTransferCallToolDTO", + "title": "TransferCallTool" + }, + { + "$ref": "#/components/schemas/CreateSipRequestToolDTO", + "title": "SipRequestTool" + }, + { + "$ref": "#/components/schemas/CreateVoicemailToolDTO", + "title": "VoicemailTool" + } + ] + } }, - "language": { - "type": "string", - "description": "This is the language (ISO 639-1) that is enforced for the model. Currently only Turbo v2.5 supports language enforcement. For other models, an error will be returned if language code is provided." + "toolIds": { + "description": "These are the tools that the assistant can use during the call. To use transient tools, use `tools`.\n\nBoth `tools` and `toolIds` can be used together.", + "type": "array", + "items": { + "type": "string" + } }, - "pronunciationDictionaryLocators": { - "description": "This is the pronunciation dictionary locators to use.", + "toolRefs": { + "description": "These are version-pinned references to tools. Each entry pins a specific\nversion of a tool by `(toolId, version)`. When the same `toolId` appears\nin both `toolIds` and `toolRefs[]`, the `toolRefs` pin wins (the\n`toolIds` entry is dropped at write time).", "type": "array", "items": { - "$ref": "#/components/schemas/ElevenLabsPronunciationDictionaryLocator" + "$ref": "#/components/schemas/ToolRef" } }, - "chunkPlan": { - "description": "This is the plan for chunking the model output before it is sent to the voice provider.", - "allOf": [ + "knowledgeBase": { + "description": "These are the options for the knowledge base.", + "oneOf": [ { - "$ref": "#/components/schemas/ChunkPlan" + "$ref": "#/components/schemas/CreateCustomKnowledgeBaseDTO", + "title": "Custom" } ] - } - }, - "required": [ - "provider", - "voiceId" - ] - }, - "FallbackHumeVoice": { - "type": "object", - "properties": { - "cachingEnabled": { - "type": "boolean", - "description": "This is the flag to toggle voice caching for the assistant.", - "example": true, - "default": true }, "provider": { "type": "string", - "description": "This is the voice provider that will be used.", "enum": [ - "hume" + "perplexity-ai" ] }, "model": { "type": "string", - "description": "This is the model that will be used.", - "enum": [ - "octave" - ], - "example": "octave" + "description": "This is the name of the model. Ex. cognitivecomputations/dolphin-mixtral-8x7b" }, - "voiceId": { - "type": "string", - "description": "The ID of the particular voice you want to use." + "temperature": { + "type": "number", + "description": "This is the temperature that will be used for calls. Default is 0.5.", + "minimum": 0, + "maximum": 2 }, - "isCustomHumeVoice": { - "type": "boolean", - "description": "Indicates whether the chosen voice is a preset Hume AI voice or a custom voice.", - "example": false + "maxTokens": { + "type": "number", + "description": "This is the max number of tokens that the assistant will be allowed to generate in each turn of the conversation. Default is 250.", + "minimum": 50, + "maximum": 10000 }, - "description": { - "type": "string", - "description": "Natural language instructions describing how the synthesized speech should sound, including but not limited to tone, intonation, pacing, and accent (e.g., 'a soft, gentle voice with a strong British accent').\n\nIf a Voice is specified in the request, this description serves as acting instructions.\nIf no Voice is specified, a new voice is generated based on this description." + "emotionRecognitionEnabled": { + "type": "boolean", + "description": "This determines whether we detect user's emotion while they speak and send it as an additional info to model.\n\nDefault `false` because the model is usually are good at understanding the user's emotion from text.\n\n@default false" }, - "chunkPlan": { - "description": "This is the plan for chunking the model output before it is sent to the voice provider.", - "allOf": [ - { - "$ref": "#/components/schemas/ChunkPlan" - } - ] + "numFastTurns": { + "type": "number", + "description": "This sets how many turns at the start of the conversation to use a smaller, faster model from the same provider before switching to the primary model. Example, gpt-3.5-turbo if provider is openai.\n\nDefault is 0.\n\n@default 0", + "minimum": 0 } }, "required": [ "provider", - "voiceId" + "model" ] }, - "FallbackLMNTVoice": { + "TogetherAIModel": { "type": "object", "properties": { - "cachingEnabled": { - "type": "boolean", - "description": "This is the flag to toggle voice caching for the assistant.", - "example": true, - "default": true - }, - "provider": { - "type": "string", - "description": "This is the voice provider that will be used.", - "enum": [ - "lmnt" - ] - }, - "voiceId": { - "description": "This is the provider-specific ID that will be used.", - "oneOf": [ - { - "type": "string", - "enum": [ - "amy", - "ansel", - "autumn", - "ava", - "brandon", - "caleb", - "cassian", - "chloe", - "dalton", - "daniel", - "dustin", - "elowen", - "evander", - "huxley", - "james", - "juniper", - "kennedy", - "lauren", - "leah", - "lily", - "lucas", - "magnus", - "miles", - "morgan", - "natalie", - "nathan", - "noah", - "nyssa", - "oliver", - "paige", - "ryan", - "sadie", - "sophie", - "stella", - "terrence", - "tyler", - "vesper", - "violet", - "warrick", - "zain", - "zeke", - "zoe" - ], - "title": "Preset Voice Options" - }, - { - "type": "string", - "title": "LMNT Voice ID" - } - ] - }, - "speed": { - "type": "number", - "description": "This is the speed multiplier that will be used.", - "minimum": 0.25, - "maximum": 2, - "example": null + "messages": { + "description": "This is the starting state for the conversation.", + "type": "array", + "items": { + "$ref": "#/components/schemas/OpenAIMessage" + } }, - "language": { - "description": "Two letter ISO 639-1 language code. Use \"auto\" for auto-detection.", - "enum": [ - "aa", - "ab", - "ae", - "af", - "ak", - "am", - "an", - "ar", - "as", - "av", - "ay", - "az", - "ba", - "be", - "bg", - "bh", - "bi", - "bm", - "bn", - "bo", - "br", - "bs", - "ca", - "ce", - "ch", - "co", - "cr", - "cs", - "cu", - "cv", - "cy", - "da", - "de", - "dv", - "dz", - "ee", - "el", - "en", - "eo", - "es", - "et", - "eu", - "fa", - "ff", - "fi", - "fj", - "fo", - "fr", - "fy", - "ga", - "gd", - "gl", - "gn", - "gu", - "gv", - "ha", - "he", - "hi", - "ho", - "hr", - "ht", - "hu", - "hy", - "hz", - "ia", - "id", - "ie", - "ig", - "ii", - "ik", - "io", - "is", - "it", - "iu", - "ja", - "jv", - "ka", - "kg", - "ki", - "kj", - "kk", - "kl", - "km", - "kn", - "ko", - "kr", - "ks", - "ku", - "kv", - "kw", - "ky", - "la", - "lb", - "lg", - "li", - "ln", - "lo", - "lt", - "lu", - "lv", - "mg", - "mh", - "mi", - "mk", - "ml", - "mn", - "mr", - "ms", - "mt", - "my", - "na", - "nb", - "nd", - "ne", - "ng", - "nl", - "nn", - "no", - "nr", - "nv", - "ny", - "oc", - "oj", - "om", - "or", - "os", - "pa", - "pi", - "pl", - "ps", - "pt", - "qu", - "rm", - "rn", - "ro", - "ru", - "rw", - "sa", - "sc", - "sd", - "se", - "sg", - "si", - "sk", - "sl", - "sm", - "sn", - "so", - "sq", - "sr", - "ss", - "st", - "su", - "sv", - "sw", - "ta", - "te", - "tg", - "th", - "ti", - "tk", - "tl", - "tn", - "to", - "tr", - "ts", - "tt", - "tw", - "ty", - "ug", - "uk", - "ur", - "uz", - "ve", - "vi", - "vo", - "wa", - "wo", - "xh", - "yi", - "yue", - "yo", - "za", - "zh", - "zu", - "auto" - ], - "example": "en", + "tools": { + "type": "array", + "description": "These are the tools that the assistant can use during the call. To use existing tools, use `toolIds`.\n\nBoth `tools` and `toolIds` can be used together.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/CreateApiRequestToolDTO", + "title": "ApiRequestTool" + }, + { + "$ref": "#/components/schemas/CreateBashToolDTO", + "title": "BashTool" + }, + { + "$ref": "#/components/schemas/CreateCodeToolDTO", + "title": "CodeTool" + }, + { + "$ref": "#/components/schemas/CreateComputerToolDTO", + "title": "ComputerTool" + }, + { + "$ref": "#/components/schemas/CreateDtmfToolDTO", + "title": "DtmfTool" + }, + { + "$ref": "#/components/schemas/CreateEndCallToolDTO", + "title": "EndCallTool" + }, + { + "$ref": "#/components/schemas/CreateFunctionToolDTO", + "title": "FunctionTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelCalendarAvailabilityToolDTO", + "title": "GoHighLevelCalendarAvailabilityTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelCalendarEventCreateToolDTO", + "title": "GoHighLevelCalendarEventCreateTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelContactCreateToolDTO", + "title": "GoHighLevelContactCreateTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelContactGetToolDTO", + "title": "GoHighLevelContactGetTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarCheckAvailabilityToolDTO", + "title": "GoogleCalendarCheckAvailabilityTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarCreateEventToolDTO", + "title": "GoogleCalendarCreateEventTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleSheetsRowAppendToolDTO", + "title": "GoogleSheetsRowAppendTool" + }, + { + "$ref": "#/components/schemas/CreateHandoffToolDTO", + "title": "HandoffTool" + }, + { + "$ref": "#/components/schemas/CreateMcpToolDTO", + "title": "McpTool" + }, + { + "$ref": "#/components/schemas/CreateQueryToolDTO", + "title": "QueryTool" + }, + { + "$ref": "#/components/schemas/CreateSlackSendMessageToolDTO", + "title": "SlackSendMessageTool" + }, + { + "$ref": "#/components/schemas/CreateSmsToolDTO", + "title": "SmsTool" + }, + { + "$ref": "#/components/schemas/CreateTextEditorToolDTO", + "title": "TextEditorTool" + }, + { + "$ref": "#/components/schemas/CreateTransferCallToolDTO", + "title": "TransferCallTool" + }, + { + "$ref": "#/components/schemas/CreateSipRequestToolDTO", + "title": "SipRequestTool" + }, + { + "$ref": "#/components/schemas/CreateVoicemailToolDTO", + "title": "VoicemailTool" + } + ] + } + }, + "toolIds": { + "description": "These are the tools that the assistant can use during the call. To use transient tools, use `tools`.\n\nBoth `tools` and `toolIds` can be used together.", + "type": "array", + "items": { + "type": "string" + } + }, + "toolRefs": { + "description": "These are version-pinned references to tools. Each entry pins a specific\nversion of a tool by `(toolId, version)`. When the same `toolId` appears\nin both `toolIds` and `toolRefs[]`, the `toolRefs` pin wins (the\n`toolIds` entry is dropped at write time).", + "type": "array", + "items": { + "$ref": "#/components/schemas/ToolRef" + } + }, + "knowledgeBase": { + "description": "These are the options for the knowledge base.", "oneOf": [ { - "type": "string", - "enum": [ - "aa", - "ab", - "ae", - "af", - "ak", - "am", - "an", - "ar", - "as", - "av", - "ay", - "az", - "ba", - "be", - "bg", - "bh", - "bi", - "bm", - "bn", - "bo", - "br", - "bs", - "ca", - "ce", - "ch", - "co", - "cr", - "cs", - "cu", - "cv", - "cy", - "da", - "de", - "dv", - "dz", - "ee", - "el", - "en", - "eo", - "es", - "et", - "eu", - "fa", - "ff", - "fi", - "fj", - "fo", - "fr", - "fy", - "ga", - "gd", - "gl", - "gn", - "gu", - "gv", - "ha", - "he", - "hi", - "ho", - "hr", - "ht", - "hu", - "hy", - "hz", - "ia", - "id", - "ie", - "ig", - "ii", - "ik", - "io", - "is", - "it", - "iu", - "ja", - "jv", - "ka", - "kg", - "ki", - "kj", - "kk", - "kl", - "km", - "kn", - "ko", - "kr", - "ks", - "ku", - "kv", - "kw", - "ky", - "la", - "lb", - "lg", - "li", - "ln", - "lo", - "lt", - "lu", - "lv", - "mg", - "mh", - "mi", - "mk", - "ml", - "mn", - "mr", - "ms", - "mt", - "my", - "na", - "nb", - "nd", - "ne", - "ng", - "nl", - "nn", - "no", - "nr", - "nv", - "ny", - "oc", - "oj", - "om", - "or", - "os", - "pa", - "pi", - "pl", - "ps", - "pt", - "qu", - "rm", - "rn", - "ro", - "ru", - "rw", - "sa", - "sc", - "sd", - "se", - "sg", - "si", - "sk", - "sl", - "sm", - "sn", - "so", - "sq", - "sr", - "ss", - "st", - "su", - "sv", - "sw", - "ta", - "te", - "tg", - "th", - "ti", - "tk", - "tl", - "tn", - "to", - "tr", - "ts", - "tt", - "tw", - "ty", - "ug", - "uk", - "ur", - "uz", - "ve", - "vi", - "vo", - "wa", - "wo", - "xh", - "yi", - "yue", - "yo", - "za", - "zh", - "zu" - ], - "title": "ISO 639-1 Language Code" - }, - { - "type": "string", - "enum": [ - "auto" - ], - "title": "Auto-detect" + "$ref": "#/components/schemas/CreateCustomKnowledgeBaseDTO", + "title": "Custom" } ] }, - "chunkPlan": { - "description": "This is the plan for chunking the model output before it is sent to the voice provider.", - "allOf": [ - { - "$ref": "#/components/schemas/ChunkPlan" - } - ] - } - }, - "required": [ - "provider", - "voiceId" - ] - }, - "FallbackNeuphonicVoice": { - "type": "object", - "properties": { - "cachingEnabled": { - "type": "boolean", - "description": "This is the flag to toggle voice caching for the assistant.", - "example": true, - "default": true - }, - "provider": { - "type": "string", - "description": "This is the voice provider that will be used.", - "enum": [ - "neuphonic" - ] - }, - "voiceId": { - "description": "This is the provider-specific ID that will be used.", - "oneOf": [ - { - "type": "string", - "enum": [], - "title": "Preset Voice Options" - }, - { - "type": "string", - "title": "Neuphonic Voice ID" - } + "provider": { + "type": "string", + "enum": [ + "together-ai" ] }, "model": { "type": "string", - "description": "This is the model that will be used. Defaults to 'neu_fast' if not specified.", - "enum": [ - "neu_hq", - "neu_fast" - ], - "example": "neu_fast" + "description": "This is the name of the model. Ex. cognitivecomputations/dolphin-mixtral-8x7b" }, - "language": { - "type": "object", - "description": "This is the language (ISO 639-1) that is enforced for the model.", - "example": "en" + "temperature": { + "type": "number", + "description": "This is the temperature that will be used for calls. Default is 0.5.", + "minimum": 0, + "maximum": 2 }, - "speed": { + "maxTokens": { "type": "number", - "description": "This is the speed multiplier that will be used.", - "minimum": 0.25, - "maximum": 2, - "example": null + "description": "This is the max number of tokens that the assistant will be allowed to generate in each turn of the conversation. Default is 250.", + "minimum": 50, + "maximum": 10000 }, - "chunkPlan": { - "description": "This is the plan for chunking the model output before it is sent to the voice provider.", - "allOf": [ - { - "$ref": "#/components/schemas/ChunkPlan" - } - ] + "emotionRecognitionEnabled": { + "type": "boolean", + "description": "This determines whether we detect user's emotion while they speak and send it as an additional info to model.\n\nDefault `false` because the model is usually are good at understanding the user's emotion from text.\n\n@default false" + }, + "numFastTurns": { + "type": "number", + "description": "This sets how many turns at the start of the conversation to use a smaller, faster model from the same provider before switching to the primary model. Example, gpt-3.5-turbo if provider is openai.\n\nDefault is 0.\n\n@default 0", + "minimum": 0 } }, "required": [ "provider", - "voiceId", - "language" + "model" ] }, - "FallbackOpenAIVoice": { + "HangupNode": { "type": "object", "properties": { - "cachingEnabled": { + "type": { + "type": "string", + "enum": [ + "hangup" + ] + }, + "name": { + "type": "string", + "maxLength": 80 + }, + "isStart": { "type": "boolean", - "description": "This is the flag to toggle voice caching for the assistant.", - "example": true, - "default": true + "description": "This is whether or not the node is the start of the workflow." + }, + "metadata": { + "type": "object", + "description": "This is for metadata you want to store on the task." + } + }, + "required": [ + "type", + "name" + ] + }, + "WorkflowOpenAIModel": { + "type": "object", + "properties": { + "messages": { + "description": "These are the messages used to customize the prompt used for structured output extraction.\n\nWhen provided, these messages replace the default prompts. Message contents support LiquidJS templating with the following variables:\n- `{{transcript}}` or `{{messages}}` to reference the conversation (one is required)\n- `{{structuredOutput.name}}`, `{{structuredOutput.description}}`, or `{{structuredOutput.schema}}` to reference the structured output definition (one is required)\n- `{{systemPrompt}}`, `{{callEndedReason}}`, `{{duration}}`, `{{startedAt}}`, `{{endedAt}}`, and any `assistantOverrides.variableValues`\n\n`{{messages}}` is the full message history including tool calls; `{{transcript}}` is the spoken text only, which uses significantly fewer tokens.\n\nIf not provided, default system and user prompts are used.", + "type": "array", + "items": { + "$ref": "#/components/schemas/OpenAIMessage" + } }, "provider": { "type": "string", - "description": "This is the voice provider that will be used.", + "description": "This is the provider of the model (`openai`).", "enum": [ "openai" ] }, - "voiceId": { - "description": "This is the provider-specific ID that will be used.\nPlease note that ash, ballad, coral, sage, and verse may only be used with realtime models.", - "oneOf": [ - { - "type": "string", - "enum": [ - "alloy", - "echo", - "fable", - "onyx", - "nova", - "shimmer" - ], - "title": "Preset Voice Options" - }, - { - "type": "string", - "title": "OpenAI Voice ID" - } - ] - }, "model": { "type": "string", - "description": "This is the model that will be used for text-to-speech.", + "description": "This is the OpenAI model that will be used.\n\nWhen using Vapi OpenAI or your own Azure Credentials, you have the option to specify the region for the selected model. This shouldn't be specified unless you have a specific reason to do so. Vapi will automatically find the fastest region that make sense.\nThis is helpful when you are required to comply with Data Residency rules. Learn more about Azure regions here https://azure.microsoft.com/en-us/explore/global-infrastructure/data-residency/.", + "maxLength": 100, "enum": [ - "tts-1", - "tts-1-hd", - "gpt-4o-mini-tts" + "gpt-5.6-sol", + "gpt-5.6-terra", + "gpt-5.6-luna", + "gpt-5.5", + "chat-latest", + "gpt-5.4", + "gpt-5.4-mini", + "gpt-5.4-nano", + "gpt-5.2", + "gpt-5.2-chat-latest", + "gpt-5.1", + "gpt-5.1-chat-latest", + "gpt-5", + "gpt-5-chat-latest", + "gpt-5-mini", + "gpt-5-nano", + "gpt-4.1-2025-04-14", + "gpt-4.1-mini-2025-04-14", + "gpt-4.1-nano-2025-04-14", + "gpt-4.1", + "gpt-4.1-mini", + "gpt-4.1-nano", + "chatgpt-4o-latest", + "o3", + "o3-mini", + "o4-mini", + "o1-mini", + "o1-mini-2024-09-12", + "gpt-4o-mini-2024-07-18", + "gpt-4o-mini", + "gpt-4o", + "gpt-4o-2024-05-13", + "gpt-4o-2024-08-06", + "gpt-4o-2024-11-20", + "gpt-4-turbo", + "gpt-4-turbo-2024-04-09", + "gpt-4-turbo-preview", + "gpt-4-0125-preview", + "gpt-4-1106-preview", + "gpt-4", + "gpt-4-0613", + "gpt-3.5-turbo", + "gpt-3.5-turbo-0125", + "gpt-3.5-turbo-1106", + "gpt-3.5-turbo-16k", + "gpt-3.5-turbo-0613", + "gpt-5.6-luna:westus3", + "gpt-5.6-terra:westus3", + "gpt-5.6-sol:westus3", + "gpt-5.4:eastus2", + "gpt-5.4:swedencentral", + "gpt-5.4-mini:eastus2", + "gpt-5.4-mini:swedencentral", + "gpt-5.4-nano:eastus2", + "gpt-5.4-nano:swedencentral", + "gpt-5.2:eastus2", + "gpt-5.2:swedencentral", + "gpt-5.1:eastus2", + "gpt-5.1:swedencentral", + "gpt-5:eastus2", + "gpt-5:swedencentral", + "gpt-5:canadaeast", + "gpt-5:eastus", + "gpt-5:westeurope", + "gpt-5:germanywestcentral", + "gpt-5:polandcentral", + "gpt-5:spaincentral", + "gpt-5-mini:eastus2", + "gpt-5-mini:swedencentral", + "gpt-5-mini:westeurope", + "gpt-5-mini:germanywestcentral", + "gpt-5-mini:polandcentral", + "gpt-5-mini:spaincentral", + "gpt-5-nano:eastus2", + "gpt-5-nano:swedencentral", + "gpt-4.1-2025-04-14:westus", + "gpt-4.1-2025-04-14:eastus2", + "gpt-4.1-2025-04-14:eastus", + "gpt-4.1-2025-04-14:westus3", + "gpt-4.1-2025-04-14:northcentralus", + "gpt-4.1-2025-04-14:southcentralus", + "gpt-4.1-2025-04-14:westeurope", + "gpt-4.1-2025-04-14:germanywestcentral", + "gpt-4.1-2025-04-14:polandcentral", + "gpt-4.1-2025-04-14:spaincentral", + "gpt-4.1-mini-2025-04-14:westus", + "gpt-4.1-mini-2025-04-14:eastus2", + "gpt-4.1-mini-2025-04-14:eastus", + "gpt-4.1-mini-2025-04-14:westus3", + "gpt-4.1-mini-2025-04-14:northcentralus", + "gpt-4.1-mini-2025-04-14:southcentralus", + "gpt-4.1-mini-2025-04-14:westeurope", + "gpt-4.1-mini-2025-04-14:germanywestcentral", + "gpt-4.1-mini-2025-04-14:polandcentral", + "gpt-4.1-mini-2025-04-14:spaincentral", + "gpt-4.1-nano-2025-04-14:westus", + "gpt-4.1-nano-2025-04-14:eastus2", + "gpt-4.1-nano-2025-04-14:westus3", + "gpt-4.1-nano-2025-04-14:northcentralus", + "gpt-4.1-nano-2025-04-14:southcentralus", + "gpt-4o-2024-11-20:swedencentral", + "gpt-4o-2024-11-20:westus", + "gpt-4o-2024-11-20:eastus2", + "gpt-4o-2024-11-20:eastus", + "gpt-4o-2024-11-20:westus3", + "gpt-4o-2024-11-20:southcentralus", + "gpt-4o-2024-11-20:westeurope", + "gpt-4o-2024-11-20:germanywestcentral", + "gpt-4o-2024-11-20:polandcentral", + "gpt-4o-2024-11-20:spaincentral", + "gpt-4o-2024-08-06:westus", + "gpt-4o-2024-08-06:westus3", + "gpt-4o-2024-08-06:eastus", + "gpt-4o-2024-08-06:eastus2", + "gpt-4o-2024-08-06:northcentralus", + "gpt-4o-2024-08-06:southcentralus", + "gpt-4o-mini-2024-07-18:westus", + "gpt-4o-mini-2024-07-18:westus3", + "gpt-4o-mini-2024-07-18:eastus", + "gpt-4o-mini-2024-07-18:eastus2", + "gpt-4o-mini-2024-07-18:northcentralus", + "gpt-4o-mini-2024-07-18:southcentralus", + "gpt-4o-2024-05-13:eastus2", + "gpt-4o-2024-05-13:eastus", + "gpt-4o-2024-05-13:northcentralus", + "gpt-4o-2024-05-13:southcentralus", + "gpt-4o-2024-05-13:westus3", + "gpt-4o-2024-05-13:westus", + "gpt-4-turbo-2024-04-09:eastus2", + "gpt-4-0125-preview:eastus", + "gpt-4-0125-preview:northcentralus", + "gpt-4-0125-preview:southcentralus", + "gpt-4-1106-preview:australiaeast", + "gpt-4-1106-preview:canadaeast", + "gpt-4-1106-preview:france", + "gpt-4-1106-preview:india", + "gpt-4-1106-preview:norway", + "gpt-4-1106-preview:swedencentral", + "gpt-4-1106-preview:uk", + "gpt-4-1106-preview:westus", + "gpt-4-1106-preview:westus3", + "gpt-4-0613:canadaeast", + "gpt-3.5-turbo-0125:canadaeast", + "gpt-3.5-turbo-0125:northcentralus", + "gpt-3.5-turbo-0125:southcentralus", + "gpt-3.5-turbo-1106:canadaeast", + "gpt-3.5-turbo-1106:westus", + "gpt-4.1:australiaeast", + "gpt-4o:australiaeast", + "gpt-5.4-mini:australiaeast" ] }, - "instructions": { - "type": "string", - "description": "This is a prompt that allows you to control the voice of your generated audio.\nDoes not work with 'tts-1' or 'tts-1-hd' models.", - "maxLength": 10000 - }, - "speed": { + "temperature": { "type": "number", - "description": "This is the speed multiplier that will be used.", - "minimum": 0.25, - "maximum": 4, - "example": null + "description": "This is the temperature of the model.", + "minimum": 0, + "maximum": 2 }, - "chunkPlan": { - "description": "This is the plan for chunking the model output before it is sent to the voice provider.", - "allOf": [ - { - "$ref": "#/components/schemas/ChunkPlan" - } - ] + "maxTokens": { + "type": "number", + "description": "This is the max tokens of the model.", + "minimum": 50, + "maximum": 10000 } }, "required": [ "provider", - "voiceId" + "model" ] }, - "FallbackPlayHTVoice": { + "WorkflowAnthropicModel": { "type": "object", "properties": { - "cachingEnabled": { - "type": "boolean", - "description": "This is the flag to toggle voice caching for the assistant.", - "example": true, - "default": true + "messages": { + "description": "These are the messages used to customize the prompt used for structured output extraction.\n\nWhen provided, these messages replace the default prompts. Message contents support LiquidJS templating with the following variables:\n- `{{transcript}}` or `{{messages}}` to reference the conversation (one is required)\n- `{{structuredOutput.name}}`, `{{structuredOutput.description}}`, or `{{structuredOutput.schema}}` to reference the structured output definition (one is required)\n- `{{systemPrompt}}`, `{{callEndedReason}}`, `{{duration}}`, `{{startedAt}}`, `{{endedAt}}`, and any `assistantOverrides.variableValues`\n\n`{{messages}}` is the full message history including tool calls; `{{transcript}}` is the spoken text only, which uses significantly fewer tokens.\n\nIf not provided, default system and user prompts are used.", + "type": "array", + "items": { + "$ref": "#/components/schemas/OpenAIMessage" + } }, "provider": { "type": "string", - "description": "This is the voice provider that will be used.", + "description": "This is the provider of the model (`anthropic`).", "enum": [ - "playht" + "anthropic" ] }, - "voiceId": { - "description": "This is the provider-specific ID that will be used.", - "oneOf": [ - { - "type": "string", - "enum": [ - "jennifer", - "melissa", - "will", - "chris", - "matt", - "jack", - "ruby", - "davis", - "donna", - "michael" - ], - "title": "Preset Voice Options" - }, + "model": { + "type": "string", + "description": "This is the specific model that will be used.", + "maxLength": 100, + "enum": [ + "claude-3-opus-20240229", + "claude-3-sonnet-20240229", + "claude-3-haiku-20240307", + "claude-3-5-sonnet-20240620", + "claude-3-5-sonnet-20241022", + "claude-3-5-haiku-20241022", + "claude-3-7-sonnet-20250219", + "claude-opus-4-20250514", + "claude-opus-4-5-20251101", + "claude-opus-4-6", + "claude-sonnet-4-20250514", + "claude-sonnet-4-5-20250929", + "claude-sonnet-4-6", + "claude-sonnet-5", + "claude-haiku-4-5-20251001" + ] + }, + "thinking": { + "description": "This is the optional configuration for Anthropic's thinking feature.\n\n- If provided, `maxTokens` must be greater than `thinking.budgetTokens`.", + "allOf": [ { - "type": "string", - "title": "PlayHT Voice ID" + "$ref": "#/components/schemas/AnthropicThinkingConfig" } ] }, - "speed": { - "type": "number", - "description": "This is the speed multiplier that will be used.", - "minimum": 0.1, - "maximum": 5, - "example": null - }, "temperature": { "type": "number", - "description": "A floating point number between 0, exclusive, and 2, inclusive. If equal to null or not provided, the model's default temperature will be used. The temperature parameter controls variance. Lower temperatures result in more predictable results, higher temperatures allow each run to vary more, so the voice may sound less like the baseline voice.", - "minimum": 0.1, - "maximum": 2, - "example": null - }, - "emotion": { - "type": "string", - "description": "An emotion to be applied to the speech.", - "enum": [ - "female_happy", - "female_sad", - "female_angry", - "female_fearful", - "female_disgust", - "female_surprised", - "male_happy", - "male_sad", - "male_angry", - "male_fearful", - "male_disgust", - "male_surprised" - ], - "example": null - }, - "voiceGuidance": { - "type": "number", - "description": "A number between 1 and 6. Use lower numbers to reduce how unique your chosen voice will be compared to other voices.", - "minimum": 1, - "maximum": 6, - "example": null - }, - "styleGuidance": { - "type": "number", - "description": "A number between 1 and 30. Use lower numbers to to reduce how strong your chosen emotion will be. Higher numbers will create a very emotional performance.", - "minimum": 1, - "maximum": 30, - "example": null + "description": "This is the temperature of the model.", + "minimum": 0, + "maximum": 2 }, - "textGuidance": { + "maxTokens": { "type": "number", - "description": "A number between 1 and 2. This number influences how closely the generated speech adheres to the input text. Use lower values to create more fluid speech, but with a higher chance of deviating from the input text. Higher numbers will make the generated speech more accurate to the input text, ensuring that the words spoken align closely with the provided text.", - "minimum": 1, - "maximum": 2, - "example": null + "description": "This is the max tokens of the model.", + "minimum": 50, + "maximum": 10000 + } + }, + "required": [ + "provider", + "model" + ] + }, + "WorkflowAnthropicBedrockModel": { + "type": "object", + "properties": { + "messages": { + "description": "These are the messages used to customize the prompt used for structured output extraction.\n\nWhen provided, these messages replace the default prompts. Message contents support LiquidJS templating with the following variables:\n- `{{transcript}}` or `{{messages}}` to reference the conversation (one is required)\n- `{{structuredOutput.name}}`, `{{structuredOutput.description}}`, or `{{structuredOutput.schema}}` to reference the structured output definition (one is required)\n- `{{systemPrompt}}`, `{{callEndedReason}}`, `{{duration}}`, `{{startedAt}}`, `{{endedAt}}`, and any `assistantOverrides.variableValues`\n\n`{{messages}}` is the full message history including tool calls; `{{transcript}}` is the spoken text only, which uses significantly fewer tokens.\n\nIf not provided, default system and user prompts are used.", + "type": "array", + "items": { + "$ref": "#/components/schemas/OpenAIMessage" + } }, - "model": { + "provider": { "type": "string", - "description": "Playht voice model/engine to use.", + "description": "This is the provider of the model (`anthropic-bedrock`).", "enum": [ - "PlayHT2.0", - "PlayHT2.0-turbo", - "Play3.0-mini", - "PlayDialog" + "anthropic-bedrock" ] }, - "language": { + "model": { "type": "string", - "description": "The language to use for the speech.", + "description": "This is the specific model that will be used.", + "maxLength": 100, "enum": [ - "afrikaans", - "albanian", - "amharic", - "arabic", - "bengali", - "bulgarian", - "catalan", - "croatian", - "czech", - "danish", - "dutch", - "english", - "french", - "galician", - "german", - "greek", - "hebrew", - "hindi", - "hungarian", - "indonesian", - "italian", - "japanese", - "korean", - "malay", - "mandarin", - "polish", - "portuguese", - "russian", - "serbian", - "spanish", - "swedish", - "tagalog", - "thai", - "turkish", - "ukrainian", - "urdu", - "xhosa" + "claude-3-opus-20240229", + "claude-3-sonnet-20240229", + "claude-3-haiku-20240307", + "claude-3-5-sonnet-20240620", + "claude-3-5-sonnet-20241022", + "claude-3-5-haiku-20241022", + "claude-3-7-sonnet-20250219", + "claude-opus-4-20250514", + "claude-opus-4-5-20251101", + "claude-opus-4-6", + "claude-sonnet-4-20250514", + "claude-sonnet-4-5-20250929", + "claude-sonnet-4-6", + "claude-haiku-4-5-20251001", + "global.anthropic.claude-haiku-4-5-20251001-v1:0" ] }, - "chunkPlan": { - "description": "This is the plan for chunking the model output before it is sent to the voice provider.", + "thinking": { + "description": "This is the optional configuration for Anthropic's thinking feature.\n\n- If provided, `maxTokens` must be greater than `thinking.budgetTokens`.", "allOf": [ { - "$ref": "#/components/schemas/ChunkPlan" + "$ref": "#/components/schemas/AnthropicThinkingConfig" } ] + }, + "temperature": { + "type": "number", + "description": "This is the temperature of the model.", + "minimum": 0, + "maximum": 2 + }, + "maxTokens": { + "type": "number", + "description": "This is the max tokens of the model.", + "minimum": 50, + "maximum": 10000 } }, "required": [ "provider", - "voiceId" + "model" ] }, - "FallbackRimeAIVoice": { + "WorkflowGoogleModel": { "type": "object", "properties": { - "cachingEnabled": { - "type": "boolean", - "description": "This is the flag to toggle voice caching for the assistant.", - "example": true, - "default": true + "messages": { + "description": "These are the messages used to customize the prompt used for structured output extraction.\n\nWhen provided, these messages replace the default prompts. Message contents support LiquidJS templating with the following variables:\n- `{{transcript}}` or `{{messages}}` to reference the conversation (one is required)\n- `{{structuredOutput.name}}`, `{{structuredOutput.description}}`, or `{{structuredOutput.schema}}` to reference the structured output definition (one is required)\n- `{{systemPrompt}}`, `{{callEndedReason}}`, `{{duration}}`, `{{startedAt}}`, `{{endedAt}}`, and any `assistantOverrides.variableValues`\n\n`{{messages}}` is the full message history including tool calls; `{{transcript}}` is the spoken text only, which uses significantly fewer tokens.\n\nIf not provided, default system and user prompts are used.", + "type": "array", + "items": { + "$ref": "#/components/schemas/OpenAIMessage" + } }, "provider": { "type": "string", - "description": "This is the voice provider that will be used.", + "description": "This is the provider of the model (`google`).", "enum": [ - "rime-ai" - ] - }, - "voiceId": { - "description": "This is the provider-specific ID that will be used.", - "oneOf": [ - { - "type": "string", - "enum": [ - "abbie", - "allison", - "ally", - "alona", - "amber", - "ana", - "antoine", - "armon", - "brenda", - "brittany", - "carol", - "colin", - "courtney", - "elena", - "elliot", - "eva", - "geoff", - "gerald", - "hank", - "helen", - "hera", - "jen", - "joe", - "joy", - "juan", - "kendra", - "kendrick", - "kenneth", - "kevin", - "kris", - "linda", - "madison", - "marge", - "marina", - "marissa", - "marta", - "maya", - "nicholas", - "nyles", - "phil", - "reba", - "rex", - "rick", - "ritu", - "rob", - "rodney", - "rohan", - "rosco", - "samantha", - "sandy", - "selena", - "seth", - "sharon", - "stan", - "tamra", - "tanya", - "tibur", - "tj", - "tyler", - "viv", - "yadira", - "marsh", - "bayou", - "creek", - "brook", - "flower", - "spore", - "glacier", - "gulch", - "alpine", - "cove", - "lagoon", - "tundra", - "steppe", - "mesa", - "grove", - "rainforest", - "moraine", - "wildflower", - "peak", - "boulder", - "gypsum", - "zest", - "luna", - "celeste", - "orion", - "ursa", - "astra", - "esther", - "estelle", - "andromeda" - ], - "title": "Preset Voice Options" - }, - { - "type": "string", - "title": "RimeAI Voice ID" - } + "google" ] }, "model": { "type": "string", - "description": "This is the model that will be used. Defaults to 'arcana' when not specified.", + "description": "This is the name of the model. Ex. cognitivecomputations/dolphin-mixtral-8x7b", + "maxLength": 100, "enum": [ - "arcana", - "mistv2", - "mist" - ], - "example": "arcana" + "gemini-3.5-flash", + "gemini-3.1-flash-lite", + "gemini-3-flash-preview", + "gemini-2.5-pro", + "gemini-2.5-flash", + "gemini-2.5-flash-lite", + "gemini-2.0-flash-thinking-exp", + "gemini-2.0-pro-exp-02-05", + "gemini-2.0-flash", + "gemini-2.0-flash-lite", + "gemini-2.0-flash-exp", + "gemini-2.0-flash-realtime-exp", + "gemini-1.5-flash", + "gemini-1.5-flash-002", + "gemini-1.5-pro", + "gemini-1.5-pro-002", + "gemini-1.0-pro" + ] }, - "speed": { + "temperature": { "type": "number", - "description": "This is the speed multiplier that will be used.", - "minimum": 0.1, - "example": null - }, - "pauseBetweenBrackets": { - "type": "boolean", - "description": "This is a flag that controls whether to add slight pauses using angle brackets. Example: \"Hi. <200> I'd love to have a conversation with you.\" adds a 200ms pause between the first and second sentences.", - "example": false - }, - "phonemizeBetweenBrackets": { - "type": "boolean", - "description": "This is a flag that controls whether text inside brackets should be phonemized (converted to phonetic pronunciation) - Example: \"{h'El.o} World\" will pronounce \"Hello\" as expected.", - "example": false - }, - "reduceLatency": { - "type": "boolean", - "description": "This is a flag that controls whether to optimize for reduced latency in streaming. https://docs.rime.ai/api-reference/endpoint/websockets#param-reduce-latency", - "example": false - }, - "inlineSpeedAlpha": { - "type": "string", - "description": "This is a string that allows inline speed control using alpha notation. https://docs.rime.ai/api-reference/endpoint/websockets#param-inline-speed-alpha", - "example": null + "description": "This is the temperature of the model.", + "minimum": 0, + "maximum": 2 }, - "chunkPlan": { - "description": "This is the plan for chunking the model output before it is sent to the voice provider.", - "allOf": [ - { - "$ref": "#/components/schemas/ChunkPlan" - } - ] + "maxTokens": { + "type": "number", + "description": "This is the max tokens of the model.", + "minimum": 50, + "maximum": 10000 } }, "required": [ "provider", - "voiceId" + "model" ] }, - "FallbackSesameVoice": { + "WorkflowCustomModel": { "type": "object", "properties": { - "cachingEnabled": { - "type": "boolean", - "description": "This is the flag to toggle voice caching for the assistant.", - "example": true, - "default": true + "messages": { + "description": "These are the messages used to customize the prompt used for structured output extraction.\n\nWhen provided, these messages replace the default prompts. Message contents support LiquidJS templating with the following variables:\n- `{{transcript}}` or `{{messages}}` to reference the conversation (one is required)\n- `{{structuredOutput.name}}`, `{{structuredOutput.description}}`, or `{{structuredOutput.schema}}` to reference the structured output definition (one is required)\n- `{{systemPrompt}}`, `{{callEndedReason}}`, `{{duration}}`, `{{startedAt}}`, `{{endedAt}}`, and any `assistantOverrides.variableValues`\n\n`{{messages}}` is the full message history including tool calls; `{{transcript}}` is the spoken text only, which uses significantly fewer tokens.\n\nIf not provided, default system and user prompts are used.", + "type": "array", + "items": { + "$ref": "#/components/schemas/OpenAIMessage" + } }, "provider": { "type": "string", - "description": "This is the voice provider that will be used.", + "description": "This is the provider of the model (`custom-llm`).", "enum": [ - "sesame" + "custom-llm" ] }, - "voiceId": { + "metadataSendMode": { "type": "string", - "description": "This is the provider-specific ID that will be used.", - "title": "Sesame Voice ID. This should be either a name (a built-in voice) or a UUID (a custom voice)." + "description": "This determines whether metadata is sent in requests to the custom provider.\n\n- `off` will not send any metadata. payload will look like `{ messages }`\n- `variable` will send `assistant.metadata` as a variable on the payload. payload will look like `{ messages, metadata }`\n- `destructured` will send `assistant.metadata` fields directly on the payload. payload will look like `{ messages, ...metadata }`\n\nFurther, `variable` and `destructured` will send `call`, `phoneNumber`, and `customer` objects in the payload.\n\nDefault is `variable`.", + "enum": [ + "off", + "variable", + "destructured" + ] + }, + "url": { + "type": "string", + "description": "These is the URL we'll use for the OpenAI client's `baseURL`. Ex. https://openrouter.ai/api/v1" + }, + "headers": { + "type": "object", + "description": "These are the headers we'll use for the OpenAI client's `headers`." + }, + "timeoutSeconds": { + "type": "number", + "description": "This sets the timeout for the connection to the custom provider without needing to stream any tokens back. Default is 20 seconds.", + "minimum": 20, + "maximum": 600 }, "model": { "type": "string", - "description": "This is the model that will be used.", - "enum": [ - "csm-1b" - ] + "description": "This is the name of the model. Ex. cognitivecomputations/dolphin-mixtral-8x7b", + "maxLength": 100 }, - "chunkPlan": { - "description": "This is the plan for chunking the model output before it is sent to the voice provider.", - "allOf": [ - { - "$ref": "#/components/schemas/ChunkPlan" - } - ] + "temperature": { + "type": "number", + "description": "This is the temperature of the model.", + "minimum": 0, + "maximum": 2 + }, + "maxTokens": { + "type": "number", + "description": "This is the max tokens of the model.", + "minimum": 50, + "maximum": 10000 } }, "required": [ "provider", - "voiceId", + "url", "model" ] }, - "FallbackSmallestAIVoice": { + "GlobalNodePlan": { "type": "object", "properties": { - "cachingEnabled": { + "enabled": { "type": "boolean", - "description": "This is the flag to toggle voice caching for the assistant.", - "example": true, - "default": true + "description": "This is the flag to determine if this node is a global node\n\n@default false", + "default": false }, - "provider": { + "enterCondition": { "type": "string", - "description": "This is the voice provider that will be used.", + "description": "This is the condition that will be checked to determine if the global node should be executed.\n\n@default ''", + "maxLength": 1000, + "default": "" + } + } + }, + "ConversationNode": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "This is the Conversation node. This can be used to start a conversation with the customer.\n\nThe flow is:\n- Workflow starts the conversation node\n- Model is active with the `prompt` and global context.\n- Model will call a tool to exit this node.\n- Workflow will extract variables from the conversation.\n- Workflow continues.", "enum": [ - "smallest-ai" + "conversation" ] }, - "voiceId": { - "description": "This is the provider-specific ID that will be used.", + "model": { + "description": "This is the model for the node.\n\nThis overrides `workflow.model`.", "oneOf": [ { - "type": "string", - "enum": [ - "emily", - "jasmine", - "arman", - "james", - "mithali", - "aravind", - "raj", - "diya", - "raman", - "ananya", - "isha", - "william", - "aarav", - "monika", - "niharika", - "deepika", - "raghav", - "kajal", - "radhika", - "mansi", - "nisha", - "saurabh", - "pooja", - "saina", - "sanya" - ], - "title": "Preset Voice Options" + "$ref": "#/components/schemas/WorkflowOpenAIModel", + "title": "WorkflowOpenAIModel" }, { - "type": "string", - "title": "Smallest AI Voice ID" + "$ref": "#/components/schemas/WorkflowAnthropicModel", + "title": "WorkflowAnthropicModel" + }, + { + "$ref": "#/components/schemas/WorkflowAnthropicBedrockModel", + "title": "WorkflowAnthropicBedrockModel" + }, + { + "$ref": "#/components/schemas/WorkflowGoogleModel", + "title": "WorkflowGoogleModel" + }, + { + "$ref": "#/components/schemas/WorkflowCustomModel", + "title": "WorkflowCustomModel" } ] }, - "model": { - "type": "string", - "description": "Smallest AI voice model to use. Defaults to 'lightning' when not specified.", - "enum": [ - "lightning" - ] - }, - "speed": { - "type": "number", - "description": "This is the speed multiplier that will be used.", - "example": null - }, - "chunkPlan": { - "description": "This is the plan for chunking the model output before it is sent to the voice provider.", - "allOf": [ + "transcriber": { + "description": "This is the transcriber for the node.\n\nThis overrides `workflow.transcriber`.", + "oneOf": [ { - "$ref": "#/components/schemas/ChunkPlan" + "$ref": "#/components/schemas/AssemblyAITranscriber", + "title": "AssemblyAITranscriber" + }, + { + "$ref": "#/components/schemas/AzureSpeechTranscriber", + "title": "AzureSpeechTranscriber" + }, + { + "$ref": "#/components/schemas/CustomTranscriber", + "title": "CustomTranscriber" + }, + { + "$ref": "#/components/schemas/DeepgramTranscriber", + "title": "DeepgramTranscriber" + }, + { + "$ref": "#/components/schemas/ElevenLabsTranscriber", + "title": "ElevenLabsTranscriber" + }, + { + "$ref": "#/components/schemas/GladiaTranscriber", + "title": "GladiaTranscriber" + }, + { + "$ref": "#/components/schemas/GoogleTranscriber", + "title": "GoogleTranscriber" + }, + { + "$ref": "#/components/schemas/SpeechmaticsTranscriber", + "title": "SpeechmaticsTranscriber" + }, + { + "$ref": "#/components/schemas/TalkscriberTranscriber", + "title": "TalkscriberTranscriber" + }, + { + "$ref": "#/components/schemas/OpenAITranscriber", + "title": "OpenAITranscriber" + }, + { + "$ref": "#/components/schemas/CartesiaTranscriber", + "title": "CartesiaTranscriber" + }, + { + "$ref": "#/components/schemas/SonioxTranscriber", + "title": "SonioxTranscriber" + }, + { + "$ref": "#/components/schemas/XaiTranscriber", + "title": "XaiTranscriber" + }, + { + "$ref": "#/components/schemas/VapiTranscriber", + "title": "VapiTranscriber" } ] - } - }, - "required": [ - "provider", - "voiceId" - ] - }, - "FallbackTavusVoice": { - "type": "object", - "properties": { - "cachingEnabled": { - "type": "boolean", - "description": "This is the flag to toggle voice caching for the assistant.", - "example": true, - "default": true - }, - "provider": { - "type": "string", - "description": "This is the voice provider that will be used.", - "enum": [ - "tavus" - ] }, - "voiceId": { - "description": "This is the provider-specific ID that will be used.", + "voice": { + "description": "This is the voice for the node.\n\nThis overrides `workflow.voice`.", "oneOf": [ { - "type": "string", - "enum": [ - "r52da2535a" - ], - "title": "Preset Voice Options" + "$ref": "#/components/schemas/AzureVoice", + "title": "AzureVoice" }, { - "type": "string", - "title": "Tavus Voice ID" + "$ref": "#/components/schemas/CartesiaVoice", + "title": "CartesiaVoice" + }, + { + "$ref": "#/components/schemas/CustomVoice", + "title": "CustomVoice" + }, + { + "$ref": "#/components/schemas/DeepgramVoice", + "title": "DeepgramVoice" + }, + { + "$ref": "#/components/schemas/ElevenLabsVoice", + "title": "ElevenLabsVoice" + }, + { + "$ref": "#/components/schemas/HumeVoice", + "title": "HumeVoice" + }, + { + "$ref": "#/components/schemas/LMNTVoice", + "title": "LMNTVoice" + }, + { + "$ref": "#/components/schemas/NeuphonicVoice", + "title": "NeuphonicVoice" + }, + { + "$ref": "#/components/schemas/OpenAIVoice", + "title": "OpenAIVoice" + }, + { + "$ref": "#/components/schemas/PlayHTVoice", + "title": "PlayHTVoice" + }, + { + "$ref": "#/components/schemas/WellSaidVoice", + "title": "WellSaidVoice" + }, + { + "$ref": "#/components/schemas/RimeAIVoice", + "title": "RimeAIVoice" + }, + { + "$ref": "#/components/schemas/SmallestAIVoice", + "title": "SmallestAIVoice" + }, + { + "$ref": "#/components/schemas/TavusVoice", + "title": "TavusVoice" + }, + { + "$ref": "#/components/schemas/VapiVoice", + "title": "VapiVoice" + }, + { + "$ref": "#/components/schemas/SesameVoice", + "title": "SesameVoice" + }, + { + "$ref": "#/components/schemas/InworldVoice", + "title": "InworldVoice" + }, + { + "$ref": "#/components/schemas/MinimaxVoice", + "title": "MinimaxVoice" + }, + { + "$ref": "#/components/schemas/XaiVoice", + "title": "XaiVoice" + }, + { + "$ref": "#/components/schemas/MicrosoftVoice", + "title": "MicrosoftVoice" } ] }, - "personaId": { - "type": "string", - "description": "This is the unique identifier for the persona that the replica will use in the conversation." - }, - "callbackUrl": { - "type": "string", - "description": "This is the url that will receive webhooks with updates regarding the conversation state." - }, - "conversationName": { - "type": "string", - "description": "This is the name for the conversation." + "tools": { + "type": "array", + "description": "These are the tools that the conversation node can use during the call. To use existing tools, use `toolIds`.\n\nBoth `tools` and `toolIds` can be used together.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/CreateApiRequestToolDTO", + "title": "ApiRequestTool" + }, + { + "$ref": "#/components/schemas/CreateBashToolDTO", + "title": "BashTool" + }, + { + "$ref": "#/components/schemas/CreateCodeToolDTO", + "title": "CodeTool" + }, + { + "$ref": "#/components/schemas/CreateComputerToolDTO", + "title": "ComputerTool" + }, + { + "$ref": "#/components/schemas/CreateDtmfToolDTO", + "title": "DtmfTool" + }, + { + "$ref": "#/components/schemas/CreateEndCallToolDTO", + "title": "EndCallTool" + }, + { + "$ref": "#/components/schemas/CreateFunctionToolDTO", + "title": "FunctionTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelCalendarAvailabilityToolDTO", + "title": "GoHighLevelCalendarAvailabilityTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelCalendarEventCreateToolDTO", + "title": "GoHighLevelCalendarEventCreateTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelContactCreateToolDTO", + "title": "GoHighLevelContactCreateTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelContactGetToolDTO", + "title": "GoHighLevelContactGetTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarCheckAvailabilityToolDTO", + "title": "GoogleCalendarCheckAvailabilityTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarCreateEventToolDTO", + "title": "GoogleCalendarCreateEventTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleSheetsRowAppendToolDTO", + "title": "GoogleSheetsRowAppendTool" + }, + { + "$ref": "#/components/schemas/CreateHandoffToolDTO", + "title": "HandoffTool" + }, + { + "$ref": "#/components/schemas/CreateMcpToolDTO", + "title": "McpTool" + }, + { + "$ref": "#/components/schemas/CreateQueryToolDTO", + "title": "QueryTool" + }, + { + "$ref": "#/components/schemas/CreateSlackSendMessageToolDTO", + "title": "SlackSendMessageTool" + }, + { + "$ref": "#/components/schemas/CreateSmsToolDTO", + "title": "SmsTool" + }, + { + "$ref": "#/components/schemas/CreateTextEditorToolDTO", + "title": "TextEditorTool" + }, + { + "$ref": "#/components/schemas/CreateTransferCallToolDTO", + "title": "TransferCallTool" + }, + { + "$ref": "#/components/schemas/CreateSipRequestToolDTO", + "title": "SipRequestTool" + }, + { + "$ref": "#/components/schemas/CreateVoicemailToolDTO", + "title": "VoicemailTool" + } + ] + } }, - "conversationalContext": { - "type": "string", - "description": "This is the context that will be appended to any context provided in the persona, if one is provided." + "toolIds": { + "description": "These are the tools that the conversation node can use during the call. To use transient tools, use `tools`.\n\nBoth `tools` and `toolIds` can be used together.", + "type": "array", + "items": { + "type": "string" + } }, - "customGreeting": { + "prompt": { "type": "string", - "description": "This is the custom greeting that the replica will give once a participant joines the conversation." + "maxLength": 5000 }, - "properties": { - "description": "These are optional properties used to customize the conversation.", + "globalNodePlan": { + "description": "This is the plan for the global node.", "allOf": [ { - "$ref": "#/components/schemas/TavusConversationProperties" + "$ref": "#/components/schemas/GlobalNodePlan" } ] }, - "chunkPlan": { - "description": "This is the plan for chunking the model output before it is sent to the voice provider.", + "variableExtractionPlan": { + "description": "This is the plan that controls the variable extraction from the user's responses.\n\nUsage:\nUse `schema` to specify what you want to extract from the user's responses.\n```json\n{\n \"schema\": {\n \"type\": \"object\",\n \"properties\": {\n \"user\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n },\n \"age\": {\n \"type\": \"number\"\n }\n }\n }\n }\n }\n}\n```\n\nThis will be extracted as `{{ user.name }}` and `{{ user.age }}` respectively.\n\n(Optional) Use `aliases` to create new variables.\n\n```json\n{\n \"aliases\": [\n {\n \"key\": \"userAge\",\n \"value\": \"{{user.age}}\"\n },\n {\n \"key\": \"userName\",\n \"value\": \"{{user.name}}\"\n }\n ]\n}\n```\n\nThis will be extracted as `{{ userAge }}` and `{{ userName }}` respectively.\n\nNote: The `schema` field is required for Conversation nodes if you want to extract variables from the user's responses. `aliases` is just a convenience.", "allOf": [ { - "$ref": "#/components/schemas/ChunkPlan" + "$ref": "#/components/schemas/VariableExtractionPlan" } ] + }, + "name": { + "type": "string", + "maxLength": 80 + }, + "isStart": { + "type": "boolean", + "description": "This is whether or not the node is the start of the workflow." + }, + "metadata": { + "type": "object", + "description": "This is for metadata you want to store on the task." } }, "required": [ - "provider", - "voiceId" + "type", + "name" ] }, - "FallbackVapiVoice": { + "ToolNode": { "type": "object", "properties": { - "cachingEnabled": { - "type": "boolean", - "description": "This is the flag to toggle voice caching for the assistant.", - "example": true, - "default": true - }, - "provider": { - "type": "string", - "description": "This is the voice provider that will be used.", - "enum": [ - "vapi" - ] - }, - "voiceId": { + "type": { "type": "string", - "description": "The voices provided by Vapi", + "description": "This is the Tool node. This can be used to call a tool in your workflow.\n\nThe flow is:\n- Workflow starts the tool node\n- Model is called to extract parameters needed by the tool from the conversation history\n- Tool is called with the parameters\n- Server returns a response\n- Workflow continues with the response", "enum": [ - "Elliot", - "Kylie", - "Rohan", - "Lily", - "Savannah", - "Hana", - "Neha", - "Cole", - "Harry", - "Paige", - "Spencer" + "tool" ] }, - "speed": { - "type": "number", - "description": "This is the speed multiplier that will be used.\n\n@default 1", - "minimum": 0.25, - "maximum": 2, - "default": 1 - }, - "chunkPlan": { - "description": "This is the plan for chunking the model output before it is sent to the voice provider.", - "allOf": [ + "tool": { + "description": "This is the tool to call. To use an existing tool, send `toolId` instead.", + "oneOf": [ { - "$ref": "#/components/schemas/ChunkPlan" + "$ref": "#/components/schemas/CreateApiRequestToolDTO", + "title": "ApiRequestTool" + }, + { + "$ref": "#/components/schemas/CreateBashToolDTO", + "title": "BashTool" + }, + { + "$ref": "#/components/schemas/CreateCodeToolDTO", + "title": "CodeTool" + }, + { + "$ref": "#/components/schemas/CreateComputerToolDTO", + "title": "ComputerTool" + }, + { + "$ref": "#/components/schemas/CreateDtmfToolDTO", + "title": "DtmfTool" + }, + { + "$ref": "#/components/schemas/CreateEndCallToolDTO", + "title": "EndCallTool" + }, + { + "$ref": "#/components/schemas/CreateFunctionToolDTO", + "title": "FunctionTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelCalendarAvailabilityToolDTO", + "title": "GoHighLevelCalendarAvailabilityTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelCalendarEventCreateToolDTO", + "title": "GoHighLevelCalendarEventCreateTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelContactCreateToolDTO", + "title": "GoHighLevelContactCreateTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelContactGetToolDTO", + "title": "GoHighLevelContactGetTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarCheckAvailabilityToolDTO", + "title": "GoogleCalendarCheckAvailabilityTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarCreateEventToolDTO", + "title": "GoogleCalendarCreateEventTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleSheetsRowAppendToolDTO", + "title": "GoogleSheetsRowAppendTool" + }, + { + "$ref": "#/components/schemas/CreateHandoffToolDTO", + "title": "HandoffTool" + }, + { + "$ref": "#/components/schemas/CreateMcpToolDTO", + "title": "McpTool" + }, + { + "$ref": "#/components/schemas/CreateQueryToolDTO", + "title": "QueryTool" + }, + { + "$ref": "#/components/schemas/CreateSlackSendMessageToolDTO", + "title": "SlackSendMessageTool" + }, + { + "$ref": "#/components/schemas/CreateSmsToolDTO", + "title": "SmsTool" + }, + { + "$ref": "#/components/schemas/CreateTextEditorToolDTO", + "title": "TextEditorTool" + }, + { + "$ref": "#/components/schemas/CreateTransferCallToolDTO", + "title": "TransferCallTool" + }, + { + "$ref": "#/components/schemas/CreateSipRequestToolDTO", + "title": "SipRequestTool" + }, + { + "$ref": "#/components/schemas/CreateVoicemailToolDTO", + "title": "VoicemailTool" } ] + }, + "toolId": { + "type": "string", + "description": "This is the tool to call. To use a transient tool, send `tool` instead." + }, + "name": { + "type": "string", + "maxLength": 80 + }, + "isStart": { + "type": "boolean", + "description": "This is whether or not the node is the start of the workflow." + }, + "metadata": { + "type": "object", + "description": "This is for metadata you want to store on the task." } }, "required": [ - "provider", - "voiceId" + "type", + "name" ] }, - "FallbackInworldVoice": { + "VoicemailDetectionBackoffPlan": { "type": "object", "properties": { - "cachingEnabled": { - "type": "boolean", - "description": "This is the flag to toggle voice caching for the assistant.", - "example": true, - "default": true - }, - "provider": { - "type": "string", - "description": "This is the voice provider that will be used.", - "enum": [ - "inworld" - ] + "startAtSeconds": { + "type": "number", + "description": "This is the number of seconds to wait before starting the first retry attempt.", + "minimum": 0, + "default": 5 }, - "voiceId": { - "type": "string", - "description": "Available voices by language:\n• en: Alex, Ashley, Craig, Deborah, Dennis, Edward, Elizabeth, Hades, Julia, Pixie, Mark, Olivia, Priya, Ronald, Sarah, Shaun, Theodore, Timothy, Wendy, Dominus\n• zh: Yichen, Xiaoyin, Xinyi, Jing\n• nl: Erik, Katrien, Lennart, Lore\n• fr: Alain, Hélène, Mathieu, Étienne\n• de: Johanna, Josef\n• it: Gianni, Orietta\n• ja: Asuka, Satoshi\n• ko: Hyunwoo, Minji, Seojun, Yoona\n• pl: Szymon, Wojciech\n• pt: Heitor, Maitê\n• es: Diego, Lupita, Miguel, Rafael", - "maxLength": 120, - "title": "Inworld Voice ID", - "enum": [ - "Alex", - "Ashley", - "Craig", - "Deborah", - "Dennis", - "Edward", - "Elizabeth", - "Hades", - "Julia", - "Pixie", - "Mark", - "Olivia", - "Priya", - "Ronald", - "Sarah", - "Shaun", - "Theodore", - "Timothy", - "Wendy", - "Dominus", - "Yichen", - "Xiaoyin", - "Xinyi", - "Jing", - "Erik", - "Katrien", - "Lennart", - "Lore", - "Alain", - "Hélène", - "Mathieu", - "Étienne", - "Johanna", - "Josef", - "Gianni", - "Orietta", - "Asuka", - "Satoshi", - "Hyunwoo", - "Minji", - "Seojun", - "Yoona", - "Szymon", - "Wojciech", - "Heitor", - "Maitê", - "Diego", - "Lupita", - "Miguel", - "Rafael" - ], - "example": "Alex" + "frequencySeconds": { + "type": "number", + "description": "This is the interval in seconds between retry attempts.", + "minimum": 2.5, + "default": 5 }, - "model": { - "type": "string", - "description": "This is the model that will be used.", - "enum": [ - "inworld-tts-1" - ], - "default": "inworld-tts-1" + "maxRetries": { + "type": "number", + "description": "This is the maximum number of retry attempts before giving up.", + "minimum": 1, + "maximum": 10, + "default": 6 + } + } + }, + "GoogleVoicemailDetectionPlan": { + "type": "object", + "properties": { + "beepMaxAwaitSeconds": { + "type": "number", + "description": "This is the maximum duration from the start of the call that we will wait for a voicemail beep, before speaking our message\n\n- If we detect a voicemail beep before this, we will speak the message at that point.\n\n- Setting too low a value means that the bot will start speaking its voicemail message too early. If it does so before the actual beep, it will get cut off. You should definitely tune this to your use case.\n\n@default 30\n@min 0\n@max 60", + "minimum": 0, + "maximum": 30, + "default": 30 }, - "languageCode": { + "provider": { "type": "string", - "description": "Language code for Inworld TTS synthesis", - "default": "en", + "description": "This is the provider to use for voicemail detection.", "enum": [ - "en", - "zh", - "ko", - "nl", - "fr", - "es", - "ja", - "de", - "it", - "pl", - "pt" + "google" ] }, - "chunkPlan": { - "description": "This is the plan for chunking the model output before it is sent to the voice provider.", + "backoffPlan": { + "description": "This is the backoff plan for the voicemail detection.", "allOf": [ { - "$ref": "#/components/schemas/ChunkPlan" + "$ref": "#/components/schemas/VoicemailDetectionBackoffPlan" } ] + }, + "type": { + "type": "string", + "description": "This is the detection type to use for voicemail detection.\n- 'audio': Uses native audio models (default)\n- 'transcript': Uses ASR/transcript-based detection\n@default 'audio' (audio detection)", + "enum": [ + "audio", + "transcript" + ] } }, "required": [ - "provider", - "voiceId" + "provider" ] }, - "FallbackMinimaxVoice": { + "OpenAIVoicemailDetectionPlan": { "type": "object", "properties": { - "cachingEnabled": { - "type": "boolean", - "description": "This is the flag to toggle voice caching for the assistant.", - "example": true, - "default": true + "beepMaxAwaitSeconds": { + "type": "number", + "description": "This is the maximum duration from the start of the call that we will wait for a voicemail beep, before speaking our message\n\n- If we detect a voicemail beep before this, we will speak the message at that point.\n\n- Setting too low a value means that the bot will start speaking its voicemail message too early. If it does so before the actual beep, it will get cut off. You should definitely tune this to your use case.\n\n@default 30\n@min 0\n@max 60", + "minimum": 0, + "maximum": 30, + "default": 30 }, "provider": { "type": "string", - "description": "This is the voice provider that will be used.", + "description": "This is the provider to use for voicemail detection.", "enum": [ - "minimax" + "openai" ] }, - "voiceId": { - "type": "string", - "description": "This is the provider-specific ID that will be used. Use a voice from MINIMAX_PREDEFINED_VOICES or a custom cloned voice ID.", - "title": "This is the Minimax Voice ID" - }, - "model": { - "type": "string", - "description": "This is the model that will be used. Options are 'speech-02-hd' and 'speech-02-turbo'.\nspeech-02-hd is optimized for high-fidelity applications like voiceovers and audiobooks.\nspeech-02-turbo is designed for real-time applications with low latency.\n\n@default \"speech-02-turbo\"", - "enum": [ - "speech-02-hd", - "speech-02-turbo" - ], - "example": "speech-02-turbo", - "default": "speech-02-turbo" - }, - "emotion": { - "type": "string", - "description": "The emotion to use for the voice. If not provided, will use auto-detect mode.\nOptions include: 'happy', 'sad', 'angry', 'fearful', 'surprised', 'disgusted', 'neutral'", - "example": "happy" - }, - "pitch": { - "type": "number", - "description": "Voice pitch adjustment. Range from -12 to 12 semitones.\n@default 0", - "minimum": -12, - "maximum": 12, - "example": 0, - "default": 0 - }, - "speed": { - "type": "number", - "description": "Voice speed adjustment. Range from 0.5 to 2.0.\n@default 1.0", - "minimum": 0.5, - "maximum": 2, - "example": 1, - "default": 1 - }, - "volume": { - "type": "number", - "description": "Voice volume adjustment. Range from 0.5 to 2.0.\n@default 1.0", - "minimum": 0.5, - "maximum": 2, - "example": 1, - "default": 1 - }, - "region": { - "type": "string", - "description": "The region for Minimax API. Defaults to \"worldwide\".", - "enum": [ - "worldwide", - "china" - ], - "default": "worldwide" - }, - "chunkPlan": { - "description": "This is the plan for chunking the model output before it is sent to the voice provider.", + "backoffPlan": { + "description": "This is the backoff plan for the voicemail detection.", "allOf": [ { - "$ref": "#/components/schemas/ChunkPlan" + "$ref": "#/components/schemas/VoicemailDetectionBackoffPlan" } ] + }, + "type": { + "type": "string", + "description": "This is the detection type to use for voicemail detection.\n- 'audio': Uses native audio models (default)\n- 'transcript': Uses ASR/transcript-based detection\n@default 'audio' (audio detection)", + "enum": [ + "audio", + "transcript" + ] } }, "required": [ - "provider", - "voiceId" + "provider" ] }, - "TransportConfigurationTwilio": { + "TwilioVoicemailDetectionPlan": { "type": "object", "properties": { "provider": { "type": "string", + "description": "This is the provider to use for voicemail detection.", "enum": [ "twilio" ] }, - "timeout": { - "type": "number", - "description": "The integer number of seconds that we should allow the phone to ring before assuming there is no answer.\nThe default is `60` seconds and the maximum is `600` seconds.\nFor some call flows, we will add a 5-second buffer to the timeout value you provide.\nFor this reason, a timeout value of 10 seconds could result in an actual timeout closer to 15 seconds.\nYou can set this to a short time, such as `15` seconds, to hang up before reaching an answering machine or voicemail.\n\n@default 60", - "minimum": 1, - "maximum": 600, - "example": 60 + "voicemailDetectionTypes": { + "type": "array", + "description": "These are the AMD messages from Twilio that are considered as voicemail. Default is ['machine_end_beep', 'machine_end_silence'].\n\n@default {Array} ['machine_end_beep', 'machine_end_silence']", + "enum": [ + "machine_start", + "human", + "fax", + "unknown", + "machine_end_beep", + "machine_end_silence", + "machine_end_other" + ], + "example": [ + "machine_end_beep", + "machine_end_silence" + ], + "items": { + "type": "string", + "enum": [ + "machine_start", + "human", + "fax", + "unknown", + "machine_end_beep", + "machine_end_silence", + "machine_end_other" + ] + } }, - "record": { + "enabled": { "type": "boolean", - "description": "Whether to record the call.\nCan be `true` to record the phone call, or `false` to not.\nThe default is `false`.\n\n@default false", - "example": false + "description": "This sets whether the assistant should detect voicemail. Defaults to true.\n\n@default true" }, - "recordingChannels": { - "type": "string", - "description": "The number of channels in the final recording.\nCan be: `mono` or `dual`.\nThe default is `mono`.\n`mono` records both legs of the call in a single channel of the recording file.\n`dual` records each leg to a separate channel of the recording file.\nThe first channel of a dual-channel recording contains the parent call and the second channel contains the child call.\n\n@default 'mono'", - "enum": [ - "mono", - "dual" - ], - "example": "mono" + "machineDetectionTimeout": { + "type": "number", + "description": "The number of seconds that Twilio should attempt to perform answering machine detection before timing out and returning AnsweredBy as unknown. Default is 30 seconds.\n\nIncreasing this value will provide the engine more time to make a determination. This can be useful when DetectMessageEnd is provided in the MachineDetection parameter and there is an expectation of long answering machine greetings that can exceed 30 seconds.\n\nDecreasing this value will reduce the amount of time the engine has to make a determination. This can be particularly useful when the Enable option is provided in the MachineDetection parameter and you want to limit the time for initial detection.\n\nCheck the [Twilio docs](https://www.twilio.com/docs/voice/answering-machine-detection#optional-api-tuning-parameters) for more info.\n\n@default 30", + "minimum": 3, + "maximum": 59 + }, + "machineDetectionSpeechThreshold": { + "type": "number", + "description": "The number of milliseconds that is used as the measuring stick for the length of the speech activity. Durations lower than this value will be interpreted as a human, longer as a machine. Default is 2400 milliseconds.\n\nIncreasing this value will reduce the chance of a False Machine (detected machine, actually human) for a long human greeting (e.g., a business greeting) but increase the time it takes to detect a machine.\n\nDecreasing this value will reduce the chances of a False Human (detected human, actually machine) for short voicemail greetings. The value of this parameter may need to be reduced by more than 1000ms to detect very short voicemail greetings. A reduction of that significance can result in increased False Machine detections. Adjusting the MachineDetectionSpeechEndThreshold is likely the better approach for short voicemails. Decreasing MachineDetectionSpeechThreshold will also reduce the time it takes to detect a machine.\n\nCheck the [Twilio docs](https://www.twilio.com/docs/voice/answering-machine-detection#optional-api-tuning-parameters) for more info.\n\n@default 2400", + "minimum": 1000, + "maximum": 6000 + }, + "machineDetectionSpeechEndThreshold": { + "type": "number", + "description": "The number of milliseconds of silence after speech activity at which point the speech activity is considered complete. Default is 1200 milliseconds.\n\nIncreasing this value will typically be used to better address the short voicemail greeting scenarios. For short voicemails, there is typically 1000-2000ms of audio followed by 1200-2400ms of silence and then additional audio before the beep. Increasing the MachineDetectionSpeechEndThreshold to ~2500ms will treat the 1200-2400ms of silence as a gap in the greeting but not the end of the greeting and will result in a machine detection. The downsides of such a change include:\n- Increasing the delay for human detection by the amount you increase this parameter, e.g., a change of 1200ms to 2500ms increases human detection delay by 1300ms.\n- Cases where a human has two utterances separated by a period of silence (e.g. a \"Hello\", then 2000ms of silence, and another \"Hello\") may be interpreted as a machine.\n\nDecreasing this value will result in faster human detection. The consequence is that it can lead to increased False Human (detected human, actually machine) detections because a silence gap in a voicemail greeting (not necessarily just in short voicemail scenarios) can be incorrectly interpreted as the end of speech.\n\nCheck the [Twilio docs](https://www.twilio.com/docs/voice/answering-machine-detection#optional-api-tuning-parameters) for more info.\n\n@default 1200", + "minimum": 500, + "maximum": 5000 + }, + "machineDetectionSilenceTimeout": { + "type": "number", + "description": "The number of milliseconds of initial silence after which an unknown AnsweredBy result will be returned. Default is 5000 milliseconds.\n\nIncreasing this value will result in waiting for a longer period of initial silence before returning an 'unknown' AMD result.\n\nDecreasing this value will result in waiting for a shorter period of initial silence before returning an 'unknown' AMD result.\n\nCheck the [Twilio docs](https://www.twilio.com/docs/voice/answering-machine-detection#optional-api-tuning-parameters) for more info.\n\n@default 5000", + "minimum": 2000, + "maximum": 10000 } }, "required": [ "provider" ] }, - "CreateAnthropicCredentialDTO": { + "VapiVoicemailDetectionPlan": { "type": "object", "properties": { + "beepMaxAwaitSeconds": { + "type": "number", + "description": "This is the maximum duration from the start of the call that we will wait for a voicemail beep, before speaking our message\n\n- If we detect a voicemail beep before this, we will speak the message at that point.\n\n- Setting too low a value means that the bot will start speaking its voicemail message too early. If it does so before the actual beep, it will get cut off. You should definitely tune this to your use case.\n\n@default 30\n@min 0\n@max 60", + "minimum": 0, + "maximum": 30, + "default": 30 + }, "provider": { "type": "string", + "description": "This is the provider to use for voicemail detection.", "enum": [ - "anthropic" + "vapi" ] }, - "apiKey": { - "type": "string", - "maxLength": 10000, - "description": "This is not returned in the API." + "backoffPlan": { + "description": "This is the backoff plan for the voicemail detection.", + "allOf": [ + { + "$ref": "#/components/schemas/VoicemailDetectionBackoffPlan" + } + ] }, - "name": { + "type": { "type": "string", - "description": "This is the name of credential. This is just for your reference.", - "minLength": 1, - "maxLength": 40 + "description": "This is the detection type to use for voicemail detection.\n- 'audio': Uses native audio models (default)\n- 'transcript': Uses ASR/transcript-based detection\n@default 'audio' (audio detection)", + "enum": [ + "audio", + "transcript" + ] } }, "required": [ - "provider", - "apiKey" + "provider" ] }, - "CreateAnyscaleCredentialDTO": { + "TransferHookAction": { "type": "object", "properties": { - "provider": { + "type": { "type": "string", + "description": "This is the type of action - must be \"transfer\"", "enum": [ - "anyscale" + "transfer" ] }, - "apiKey": { - "type": "string", - "maxLength": 10000, - "description": "This is not returned in the API." - }, - "name": { - "type": "string", - "description": "This is the name of credential. This is just for your reference.", - "minLength": 1, - "maxLength": 40 + "destination": { + "description": "This is the destination details for the transfer - can be a phone number or SIP URI", + "oneOf": [ + { + "$ref": "#/components/schemas/TransferDestinationNumber", + "title": "NumberTransferDestination" + }, + { + "$ref": "#/components/schemas/TransferDestinationSip", + "title": "SipTransferDestination" + } + ] } }, "required": [ - "provider", - "apiKey" + "type" ] }, - "CreateAssemblyAICredentialDTO": { + "FunctionCallHookAction": { "type": "object", "properties": { - "provider": { - "type": "string", - "enum": [ - "assembly-ai" - ] - }, - "apiKey": { - "type": "string", - "description": "This is not returned in the API." - }, - "name": { - "type": "string", - "description": "This is the name of credential. This is just for your reference.", - "minLength": 1, - "maxLength": 40 - } - }, - "required": [ - "provider", - "apiKey" - ] - }, - "AzureBlobStorageBucketPlan": { - "type": "object", - "properties": { - "connectionString": { - "type": "string", - "description": "This is the blob storage connection string for the Azure resource." - }, - "containerName": { - "type": "string", - "description": "This is the container name for the Azure blob storage." - }, - "path": { - "type": "string", - "description": "This is the path where call artifacts will be stored.\n\nUsage:\n- To store call artifacts in a specific folder, set this to the full path. Eg. \"/folder-name1/folder-name2\".\n- To store call artifacts in the root of the bucket, leave this blank.\n\n@default \"/\"" - } - }, - "required": [ - "connectionString", - "containerName" - ] - }, - "CreateAzureCredentialDTO": { - "type": "object", - "properties": { - "provider": { - "type": "string", - "enum": [ - "azure" - ] + "messages": { + "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" + }, + { + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] + } }, - "service": { + "type": { "type": "string", - "description": "This is the service being used in Azure.", "enum": [ - "speech", - "blob_storage" + "function" ], - "default": "speech" + "description": "The type of tool. \"function\" for Function tool." }, - "region": { - "type": "string", - "description": "This is the region of the Azure resource.", - "enum": [ - "australia", - "canadaeast", - "canadacentral", - "eastus2", - "eastus", - "france", - "india", - "japaneast", - "japanwest", - "uaenorth", - "northcentralus", - "norway", - "southcentralus", - "swedencentral", - "switzerland", - "uk", - "westus", - "westus3" + "async": { + "type": "boolean", + "example": false, + "description": "This determines if the tool is async.\n\n If async, the assistant will move forward without waiting for your server to respond. This is useful if you just want to trigger something on your server.\n\n If sync, the assistant will wait for your server to respond. This is useful if want assistant to respond with the result from your server.\n\n Defaults to synchronous (`false`)." + }, + "server": { + "description": "\n This is the server where a `tool-calls` webhook will be sent.\n\n Notes:\n - Webhook is sent to this server when a tool call is made.\n - Webhook contains the call, assistant, and phone number objects.\n - Webhook contains the variables set on the assistant.\n - Webhook is sent to the first available URL in this order: {{tool.server.url}}, {{assistant.server.url}}, {{phoneNumber.server.url}}, {{org.server.url}}.\n - Webhook expects a response with tool call result.", + "allOf": [ + { + "$ref": "#/components/schemas/Server" + } ] }, - "apiKey": { - "type": "string", - "description": "This is not returned in the API.", - "maxLength": 10000 + "variableExtractionPlan": { + "description": "Plan to extract variables from the tool response", + "allOf": [ + { + "$ref": "#/components/schemas/VariableExtractionPlan" + } + ] }, - "fallbackIndex": { - "type": "number", - "minimum": 1, - "description": "This is the order in which this storage provider is tried during upload retries. Lower numbers are tried first in increasing order." + "parameters": { + "description": "Static key-value pairs merged into the request body. Values support Liquid templates.", + "type": "array", + "items": { + "$ref": "#/components/schemas/ToolParameter" + } }, - "bucketPlan": { - "description": "This is the bucket plan that can be provided to store call artifacts in Azure Blob Storage.", + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", "allOf": [ { - "$ref": "#/components/schemas/AzureBlobStorageBucketPlan" + "$ref": "#/components/schemas/ToolRejectionPlan" } ] }, - "name": { - "type": "string", - "description": "This is the name of credential. This is just for your reference.", - "minLength": 1, - "maxLength": 40 + "function": { + "description": "This is the function definition of the tool.", + "allOf": [ + { + "$ref": "#/components/schemas/OpenAIFunction" + } + ] } }, "required": [ - "provider", - "service" + "type" ] }, - "CreateAzureOpenAICredentialDTO": { + "SayHookAction": { "type": "object", "properties": { - "provider": { + "type": { "type": "string", + "description": "This is the type of action - must be \"say\"", "enum": [ - "azure-openai" + "say" ] }, - "region": { - "type": "string", - "enum": [ - "australia", - "canadaeast", - "canadacentral", - "eastus2", - "eastus", - "france", - "india", - "japaneast", - "japanwest", - "uaenorth", - "northcentralus", - "norway", - "southcentralus", - "swedencentral", - "switzerland", - "uk", - "westus", - "westus3" + "exact": { + "description": "This is the exact message to say. When a string array is provided, one is randomly selected.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ], + "examples": [ + "Are you still there?", + [ + "I didn't catch that.", + "Could you repeat that?", + "Are you still there?" + ] ] }, - "models": { - "type": "array", - "enum": [ - "gpt-5", - "gpt-5-mini", - "gpt-5-nano", - "gpt-4.1-2025-04-14", - "gpt-4.1-mini-2025-04-14", - "gpt-4.1-nano-2025-04-14", - "gpt-4o-2024-11-20", - "gpt-4o-2024-08-06", - "gpt-4o-2024-05-13", - "gpt-4o-mini-2024-07-18", - "gpt-4-turbo-2024-04-09", - "gpt-4-0125-preview", - "gpt-4-1106-preview", - "gpt-4-0613", - "gpt-35-turbo-0125", - "gpt-35-turbo-1106" - ], - "example": [ - "gpt-4-0125-preview", - "gpt-4-0613" + "prompt": { + "description": "This is the prompt for the assistant to generate a response based on existing conversation.\nCan be a string or an array of chat messages.", + "oneOf": [ + { + "type": "string", + "title": "String" + }, + { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/SystemMessage", + "title": "SystemMessage" + }, + { + "$ref": "#/components/schemas/UserMessage", + "title": "UserMessage" + }, + { + "$ref": "#/components/schemas/AssistantMessage", + "title": "AssistantMessage" + }, + { + "$ref": "#/components/schemas/ToolMessage", + "title": "ToolMessage" + }, + { + "$ref": "#/components/schemas/DeveloperMessage", + "title": "DeveloperMessage" + } + ] + }, + "title": "MessageArray" + } ], - "items": { - "type": "string", - "enum": [ - "gpt-5", - "gpt-5-mini", - "gpt-5-nano", - "gpt-4.1-2025-04-14", - "gpt-4.1-mini-2025-04-14", - "gpt-4.1-nano-2025-04-14", - "gpt-4o-2024-11-20", - "gpt-4o-2024-08-06", - "gpt-4o-2024-05-13", - "gpt-4o-mini-2024-07-18", - "gpt-4-turbo-2024-04-09", - "gpt-4-0125-preview", - "gpt-4-1106-preview", - "gpt-4-0613", - "gpt-35-turbo-0125", - "gpt-35-turbo-1106" + "examples": [ + "Ask the user if they're still in the call", + [ + { + "role": "system", + "content": "You are a helpful assistant, and would like to know if the user is still in the call based on the conversation history in {{transcript}}" + } ] - } - }, - "openAIKey": { - "type": "string", - "maxLength": 10000, - "description": "This is not returned in the API." - }, - "ocpApimSubscriptionKey": { - "type": "string", - "description": "This is not returned in the API." - }, - "openAIEndpoint": { - "type": "string", - "maxLength": 10000 - }, - "name": { - "type": "string", - "description": "This is the name of credential. This is just for your reference.", - "minLength": 1, - "maxLength": 40 + ] } }, "required": [ - "provider", - "region", - "models", - "openAIKey", - "openAIEndpoint" + "type" ] }, - "SipTrunkGateway": { + "MessageAddHookAction": { "type": "object", "properties": { - "ip": { - "type": "string", - "description": "This is the address of the gateway. It can be an IPv4 address like 1.1.1.1 or a fully qualified domain name like my-sip-trunk.pstn.twilio.com." - }, - "port": { - "type": "number", - "description": "This is the port number of the gateway. Default is 5060.\n\n@default 5060", - "minimum": 1, - "maximum": 65535 - }, - "netmask": { - "type": "number", - "description": "This is the netmask of the gateway. Defaults to 32.\n\n@default 32", - "minimum": 24, - "maximum": 32 - }, - "inboundEnabled": { - "type": "boolean", - "description": "This is whether inbound calls are allowed from this gateway. Default is true.\n\n@default true" - }, - "outboundEnabled": { - "type": "boolean", - "description": "This is whether outbound calls should be sent to this gateway. Default is true.\n\nNote, if netmask is less than 32, it doesn't affect the outbound IPs that are tried. 1 attempt is made to `ip:port`.\n\n@default true" - }, - "outboundProtocol": { + "type": { "type": "string", - "description": "This is the protocol to use for SIP signaling outbound calls. Default is udp.\n\n@default udp", + "description": "This is the type of action - must be \"message.add\"", "enum": [ - "tls/srtp", - "tcp", - "tls", - "udp" + "message.add" ] }, - "optionsPingEnabled": { + "message": { + "description": "The message to add to the conversation in OpenAI format", + "example": { + "role": "system", + "content": "Context update from hook" + }, + "allOf": [ + { + "$ref": "#/components/schemas/OpenAIMessage" + } + ] + }, + "triggerResponseEnabled": { "type": "boolean", - "description": "This is whether to send options ping to the gateway. This can be used to check if the gateway is reachable. Default is false.\n\nThis is useful for high availability setups where you want to check if the gateway is reachable before routing calls to it. Note, if no gateway for a trunk is reachable, outbound calls will be rejected.\n\n@default false" + "description": "Whether to trigger an assistant response after adding the message", + "default": true } }, "required": [ - "ip" + "type", + "message" ] }, - "SipTrunkOutboundSipRegisterPlan": { - "type": "object", - "properties": { - "domain": { - "type": "string" - }, - "username": { - "type": "string" - }, - "realm": { - "type": "string" - } - } - }, - "SipTrunkOutboundAuthenticationPlan": { + "CallHookFilter": { "type": "object", "properties": { - "authPassword": { + "type": { "type": "string", - "description": "This is not returned in the API." + "description": "This is the type of filter - currently only \"oneOf\" is supported", + "enum": [ + "oneOf" + ], + "maxLength": 1000 }, - "authUsername": { - "type": "string" + "key": { + "type": "string", + "description": "This is the key to filter on (e.g. \"call.endedReason\")", + "maxLength": 1000 }, - "sipRegisterPlan": { - "description": "This can be used to configure if SIP register is required by the SIP trunk. If not provided, no SIP registration will be attempted.", - "allOf": [ - { - "$ref": "#/components/schemas/SipTrunkOutboundSipRegisterPlan" - } - ] + "oneOf": { + "description": "This is the array of possible values to match against", + "type": "array", + "items": { + "type": "string", + "maxLength": 1000 + } } - } - }, - "SbcConfiguration": { - "type": "object", - "properties": {} + }, + "required": [ + "type", + "key", + "oneOf" + ] }, - "CreateByoSipTrunkCredentialDTO": { + "CallHookCallEnding": { "type": "object", "properties": { - "provider": { + "on": { "type": "string", - "description": "This can be used to bring your own SIP trunks or to connect to a Carrier.", + "description": "This is the event that triggers this hook", "enum": [ - "byo-sip-trunk" - ] + "call.ending" + ], + "maxLength": 1000 }, - "gateways": { - "description": "This is the list of SIP trunk's gateways.", + "do": { "type": "array", + "description": "This is the set of actions to perform when the hook triggers", "items": { - "$ref": "#/components/schemas/SipTrunkGateway" + "oneOf": [ + { + "$ref": "#/components/schemas/ToolCallHookAction", + "title": "ToolCallHookAction" + }, + { + "$ref": "#/components/schemas/MessageAddHookAction", + "title": "MessageAddHookAction" + } + ] } }, - "outboundAuthenticationPlan": { - "description": "This can be used to configure the outbound authentication if required by the SIP trunk.", - "allOf": [ - { - "$ref": "#/components/schemas/SipTrunkOutboundAuthenticationPlan" - } - ] - }, - "outboundLeadingPlusEnabled": { - "type": "boolean", - "description": "This ensures the outbound origination attempts have a leading plus. Defaults to false to match conventional telecom behavior.\n\nUsage:\n- Vonage/Twilio requires leading plus for all outbound calls. Set this to true.\n\n@default false" - }, - "techPrefix": { - "type": "string", - "description": "This can be used to configure the tech prefix on outbound calls. This is an advanced property.", - "maxLength": 10000 - }, - "sipDiversionHeader": { - "type": "string", - "description": "This can be used to enable the SIP diversion header for authenticating the calling number if the SIP trunk supports it. This is an advanced property.", - "maxLength": 10000 - }, - "sbcConfiguration": { - "description": "This is an advanced configuration for enterprise deployments. This uses the onprem SBC to trunk into the SIP trunk's `gateways`, rather than the managed SBC provided by Vapi.", - "allOf": [ - { - "$ref": "#/components/schemas/SbcConfiguration" - } - ] - }, - "name": { - "type": "string", - "description": "This is the name of credential. This is just for your reference.", - "minLength": 1, - "maxLength": 40 + "filters": { + "description": "This is the set of filters that must match for the hook to trigger", + "type": "array", + "items": { + "$ref": "#/components/schemas/CallHookFilter" + } } }, "required": [ - "gateways" + "on", + "do" ] }, - "CreateCartesiaCredentialDTO": { + "CallHookAssistantSpeechInterrupted": { "type": "object", "properties": { - "provider": { + "on": { "type": "string", + "description": "This is the event that triggers this hook", "enum": [ - "cartesia" - ] - }, - "apiKey": { - "type": "string", - "description": "This is not returned in the API." + "assistant.speech.interrupted" + ], + "maxLength": 1000 }, - "name": { - "type": "string", - "description": "This is the name of credential. This is just for your reference.", - "minLength": 1, - "maxLength": 40 + "do": { + "type": "array", + "description": "This is the set of actions to perform when the hook triggers", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/SayHookAction", + "title": "SayHookAction" + }, + { + "$ref": "#/components/schemas/ToolCallHookAction", + "title": "ToolCallHookAction" + }, + { + "$ref": "#/components/schemas/MessageAddHookAction", + "title": "MessageAddHookAction" + } + ] + } } }, "required": [ - "provider", - "apiKey" + "on", + "do" ] }, - "CloudflareR2BucketPlan": { + "CallHookCustomerSpeechInterrupted": { "type": "object", "properties": { - "accessKeyId": { + "on": { "type": "string", - "description": "Cloudflare R2 Access key ID." - }, - "secretAccessKey": { - "type": "string", - "description": "Cloudflare R2 access key secret. This is not returned in the API." - }, - "url": { - "type": "string", - "description": "Cloudflare R2 base url." - }, - "name": { - "type": "string", - "description": "This is the name of the bucket." + "description": "This is the event that triggers this hook", + "enum": [ + "customer.speech.interrupted" + ], + "maxLength": 1000 }, - "path": { - "type": "string", - "description": "This is the path where call artifacts will be stored.\n\nUsage:\n- To store call artifacts in a specific folder, set this to the full path. Eg. \"/folder-name1/folder-name2\".\n- To store call artifacts in the root of the bucket, leave this blank.\n\n@default \"/\"" + "do": { + "type": "array", + "description": "This is the set of actions to perform when the hook triggers", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/SayHookAction", + "title": "SayHookAction" + }, + { + "$ref": "#/components/schemas/ToolCallHookAction", + "title": "ToolCallHookAction" + }, + { + "$ref": "#/components/schemas/MessageAddHookAction", + "title": "MessageAddHookAction" + } + ] + } } }, "required": [ - "name" + "on", + "do" ] }, - "CreateCloudflareCredentialDTO": { + "ToolCallHookAction": { "type": "object", "properties": { - "provider": { + "type": { "type": "string", + "description": "This is the type of action - must be \"tool\"", "enum": [ - "cloudflare" - ], - "description": "Credential provider. Only allowed value is cloudflare" - }, - "accountId": { - "type": "string", - "description": "Cloudflare Account Id." - }, - "apiKey": { - "type": "string", - "description": "Cloudflare API Key / Token." - }, - "accountEmail": { - "type": "string", - "description": "Cloudflare Account Email." - }, - "fallbackIndex": { - "type": "number", - "description": "This is the order in which this storage provider is tried during upload retries. Lower numbers are tried first in increasing order.", - "minimum": 1 + "tool" + ] }, - "bucketPlan": { - "description": "This is the bucket plan that can be provided to store call artifacts in R2", - "allOf": [ + "tool": { + "description": "This is the tool to call. To use an existing tool, send `toolId` instead.", + "oneOf": [ { - "$ref": "#/components/schemas/CloudflareR2BucketPlan" + "$ref": "#/components/schemas/CreateApiRequestToolDTO", + "title": "ApiRequestTool" + }, + { + "$ref": "#/components/schemas/CreateBashToolDTO", + "title": "BashTool" + }, + { + "$ref": "#/components/schemas/CreateCodeToolDTO", + "title": "CodeTool" + }, + { + "$ref": "#/components/schemas/CreateComputerToolDTO", + "title": "ComputerTool" + }, + { + "$ref": "#/components/schemas/CreateDtmfToolDTO", + "title": "DtmfTool" + }, + { + "$ref": "#/components/schemas/CreateEndCallToolDTO", + "title": "EndCallTool" + }, + { + "$ref": "#/components/schemas/CreateFunctionToolDTO", + "title": "FunctionTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelCalendarAvailabilityToolDTO", + "title": "GoHighLevelCalendarAvailabilityTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelCalendarEventCreateToolDTO", + "title": "GoHighLevelCalendarEventCreateTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelContactCreateToolDTO", + "title": "GoHighLevelContactCreateTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelContactGetToolDTO", + "title": "GoHighLevelContactGetTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarCheckAvailabilityToolDTO", + "title": "GoogleCalendarCheckAvailabilityTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarCreateEventToolDTO", + "title": "GoogleCalendarCreateEventTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleSheetsRowAppendToolDTO", + "title": "GoogleSheetsRowAppendTool" + }, + { + "$ref": "#/components/schemas/CreateHandoffToolDTO", + "title": "HandoffTool" + }, + { + "$ref": "#/components/schemas/CreateMcpToolDTO", + "title": "McpTool" + }, + { + "$ref": "#/components/schemas/CreateQueryToolDTO", + "title": "QueryTool" + }, + { + "$ref": "#/components/schemas/CreateSlackSendMessageToolDTO", + "title": "SlackSendMessageTool" + }, + { + "$ref": "#/components/schemas/CreateSmsToolDTO", + "title": "SmsTool" + }, + { + "$ref": "#/components/schemas/CreateTextEditorToolDTO", + "title": "TextEditorTool" + }, + { + "$ref": "#/components/schemas/CreateTransferCallToolDTO", + "title": "TransferCallTool" + }, + { + "$ref": "#/components/schemas/CreateSipRequestToolDTO", + "title": "SipRequestTool" + }, + { + "$ref": "#/components/schemas/CreateVoicemailToolDTO", + "title": "VoicemailTool" } ] }, - "name": { + "toolId": { "type": "string", - "description": "This is the name of credential. This is just for your reference.", - "minLength": 1, - "maxLength": 40 + "description": "This is the tool to call. To use a transient tool, send `tool` instead." } }, "required": [ - "provider" + "type" ] }, - "OAuth2AuthenticationPlan": { + "CustomerSpeechTimeoutOptions": { "type": "object", "properties": { - "type": { + "triggerResetMode": { "type": "string", + "description": "This is whether the counter for hook trigger resets the user speaks.\n\n@default never", "enum": [ - "oauth2" + "onUserSpeech", + "never" ] }, - "url": { - "type": "string", - "description": "This is the OAuth2 URL." - }, - "clientId": { - "type": "string", - "description": "This is the OAuth2 client ID." - }, - "clientSecret": { - "type": "string", - "description": "This is the OAuth2 client secret." + "timeoutSeconds": { + "type": "number", + "description": "This is the timeout in seconds before action is triggered.\nThe clock starts when the assistant finishes speaking and remains active until the user speaks.\n\n@default 7.5\n@minimum 2\n@maximum 1000", + "minimum": 1, + "maximum": 1000 }, - "scope": { - "type": "string", - "description": "This is the scope of the OAuth2 token.", - "maxLength": 1000 + "triggerMaxCount": { + "type": "number", + "description": "This is the maximum number of times the hook will trigger in a call.\n\n@default 3", + "minimum": 1, + "maximum": 10 } }, "required": [ - "type", - "url", - "clientId", - "clientSecret" + "timeoutSeconds" ] }, - "CreateCustomLLMCredentialDTO": { + "CallHookCustomerSpeechTimeout": { "type": "object", "properties": { - "provider": { + "on": { "type": "string", - "enum": [ - "custom-llm" - ] + "description": "Must be either \"customer.speech.timeout\" or match the pattern \"customer.speech.timeout[property=value]\"", + "maxLength": 1000 }, - "apiKey": { - "type": "string", - "maxLength": 10000, - "description": "This is not returned in the API." + "do": { + "type": "array", + "description": "This is the set of actions to perform when the hook triggers", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/SayHookAction", + "title": "SayHookAction" + }, + { + "$ref": "#/components/schemas/ToolCallHookAction", + "title": "ToolCallHookAction" + }, + { + "$ref": "#/components/schemas/MessageAddHookAction", + "title": "MessageAddHookAction" + } + ] + } }, - "authenticationPlan": { - "description": "This is the authentication plan. Currently supports OAuth2 RFC 6749. To use Bearer authentication, use apiKey", + "options": { + "description": "This is the set of filters that must match for the hook to trigger", "allOf": [ { - "$ref": "#/components/schemas/OAuth2AuthenticationPlan" + "$ref": "#/components/schemas/CustomerSpeechTimeoutOptions" } ] }, "name": { "type": "string", - "description": "This is the name of credential. This is just for your reference.", - "minLength": 1, - "maxLength": 40 + "description": "This is the name of the hook, it can be set by the user to identify the hook.\nIf no name is provided, the hook will be auto generated as UUID.\n\n@default UUID", + "maxLength": 1000 } }, "required": [ - "provider", - "apiKey" + "on", + "do" ] }, - "CreateDeepgramCredentialDTO": { + "CallHookModelResponseTimeout": { "type": "object", "properties": { - "provider": { + "on": { "type": "string", + "description": "This is the event that triggers this hook", "enum": [ - "deepgram" - ] - }, - "apiKey": { - "type": "string", - "description": "This is not returned in the API." - }, - "apiUrl": { - "type": "string", - "description": "This can be used to point to an onprem Deepgram instance. Defaults to api.deepgram.com." + "model.response.timeout" + ], + "maxLength": 1000 }, - "name": { - "type": "string", - "description": "This is the name of credential. This is just for your reference.", - "minLength": 1, - "maxLength": 40 + "do": { + "type": "array", + "description": "This is the set of actions to perform when the hook triggers", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/SayHookAction", + "title": "SayHookAction" + }, + { + "$ref": "#/components/schemas/ToolCallHookAction", + "title": "ToolCallHookAction" + }, + { + "$ref": "#/components/schemas/MessageAddHookAction", + "title": "MessageAddHookAction" + } + ] + } } }, "required": [ - "provider", - "apiKey" + "on", + "do" ] }, - "CreateDeepInfraCredentialDTO": { + "AIEdgeCondition": { "type": "object", "properties": { - "provider": { + "type": { "type": "string", "enum": [ - "deepinfra" + "ai" ] }, - "apiKey": { - "type": "string", - "description": "This is not returned in the API." - }, - "name": { + "prompt": { "type": "string", - "description": "This is the name of credential. This is just for your reference.", - "minLength": 1, - "maxLength": 40 + "description": "This is the prompt for the AI edge condition. It should evaluate to a boolean.", + "maxLength": 1000 } }, "required": [ - "provider", - "apiKey" + "type", + "prompt" ] }, - "CreateDeepSeekCredentialDTO": { + "Edge": { "type": "object", "properties": { - "provider": { - "type": "string", - "enum": [ - "deep-seek" + "condition": { + "oneOf": [ + { + "$ref": "#/components/schemas/AIEdgeCondition", + "title": "AIEdgeCondition" + } ] }, - "apiKey": { - "type": "string", - "description": "This is not returned in the API." - }, - "name": { - "type": "string", - "description": "This is the name of credential. This is just for your reference.", - "minLength": 1, - "maxLength": 40 - } - }, - "required": [ - "provider", - "apiKey" - ] - }, - "CreateElevenLabsCredentialDTO": { - "type": "object", - "properties": { - "provider": { + "from": { "type": "string", - "enum": [ - "11labs" - ] + "maxLength": 80 }, - "apiKey": { + "to": { "type": "string", - "maxLength": 10000, - "description": "This is not returned in the API." + "maxLength": 80 }, - "name": { - "type": "string", - "description": "This is the name of credential. This is just for your reference.", - "minLength": 1, - "maxLength": 40 + "metadata": { + "type": "object", + "description": "This is for metadata you want to store on the edge." } }, "required": [ - "provider", - "apiKey" + "from", + "to" ] }, - "GcpKey": { + "RecordingConsentPlanStayOnLine": { "type": "object", "properties": { - "type": { - "type": "string", - "description": "This is the type of the key. Most likely, this is \"service_account\"." - }, - "projectId": { - "type": "string", - "description": "This is the ID of the Google Cloud project associated with this key." - }, - "privateKeyId": { - "type": "string", - "description": "This is the unique identifier for the private key." - }, - "privateKey": { - "type": "string", - "description": "This is the private key in PEM format.\n\nNote: This is not returned in the API." - }, - "clientEmail": { - "type": "string", - "description": "This is the email address associated with the service account." - }, - "clientId": { - "type": "string", - "description": "This is the unique identifier for the client." - }, - "authUri": { + "message": { "type": "string", - "description": "This is the URI for the auth provider's authorization endpoint." + "description": "This is the message asking for consent to record the call.\nIf the type is `stay-on-line`, the message should ask the user to hang up if they do not consent.\nIf the type is `verbal`, the message should ask the user to verbally consent or decline.", + "maxLength": 1000, + "examples": [ + "For quality purposes, this call may be recorded. Please stay on the line if you agree or end the call if you do not consent.", + "This call may be recorded for quality and training purposes. Say \"I agree\" if you consent to being recorded, or \"I disagree\" if you do not consent." + ] }, - "tokenUri": { - "type": "string", - "description": "This is the URI for the auth provider's token endpoint." + "voice": { + "description": "This is the voice to use for the consent message. If not specified, inherits from the assistant's voice.\nUse a different voice for the consent message for a better user experience.", + "oneOf": [ + { + "$ref": "#/components/schemas/AzureVoice", + "title": "AzureVoice" + }, + { + "$ref": "#/components/schemas/CartesiaVoice", + "title": "CartesiaVoice" + }, + { + "$ref": "#/components/schemas/CustomVoice", + "title": "CustomVoice" + }, + { + "$ref": "#/components/schemas/DeepgramVoice", + "title": "DeepgramVoice" + }, + { + "$ref": "#/components/schemas/ElevenLabsVoice", + "title": "ElevenLabsVoice" + }, + { + "$ref": "#/components/schemas/HumeVoice", + "title": "HumeVoice" + }, + { + "$ref": "#/components/schemas/LMNTVoice", + "title": "LMNTVoice" + }, + { + "$ref": "#/components/schemas/NeuphonicVoice", + "title": "NeuphonicVoice" + }, + { + "$ref": "#/components/schemas/OpenAIVoice", + "title": "OpenAIVoice" + }, + { + "$ref": "#/components/schemas/PlayHTVoice", + "title": "PlayHTVoice" + }, + { + "$ref": "#/components/schemas/WellSaidVoice", + "title": "WellSaidVoice" + }, + { + "$ref": "#/components/schemas/RimeAIVoice", + "title": "RimeAIVoice" + }, + { + "$ref": "#/components/schemas/SmallestAIVoice", + "title": "SmallestAIVoice" + }, + { + "$ref": "#/components/schemas/TavusVoice", + "title": "TavusVoice" + }, + { + "$ref": "#/components/schemas/VapiVoice", + "title": "VapiVoice" + }, + { + "$ref": "#/components/schemas/SesameVoice", + "title": "SesameVoice" + }, + { + "$ref": "#/components/schemas/InworldVoice", + "title": "InworldVoice" + }, + { + "$ref": "#/components/schemas/MinimaxVoice", + "title": "MinimaxVoice" + }, + { + "$ref": "#/components/schemas/XaiVoice", + "title": "XaiVoice" + }, + { + "$ref": "#/components/schemas/MicrosoftVoice", + "title": "MicrosoftVoice" + } + ] }, - "authProviderX509CertUrl": { + "firstMessageMode": { "type": "string", - "description": "This is the URL of the public x509 certificate for the auth provider." + "description": "This controls whether the consent assistant speaks first or waits for the caller to speak first.\n\nUse:\n- `assistant-speaks-first` (default) to have the consent assistant play the consent message as soon as the call is answered.\n- `assistant-waits-for-user` to have the consent assistant wait for the caller to speak before playing the consent message.\n\nWe strongly recommend `assistant-waits-for-user` for outbound calls. Some telephony providers signal \"answered\" while the line is still ringing, which can cause the consent message to play into a ringing line and be missed by the caller. Waiting for the caller to speak first guarantees they hear the full consent message.\n\nNote: when combined with `type: 'stay-on-line'`, silence only counts toward consent after the caller has spoken at least once.\n\n@default 'assistant-speaks-first'", + "enum": [ + "assistant-speaks-first", + "assistant-waits-for-user" + ], + "default": "assistant-speaks-first", + "example": "assistant-speaks-first" }, - "clientX509CertUrl": { + "type": { "type": "string", - "description": "This is the URL of the public x509 certificate for the client." + "description": "This is the type of recording consent plan. This type assumes consent is granted if the user stays on the line.", + "enum": [ + "stay-on-line" + ], + "example": "stay-on-line" }, - "universeDomain": { - "type": "string", - "description": "This is the domain associated with the universe this service account belongs to." + "waitSeconds": { + "type": "number", + "description": "Number of seconds to wait before transferring to the assistant if user stays on the call", + "minimum": 1, + "maximum": 6, + "default": 3, + "example": 3 } }, "required": [ - "type", - "projectId", - "privateKeyId", - "privateKey", - "clientEmail", - "clientId", - "authUri", - "tokenUri", - "authProviderX509CertUrl", - "clientX509CertUrl", - "universeDomain" + "message", + "type" ] }, - "BucketPlan": { + "RecordingConsentPlanVerbal": { "type": "object", "properties": { - "name": { + "message": { "type": "string", - "description": "This is the name of the bucket." - }, - "region": { - "type": "string", - "description": "This is the region of the bucket.\n\nUsage:\n- If `credential.type` is `aws`, then this is required.\n- If `credential.type` is `gcp`, then this is optional since GCP allows buckets to be accessed without a region but region is required for data residency requirements. Read here: https://cloud.google.com/storage/docs/request-endpoints\n\nThis overrides the `credential.region` field if it is provided." + "description": "This is the message asking for consent to record the call.\nIf the type is `stay-on-line`, the message should ask the user to hang up if they do not consent.\nIf the type is `verbal`, the message should ask the user to verbally consent or decline.", + "maxLength": 1000, + "examples": [ + "For quality purposes, this call may be recorded. Please stay on the line if you agree or end the call if you do not consent.", + "This call may be recorded for quality and training purposes. Say \"I agree\" if you consent to being recorded, or \"I disagree\" if you do not consent." + ] }, - "path": { + "voice": { + "description": "This is the voice to use for the consent message. If not specified, inherits from the assistant's voice.\nUse a different voice for the consent message for a better user experience.", + "oneOf": [ + { + "$ref": "#/components/schemas/AzureVoice", + "title": "AzureVoice" + }, + { + "$ref": "#/components/schemas/CartesiaVoice", + "title": "CartesiaVoice" + }, + { + "$ref": "#/components/schemas/CustomVoice", + "title": "CustomVoice" + }, + { + "$ref": "#/components/schemas/DeepgramVoice", + "title": "DeepgramVoice" + }, + { + "$ref": "#/components/schemas/ElevenLabsVoice", + "title": "ElevenLabsVoice" + }, + { + "$ref": "#/components/schemas/HumeVoice", + "title": "HumeVoice" + }, + { + "$ref": "#/components/schemas/LMNTVoice", + "title": "LMNTVoice" + }, + { + "$ref": "#/components/schemas/NeuphonicVoice", + "title": "NeuphonicVoice" + }, + { + "$ref": "#/components/schemas/OpenAIVoice", + "title": "OpenAIVoice" + }, + { + "$ref": "#/components/schemas/PlayHTVoice", + "title": "PlayHTVoice" + }, + { + "$ref": "#/components/schemas/WellSaidVoice", + "title": "WellSaidVoice" + }, + { + "$ref": "#/components/schemas/RimeAIVoice", + "title": "RimeAIVoice" + }, + { + "$ref": "#/components/schemas/SmallestAIVoice", + "title": "SmallestAIVoice" + }, + { + "$ref": "#/components/schemas/TavusVoice", + "title": "TavusVoice" + }, + { + "$ref": "#/components/schemas/VapiVoice", + "title": "VapiVoice" + }, + { + "$ref": "#/components/schemas/SesameVoice", + "title": "SesameVoice" + }, + { + "$ref": "#/components/schemas/InworldVoice", + "title": "InworldVoice" + }, + { + "$ref": "#/components/schemas/MinimaxVoice", + "title": "MinimaxVoice" + }, + { + "$ref": "#/components/schemas/XaiVoice", + "title": "XaiVoice" + }, + { + "$ref": "#/components/schemas/MicrosoftVoice", + "title": "MicrosoftVoice" + } + ] + }, + "firstMessageMode": { "type": "string", - "description": "This is the path where call artifacts will be stored.\n\nUsage:\n- To store call artifacts in a specific folder, set this to the full path. Eg. \"/folder-name1/folder-name2\".\n- To store call artifacts in the root of the bucket, leave this blank.\n\n@default \"/\"" + "description": "This controls whether the consent assistant speaks first or waits for the caller to speak first.\n\nUse:\n- `assistant-speaks-first` (default) to have the consent assistant play the consent message as soon as the call is answered.\n- `assistant-waits-for-user` to have the consent assistant wait for the caller to speak before playing the consent message.\n\nWe strongly recommend `assistant-waits-for-user` for outbound calls. Some telephony providers signal \"answered\" while the line is still ringing, which can cause the consent message to play into a ringing line and be missed by the caller. Waiting for the caller to speak first guarantees they hear the full consent message.\n\nNote: when combined with `type: 'stay-on-line'`, silence only counts toward consent after the caller has spoken at least once.\n\n@default 'assistant-speaks-first'", + "enum": [ + "assistant-speaks-first", + "assistant-waits-for-user" + ], + "default": "assistant-speaks-first", + "example": "assistant-speaks-first" }, - "hmacAccessKey": { + "type": { "type": "string", - "description": "This is the HMAC access key offered by GCP for interoperability with S3 clients. Here is the guide on how to create: https://cloud.google.com/storage/docs/authentication/managing-hmackeys#console\n\nUsage:\n- If `credential.type` is `gcp`, then this is required.\n- If `credential.type` is `aws`, then this is not required since credential.awsAccessKeyId is used instead." + "description": "This is the type of recording consent plan. This type assumes consent is granted if the user verbally consents or declines.", + "enum": [ + "verbal" + ], + "example": "verbal" }, - "hmacSecret": { + "declineTool": { + "type": "object", + "description": "Tool to execute if user verbally declines recording consent" + }, + "declineToolId": { "type": "string", - "description": "This is the secret for the HMAC access key. Here is the guide on how to create: https://cloud.google.com/storage/docs/authentication/managing-hmackeys#console\n\nUsage:\n- If `credential.type` is `gcp`, then this is required.\n- If `credential.type` is `aws`, then this is not required since credential.awsSecretAccessKey is used instead.\n\nNote: This is not returned in the API." + "description": "ID of existing tool to execute if user verbally declines recording consent" } }, "required": [ - "name" + "message", + "type" ] }, - "CreateGcpCredentialDTO": { + "SecurityFilterBase": { + "type": "object", + "properties": {} + }, + "SecurityFilterPlan": { "type": "object", "properties": { - "provider": { + "enabled": { + "type": "boolean", + "description": "Whether the security filter is enabled.\n@default false", + "default": false + }, + "filters": { + "description": "Array of security filter types to apply.\nIf array is not empty, only those security filters are run.", + "example": "[{ type: \"sql-injection\" }, { type: \"xss\" }]", + "type": "array", + "items": { + "$ref": "#/components/schemas/SecurityFilterBase" + } + }, + "mode": { "type": "string", + "description": "Mode of operation when a security threat is detected.\n- 'sanitize': Remove or replace the threatening content\n- 'reject': Replace the entire transcript with replacement text\n- 'replace': Replace threatening patterns with replacement text\n@default 'sanitize'", "enum": [ - "gcp" - ] + "sanitize", + "reject", + "replace" + ], + "default": "sanitize" }, - "fallbackIndex": { - "type": "number", - "description": "This is the order in which this storage provider is tried during upload retries. Lower numbers are tried first in increasing order.", - "minimum": 1 + "replacementText": { + "type": "string", + "description": "Text to use when replacing filtered content.\n@default '[FILTERED]'", + "default": "[FILTERED]" + } + } + }, + "CompliancePlan": { + "type": "object", + "properties": { + "hipaaEnabled": { + "type": "boolean", + "description": "When this is enabled, logs, recordings, and transcriptions will be stored in HIPAA-compliant storage. Defaults to false. Only HIPAA-compliant providers will be available for LLM, Voice, and Transcriber respectively. This setting is only honored if the organization is on an Enterprise subscription or has purchased the HIPAA add-on." }, - "gcpKey": { - "description": "This is the GCP key. This is the JSON that can be generated in the Google Cloud Console at https://console.cloud.google.com/iam-admin/serviceaccounts/details//keys.\n\nThe schema is identical to the JSON that GCP outputs.", + "pciEnabled": { + "type": "boolean", + "description": "When this is enabled, the user will be restricted to use PCI-compliant providers, and no logs or transcripts are stored.\nAt the end of the call, you will receive an end-of-call-report message to store on your server. Defaults to false.", + "example": { + "pciEnabled": false + } + }, + "securityFilterPlan": { + "description": "This is the security filter plan for the assistant. It allows filtering of transcripts for security threats before sending to LLM.", "allOf": [ { - "$ref": "#/components/schemas/GcpKey" + "$ref": "#/components/schemas/SecurityFilterPlan" } ] }, - "region": { - "type": "string", - "description": "This is the region of the GCP resource.", - "maxLength": 40 - }, - "bucketPlan": { - "$ref": "#/components/schemas/BucketPlan" - }, - "name": { - "type": "string", - "description": "This is the name of credential. This is just for your reference.", - "minLength": 1, - "maxLength": 40 + "recordingConsentPlan": { + "oneOf": [ + { + "$ref": "#/components/schemas/RecordingConsentPlanStayOnLine", + "title": "RecordingConsentStayOnLinePlan" + }, + { + "$ref": "#/components/schemas/RecordingConsentPlanVerbal", + "title": "RecordingConsentPlanVerbal" + } + ], + "discriminator": { + "propertyName": "type", + "mapping": { + "stay-on-line": "#/components/schemas/RecordingConsentPlanStayOnLine", + "verbal": "#/components/schemas/RecordingConsentPlanVerbal" + } + } } - }, - "required": [ - "provider", - "gcpKey" - ] + } }, - "CreateGladiaCredentialDTO": { + "StructuredDataPlan": { "type": "object", "properties": { - "provider": { - "type": "string", - "enum": [ - "gladia" - ] + "messages": { + "description": "These are the messages used to generate the structured data.\n\n@default: ```\n[\n {\n \"role\": \"system\",\n \"content\": \"You are an expert data extractor. You will be given a transcript of a call. Extract structured data per the JSON Schema. DO NOT return anything except the structured data.\\n\\nJson Schema:\\\\n{{schema}}\\n\\nOnly respond with the JSON.\"\n },\n {\n \"role\": \"user\",\n \"content\": \"Here is the transcript:\\n\\n{{transcript}}\\n\\n. Here is the ended reason of the call:\\n\\n{{endedReason}}\\n\\n\"\n }\n]```\n\nYou can customize by providing any messages you want.\n\nHere are the template variables available:\n- {{transcript}}: the transcript of the call from `call.artifact.transcript`- {{systemPrompt}}: the system prompt of the call from `assistant.model.messages[type=system].content`- {{messages}}: the messages of the call from `assistant.model.messages`- {{schema}}: the schema of the structured data from `structuredDataPlan.schema`- {{endedReason}}: the ended reason of the call from `call.endedReason`", + "type": "array", + "items": { + "type": "object" + } }, - "apiKey": { - "type": "string", - "description": "This is not returned in the API." + "enabled": { + "type": "boolean", + "description": "This determines whether structured data is generated and stored in `call.analysis.structuredData`. Defaults to false.\n\nUsage:\n- If you want to extract structured data, set this to true and provide a `schema`.\n\n@default false" }, - "name": { - "type": "string", - "description": "This is the name of credential. This is just for your reference.", - "minLength": 1, - "maxLength": 40 + "schema": { + "description": "This is the schema of the structured data. The output is stored in `call.analysis.structuredData`.\n\nComplete guide on JSON Schema can be found [here](https://ajv.js.org/json-schema.html#json-data-type).", + "allOf": [ + { + "$ref": "#/components/schemas/JsonSchema" + } + ] + }, + "timeoutSeconds": { + "type": "number", + "description": "This is how long the request is tried before giving up. When request times out, `call.analysis.structuredData` will be empty.\n\nUsage:\n- To guarantee the structured data is generated, set this value high. Note, this will delay the end of call report in cases where model is slow to respond.\n\n@default 5 seconds", + "minimum": 1, + "maximum": 60 } - }, - "required": [ - "provider", - "apiKey" - ] + } }, - "CreateGoHighLevelCredentialDTO": { + "StructuredDataMultiPlan": { "type": "object", "properties": { - "provider": { - "type": "string", - "enum": [ - "gohighlevel" - ] - }, - "apiKey": { + "key": { "type": "string", - "description": "This is not returned in the API." + "description": "This is the key of the structured data plan in the catalog." }, - "name": { - "type": "string", - "description": "This is the name of credential. This is just for your reference.", - "minLength": 1, - "maxLength": 40 + "plan": { + "description": "This is an individual structured data plan in the catalog.", + "allOf": [ + { + "$ref": "#/components/schemas/StructuredDataPlan" + } + ] } }, "required": [ - "provider", - "apiKey" + "key", + "plan" ] }, - "CreateGroqCredentialDTO": { + "SuccessEvaluationPlan": { "type": "object", "properties": { - "provider": { + "rubric": { "type": "string", "enum": [ - "groq" - ] + "NumericScale", + "DescriptiveScale", + "Checklist", + "Matrix", + "PercentageScale", + "LikertScale", + "AutomaticRubric", + "PassFail" + ], + "description": "This enforces the rubric of the evaluation. The output is stored in `call.analysis.successEvaluation`.\n\nOptions include:\n- 'NumericScale': A scale of 1 to 10.\n- 'DescriptiveScale': A scale of Excellent, Good, Fair, Poor.\n- 'Checklist': A checklist of criteria and their status.\n- 'Matrix': A grid that evaluates multiple criteria across different performance levels.\n- 'PercentageScale': A scale of 0% to 100%.\n- 'LikertScale': A scale of Strongly Agree, Agree, Neutral, Disagree, Strongly Disagree.\n- 'AutomaticRubric': Automatically break down evaluation into several criteria, each with its own score.\n- 'PassFail': A simple 'true' if call passed, 'false' if not.\n\nDefault is 'PassFail'." }, - "apiKey": { - "type": "string", - "description": "This is not returned in the API." + "messages": { + "description": "These are the messages used to generate the success evaluation.\n\n@default: ```\n[\n {\n \"role\": \"system\",\n \"content\": \"You are an expert call evaluator. You will be given a transcript of a call and the system prompt of the AI participant. Determine if the call was successful based on the objectives inferred from the system prompt. DO NOT return anything except the result.\\n\\nRubric:\\\\n{{rubric}}\\n\\nOnly respond with the result.\"\n },\n {\n \"role\": \"user\",\n \"content\": \"Here is the transcript:\\n\\n{{transcript}}\\n\\n\"\n },\n {\n \"role\": \"user\",\n \"content\": \"Here was the system prompt of the call:\\n\\n{{systemPrompt}}\\n\\n. Here is the ended reason of the call:\\n\\n{{endedReason}}\\n\\n\"\n }\n]```\n\nYou can customize by providing any messages you want.\n\nHere are the template variables available:\n- {{transcript}}: the transcript of the call from `call.artifact.transcript`- {{systemPrompt}}: the system prompt of the call from `assistant.model.messages[type=system].content`- {{messages}}: the messages of the call from `assistant.model.messages`- {{rubric}}: the rubric of the success evaluation from `successEvaluationPlan.rubric`- {{endedReason}}: the ended reason of the call from `call.endedReason`", + "type": "array", + "items": { + "type": "object" + } }, - "name": { - "type": "string", - "description": "This is the name of credential. This is just for your reference.", - "minLength": 1, - "maxLength": 40 + "enabled": { + "type": "boolean", + "description": "This determines whether a success evaluation is generated and stored in `call.analysis.successEvaluation`. Defaults to true.\n\nUsage:\n- If you want to disable the success evaluation, set this to false.\n\n@default true" + }, + "timeoutSeconds": { + "type": "number", + "description": "This is how long the request is tried before giving up. When request times out, `call.analysis.successEvaluation` will be empty.\n\nUsage:\n- To guarantee the success evaluation is generated, set this value high. Note, this will delay the end of call report in cases where model is slow to respond.\n\n@default 5 seconds", + "minimum": 1, + "maximum": 60 } - }, - "required": [ - "provider", - "apiKey" - ] + } }, - "CreateLangfuseCredentialDTO": { + "AnalysisPlan": { "type": "object", "properties": { - "provider": { - "type": "string", - "enum": [ - "langfuse" + "minMessagesThreshold": { + "type": "number", + "description": "The minimum number of messages required to run the analysis plan.\nIf the number of messages is less than this, analysis will be skipped.\n\n@default 2", + "deprecated": true, + "minimum": 0 + }, + "summaryPlan": { + "description": "This is the plan for generating the summary of the call. This outputs to `call.analysis.summary`.", + "deprecated": true, + "allOf": [ + { + "$ref": "#/components/schemas/SummaryPlan" + } ] }, - "publicKey": { - "type": "string", - "description": "The public key for Langfuse project. Eg: pk-lf-..." + "structuredDataPlan": { + "description": "This is the plan for generating the structured data from the call. This outputs to `call.analysis.structuredData`.", + "deprecated": true, + "allOf": [ + { + "$ref": "#/components/schemas/StructuredDataPlan" + } + ] }, - "apiKey": { - "type": "string", - "description": "The secret key for Langfuse project. Eg: sk-lf-... .This is not returned in the API." + "structuredDataMultiPlan": { + "description": "This is an array of structured data plan catalogs. Each entry includes a `key` and a `plan` for generating the structured data from the call. This outputs to `call.analysis.structuredDataMulti`.", + "deprecated": true, + "type": "array", + "items": { + "$ref": "#/components/schemas/StructuredDataMultiPlan" + } }, - "apiUrl": { - "type": "string", - "description": "The host URL for Langfuse project. Eg: https://cloud.langfuse.com" + "successEvaluationPlan": { + "description": "This is the plan for generating the success evaluation of the call. This outputs to `call.analysis.successEvaluation`.", + "deprecated": true, + "allOf": [ + { + "$ref": "#/components/schemas/SuccessEvaluationPlan" + } + ] }, - "name": { - "type": "string", - "description": "This is the name of credential. This is just for your reference.", - "minLength": 1, - "maxLength": 40 + "outcomeIds": { + "description": "This is an array of outcome UUIDs to be calculated during analysis.\nThe outcomes will be calculated and stored in `call.analysis.outcomes`.", + "deprecated": true, + "type": "array", + "items": { + "type": "string" + } } - }, - "required": [ - "provider", - "publicKey", - "apiKey", - "apiUrl" - ] + } }, - "CreateLmntCredentialDTO": { + "TranscriptPlan": { "type": "object", "properties": { - "provider": { - "type": "string", - "enum": [ - "lmnt" - ] + "enabled": { + "type": "boolean", + "description": "This determines whether the transcript is stored in `call.artifact.transcript`. Defaults to true.\n\n@default true", + "example": true }, - "apiKey": { + "assistantName": { "type": "string", - "description": "This is not returned in the API." + "description": "This is the name of the assistant in the transcript. Defaults to 'AI'.\n\nUsage:\n- If you want to change the name of the assistant in the transcript, set this. Example, here is what the transcript would look like with `assistantName` set to 'Buyer':\n```\nUser: Hello, how are you?\nBuyer: I'm fine.\nUser: Do you want to buy a car?\nBuyer: No.\n```\n\n@default 'AI'" }, - "name": { + "userName": { "type": "string", - "description": "This is the name of credential. This is just for your reference.", - "minLength": 1, - "maxLength": 40 + "description": "This is the name of the user in the transcript. Defaults to 'User'.\n\nUsage:\n- If you want to change the name of the user in the transcript, set this. Example, here is what the transcript would look like with `userName` set to 'Seller':\n```\nSeller: Hello, how are you?\nAI: I'm fine.\nSeller: Do you want to buy a car?\nAI: No.\n```\n\n@default 'User'" } - }, - "required": [ - "provider", - "apiKey" - ] + } }, - "CreateMakeCredentialDTO": { + "MinMessagesCondition": { "type": "object", "properties": { - "provider": { + "type": { "type": "string", + "description": "This is the type discriminator for the minMessages condition.", + "example": "minMessages", "enum": [ - "make" + "minMessages" ] }, - "teamId": { - "type": "string", - "description": "Team ID" - }, - "region": { - "type": "string", - "description": "Region of your application. For example: eu1, eu2, us1, us2" - }, - "apiKey": { - "type": "string", - "description": "This is not returned in the API." - }, - "name": { - "type": "string", - "description": "This is the name of credential. This is just for your reference.", - "minLength": 1, - "maxLength": 40 + "count": { + "type": "number", + "description": "This is the minimum number of conversation messages required for the\nstructured output to run.\n\nA count of 0 removes the runtime default minimum, so the structured output\nruns regardless of how few messages the conversation has.", + "example": 4, + "minimum": 0 } }, "required": [ - "provider", - "teamId", - "region", - "apiKey" + "type", + "count" ] }, - "CreateOpenAICredentialDTO": { + "MinCallDurationCondition": { "type": "object", "properties": { - "provider": { + "type": { "type": "string", + "description": "This is the type discriminator for the minCallDuration condition.", + "example": "minCallDuration", "enum": [ - "openai" + "minCallDuration" ] }, - "apiKey": { - "type": "string", - "description": "This is not returned in the API." - }, - "name": { - "type": "string", - "description": "This is the name of credential. This is just for your reference.", - "minLength": 1, - "maxLength": 40 + "seconds": { + "type": "number", + "description": "This is the minimum call duration in seconds required for the structured\noutput to run.\n\nWhen timestamps are unavailable (for example, chat sessions have no call\ntimestamps), this check passes and does not block the structured output.", + "example": 10, + "minimum": 0 } }, "required": [ - "provider", - "apiKey" + "type", + "seconds" ] }, - "CreateOpenRouterCredentialDTO": { + "EndedReasonCondition": { "type": "object", "properties": { - "provider": { + "type": { "type": "string", + "description": "This is the type discriminator for the endedReason condition.", + "example": "endedReason", "enum": [ - "openrouter" + "endedReason" ] }, - "apiKey": { + "operator": { "type": "string", - "description": "This is not returned in the API." + "description": "This is the membership operator applied against `values`.\n\n- 'oneOf': the structured output runs only if the call's ended reason is in `values`.\n- 'notOneOf': the structured output runs only if the call's ended reason is NOT in `values`.", + "example": "oneOf", + "enum": [ + "oneOf", + "notOneOf" + ] }, - "name": { - "type": "string", - "description": "This is the name of credential. This is just for your reference.", - "minLength": 1, - "maxLength": 40 + "values": { + "description": "These are the ended reasons compared against the call's ended reason.\n\nAny string is accepted so configurations never break when new ended\nreasons are introduced. Must contain at least one value.", + "example": [ + "customer-ended-call" + ], + "type": "array", + "items": { + "type": "string" + } } }, "required": [ - "provider", - "apiKey" + "type", + "operator", + "values" ] }, - "CreatePerplexityAICredentialDTO": { + "ComplianceOverride": { "type": "object", "properties": { - "provider": { - "type": "string", - "enum": [ - "perplexity-ai" - ] - }, - "apiKey": { - "type": "string", - "description": "This is not returned in the API." - }, - "name": { - "type": "string", - "description": "This is the name of credential. This is just for your reference.", - "minLength": 1, - "maxLength": 40 + "forceStoreOnHipaaEnabled": { + "type": "boolean", + "description": "Force storage for this output under HIPAA. Only enable if output contains no sensitive data.", + "example": false } - }, - "required": [ - "provider", - "apiKey" - ] + } }, - "CreatePlayHTCredentialDTO": { + "CreateStructuredOutputDTO": { "type": "object", "properties": { - "provider": { + "type": { "type": "string", + "description": "This is the type of structured output.\n\n- 'ai': Uses an LLM to extract structured data from the conversation (default).\n- 'regex': Uses a regex pattern to extract data from the transcript without an LLM.\n\nDefaults to 'ai' if not specified.", "enum": [ - "playht" - ] + "ai", + "regex" + ], + "default": "ai" }, - "apiKey": { + "regex": { "type": "string", - "description": "This is not returned in the API." + "description": "This is the regex pattern to match against the transcript.\n\nOnly used when type is 'regex'. Supports both raw patterns (e.g. '\\d+') and\nregex literal format (e.g. '/\\d+/gi'). Uses RE2 syntax for safety.\n\nThe result depends on the schema type:\n- boolean: true if the pattern matches, false otherwise\n- string: the first match or first capture group\n- number/integer: the first match parsed as a number\n- array: all matches", + "minLength": 1, + "maxLength": 1000 }, - "userId": { - "type": "string" - }, - "name": { - "type": "string", - "description": "This is the name of credential. This is just for your reference.", - "minLength": 1, - "maxLength": 40 - } - }, - "required": [ - "provider", - "apiKey", - "userId" - ] - }, - "CreateRimeAICredentialDTO": { - "type": "object", - "properties": { - "provider": { - "type": "string", - "enum": [ - "rime-ai" + "model": { + "description": "This is the model that will be used to extract the structured output.\n\nTo provide your own custom system and user prompts for structured output extraction, populate the messages array with your system and user messages. You can specify liquid templating in your system and user messages.\nBetween the system or user messages, you must reference either 'transcript' or 'messages' with the `{{}}` syntax to access the conversation history.\nBetween the system or user messages, you must reference a variation of the structured output with the `{{}}` syntax to access the structured output definition.\ni.e.:\n`{{structuredOutput}}`\n`{{structuredOutput.name}}`\n`{{structuredOutput.description}}`\n`{{structuredOutput.schema}}`\n\nIf model is not specified, GPT-4.1 will be used by default for extraction, utilizing default system and user prompts.\nIf messages or required fields are not specified, the default system and user prompts will be used.", + "oneOf": [ + { + "$ref": "#/components/schemas/WorkflowOpenAIModel", + "title": "WorkflowOpenAIModel" + }, + { + "$ref": "#/components/schemas/WorkflowAnthropicModel", + "title": "WorkflowAnthropicModel" + }, + { + "$ref": "#/components/schemas/WorkflowAnthropicBedrockModel", + "title": "WorkflowAnthropicBedrockModel" + }, + { + "$ref": "#/components/schemas/WorkflowGoogleModel", + "title": "WorkflowGoogleModel" + }, + { + "$ref": "#/components/schemas/WorkflowCustomModel", + "title": "WorkflowCustomModel" + } ] }, - "apiKey": { - "type": "string", - "description": "This is not returned in the API." - }, - "name": { - "type": "string", - "description": "This is the name of credential. This is just for your reference.", - "minLength": 1, - "maxLength": 40 - } - }, - "required": [ - "provider", - "apiKey" - ] - }, - "CreateRunpodCredentialDTO": { - "type": "object", - "properties": { - "provider": { - "type": "string", - "enum": [ - "runpod" + "compliancePlan": { + "description": "Compliance configuration for this output. Only enable overrides if no sensitive data will be stored.", + "example": { + "forceStoreOnHipaaEnabled": false + }, + "allOf": [ + { + "$ref": "#/components/schemas/ComplianceOverride" + } ] }, - "apiKey": { - "type": "string", - "description": "This is not returned in the API." + "conditions": { + "type": "array", + "nullable": true, + "description": "These are the conditions that gate the execution of this structured output. Every condition must pass for the structured output to run (AND semantics). When omitted or empty, no user-defined conditions gate this output. Send null to clear a previously saved gate.", + "example": [ + { + "type": "minMessages", + "count": 4 + }, + { + "type": "minCallDuration", + "seconds": 10 + } + ], + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/MinMessagesCondition", + "title": "MinMessagesCondition" + }, + { + "$ref": "#/components/schemas/MinCallDurationCondition", + "title": "MinCallDurationCondition" + }, + { + "$ref": "#/components/schemas/EndedReasonCondition", + "title": "EndedReasonCondition" + } + ] + } }, "name": { "type": "string", - "description": "This is the name of credential. This is just for your reference.", + "description": "This is the name of the structured output.", "minLength": 1, "maxLength": 40 - } - }, - "required": [ - "provider", - "apiKey" - ] - }, - "CreateS3CredentialDTO": { - "type": "object", - "properties": { - "provider": { - "type": "string", - "enum": [ - "s3" - ], - "description": "Credential provider. Only allowed value is s3" - }, - "awsAccessKeyId": { - "type": "string", - "description": "AWS access key ID." - }, - "awsSecretAccessKey": { - "type": "string", - "description": "AWS access key secret. This is not returned in the API." - }, - "region": { - "type": "string", - "description": "AWS region in which the S3 bucket is located." }, - "s3BucketName": { - "type": "string", - "description": "AWS S3 bucket name." + "schema": { + "description": "This is the JSON Schema definition for the structured output.\n\nThis is required when creating a structured output. Defines the structure and validation rules for the data that will be extracted. Supports all JSON Schema features including:\n- Objects and nested properties\n- Arrays and array validation\n- String, number, boolean, and null types\n- Enums and const values\n- Validation constraints (min/max, patterns, etc.)\n- Composition with allOf, anyOf, oneOf", + "allOf": [ + { + "$ref": "#/components/schemas/JsonSchema" + } + ] }, - "s3PathPrefix": { + "description": { "type": "string", - "description": "The path prefix for the uploaded recording. Ex. \"recordings/\"" + "description": "This is the description of what the structured output extracts.\n\nUse this to provide context about what data will be extracted and how it will be used." }, - "fallbackIndex": { - "type": "number", - "minimum": 1, - "description": "This is the order in which this storage provider is tried during upload retries. Lower numbers are tried first in increasing order." + "assistantIds": { + "description": "These are the assistant IDs that this structured output is linked to.\n\nWhen linked to assistants, this structured output will be available for extraction during those assistant's calls.", + "type": "array", + "items": { + "type": "string" + } }, - "name": { - "type": "string", - "description": "This is the name of credential. This is just for your reference.", - "minLength": 1, - "maxLength": 40 + "workflowIds": { + "description": "These are the workflow IDs that this structured output is linked to.\n\nWhen linked to workflows, this structured output will be available for extraction during those workflow's execution.", + "type": "array", + "items": { + "type": "string" + } } }, "required": [ - "provider", - "awsAccessKeyId", - "awsSecretAccessKey", - "region", - "s3BucketName", - "s3PathPrefix" + "name", + "schema" ] }, - "SupabaseBucketPlan": { + "NumberComparatorScorecardMetricCondition": { "type": "object", "properties": { - "region": { + "type": { "type": "string", - "description": "This is the S3 Region. It should look like us-east-1\nIt should be one of the supabase regions defined in the SUPABASE_REGION enum\nCheck https://supabase.com/docs/guides/platform/regions for up to date regions", + "description": "This is the type of the condition. Currently only 'comparator' is supported.", "enum": [ - "us-west-1", - "us-east-1", - "us-east-2", - "ca-central-1", - "eu-west-1", - "eu-west-2", - "eu-west-3", - "eu-central-1", - "eu-central-2", - "eu-north-1", - "ap-south-1", - "ap-southeast-1", - "ap-northeast-1", - "ap-northeast-2", - "ap-southeast-2", - "sa-east-1" + "comparator" ] }, - "url": { - "type": "string", - "description": "This is the S3 compatible URL for Supabase S3\nThis should look like https://.supabase.co/storage/v1/s3" - }, - "accessKeyId": { - "type": "string", - "description": "This is the Supabase S3 Access Key ID.\nThe user creates this in the Supabase project Storage settings" - }, - "secretAccessKey": { - "type": "string", - "description": "This is the Supabase S3 Secret Access Key.\nThe user creates this in the Supabase project Storage settings along with the access key id" - }, - "name": { - "type": "string", - "description": "This is the Supabase S3 Bucket Name.\nThe user must create this in Supabase under Storage > Buckets\nA bucket that does not exist will not be checked now, but file uploads will fail" - }, - "path": { - "type": "string", - "description": "This is the Supabase S3 Bucket Folder Path.\nThe user can create this in Supabase under Storage > Buckets\nA path that does not exist will not be checked now, but file uploads will fail\nA Path is like a folder in the bucket\nEg. If the bucket is called \"my-bucket\" and the path is \"my-folder\", the full path is \"my-bucket/my-folder\"" - } - }, - "required": [ - "region", - "url", - "accessKeyId", - "secretAccessKey", - "name" - ] - }, - "CreateSupabaseCredentialDTO": { - "type": "object", - "properties": { - "provider": { + "comparator": { "type": "string", + "description": "This is the comparator that will be used to compare the result of the structured output with the value specified.\nOnly '=', '!=', '>', '<', '>=', and '<=' are supported for number conditions\nOnly '=' is supported for boolean conditions.", "enum": [ - "supabase" - ], - "description": "This is for supabase storage." + "=", + "!=", + ">", + "<", + ">=", + "<=" + ] }, - "fallbackIndex": { + "value": { "type": "number", - "minimum": 1, - "description": "This is the order in which this storage provider is tried during upload retries. Lower numbers are tried first in increasing order." - }, - "bucketPlan": { - "$ref": "#/components/schemas/SupabaseBucketPlan" + "description": "This is the value that will be used to compare the result of the structured output with the comparator.\nIf the result of the comparison is true, the points will be added to the overall score." }, - "name": { - "type": "string", - "description": "This is the name of credential. This is just for your reference.", - "minLength": 1, - "maxLength": 40 + "points": { + "type": "number", + "description": "These are the points that will be added to the overall score if the condition is met.\nThe points must be between 0 and 100.", + "minimum": 0, + "maximum": 100 } }, "required": [ - "provider" + "type", + "comparator", + "value", + "points" ] }, - "CreateSmallestAICredentialDTO": { + "BooleanComparatorScorecardMetricCondition": { "type": "object", "properties": { - "provider": { + "type": { "type": "string", + "description": "This is the type of the condition. Currently only 'comparator' is supported.", "enum": [ - "smallest-ai" + "comparator" ] }, - "apiKey": { + "comparator": { "type": "string", - "description": "This is not returned in the API." + "description": "The comparator can only be '=' for boolean conditions.", + "enum": [ + "=" + ] }, - "name": { - "type": "string", - "description": "This is the name of credential. This is just for your reference.", - "minLength": 1, - "maxLength": 40 + "value": { + "type": "boolean", + "description": "This is the value that will be used to compare the result of the structured output with the comparator.\nIf the result of the comparison is true, the points will be added to the overall score." + }, + "points": { + "type": "number", + "description": "These are the points that will be added to the overall score if the condition is met.\nThe points must be between 0 and 100.", + "minimum": 0, + "maximum": 100 } }, "required": [ - "provider", - "apiKey" + "type", + "comparator", + "value", + "points" ] }, - "CreateTavusCredentialDTO": { + "ScorecardMetric": { "type": "object", "properties": { - "provider": { - "type": "string", - "enum": [ - "tavus" - ] - }, - "apiKey": { - "type": "string", - "description": "This is not returned in the API." + "conditions": { + "type": "array", + "description": "These are the conditions that will be used to evaluate the scorecard.\nEach condition will have a comparator, value, and points that will be used to calculate the final score.\nThe points will be added to the overall score if the condition is met.\nThe overall score will be normalized to a 100 point scale to ensure uniformity across different scorecards.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/NumberComparatorScorecardMetricCondition", + "title": "NumberComparatorScorecardMetricCondition" + }, + { + "$ref": "#/components/schemas/BooleanComparatorScorecardMetricCondition", + "title": "BooleanComparatorScorecardMetricCondition" + } + ] + } }, - "name": { + "structuredOutputId": { "type": "string", - "description": "This is the name of credential. This is just for your reference.", - "minLength": 1, - "maxLength": 40 + "description": "This is the unique identifier for the structured output that will be used to evaluate the scorecard.\nThe structured output must be of type number or boolean only for now." } }, "required": [ - "provider", - "apiKey" + "conditions", + "structuredOutputId" ] }, - "CreateTogetherAICredentialDTO": { + "CreateScorecardDTO": { "type": "object", "properties": { - "provider": { + "name": { "type": "string", - "enum": [ - "together-ai" - ] + "description": "This is the name of the scorecard. It is only for user reference and will not be used for any evaluation.", + "maxLength": 80 }, - "apiKey": { + "description": { "type": "string", - "description": "This is not returned in the API." + "description": "This is the description of the scorecard. It is only for user reference and will not be used for any evaluation.", + "maxLength": 500 }, - "name": { - "type": "string", - "description": "This is the name of credential. This is just for your reference.", - "minLength": 1, - "maxLength": 40 + "metrics": { + "description": "These are the metrics that will be used to evaluate the scorecard.\nEach metric will have a set of conditions and points that will be used to generate the score.", + "type": "array", + "items": { + "$ref": "#/components/schemas/ScorecardMetric" + } + }, + "assistantIds": { + "description": "These are the assistant IDs that this scorecard is linked to.\nWhen linked to assistants, this scorecard will be available for evaluation during those assistants' calls.", + "type": "array", + "items": { + "type": "string" + } } }, "required": [ - "provider", - "apiKey" + "metrics" ] }, - "CreateTwilioCredentialDTO": { + "ArtifactPlan": { "type": "object", "properties": { - "provider": { + "recordingEnabled": { + "type": "boolean", + "description": "This determines whether assistant's calls are recorded. Defaults to true.\n\nUsage:\n- If you don't want to record the calls, set this to false.\n- If you want to record the calls when `assistant.hipaaEnabled` (deprecated) or `assistant.compliancePlan.hipaaEnabled` explicity set this to true and make sure to provide S3 or GCP credentials on the Provider Credentials page in the Dashboard.\n\nYou can find the recording at `call.artifact.recordingUrl` and `call.artifact.stereoRecordingUrl` after the call is ended.\n\n@default true", + "example": true + }, + "recordingFormat": { "type": "string", + "description": "This determines the format of the recording. Defaults to `wav;l16`.\n\n@default 'wav;l16'", "enum": [ - "twilio" + "wav;l16", + "mp3" ] }, - "authToken": { - "type": "string", - "description": "This is not returned in the API." + "recordingUseCustomStorageEnabled": { + "type": "boolean", + "description": "This determines whether to use custom storage (S3 or GCP) for call recordings when storage credentials are configured.\n\nWhen set to false, recordings will be stored on Vapi's storage instead of your custom storage, even if you have custom storage credentials configured.\n\nUsage:\n- Set to false if you have custom storage configured but want to store recordings on Vapi's storage for this assistant.\n- Set to true (or leave unset) to use your custom storage for recordings when available.\n\nIf your organization has ZDR (zero data retention) or PCI enabled, recordings are never written to Vapi storage. In that case, false means \"do not use my custom storage\", so nothing is stored at all.\n\n@default true", + "example": true }, - "apiKey": { - "type": "string", - "description": "This is not returned in the API." + "videoRecordingEnabled": { + "type": "boolean", + "description": "This determines whether the video is recorded during the call. Defaults to false. Only relevant for `webCall` type.\n\nYou can find the video recording at `call.artifact.videoRecordingUrl` after the call is ended.\n\n@default false", + "example": false }, - "apiSecret": { - "type": "string", - "description": "This is not returned in the API." + "fullMessageHistoryEnabled": { + "type": "boolean", + "description": "This determines whether the artifact contains the full message history, even after handoff context engineering. Defaults to false.", + "example": false }, - "accountSid": { - "type": "string" + "pcapEnabled": { + "type": "boolean", + "description": "This determines whether the SIP packet capture is enabled. Defaults to true. Only relevant for `phone` type calls where phone number's provider is `vapi` or `byo-phone-number`.\n\nYou can find the packet capture at `call.artifact.pcapUrl` after the call is ended.\n\n@default true", + "example": true }, - "name": { - "type": "string", - "description": "This is the name of credential. This is just for your reference.", - "minLength": 1, - "maxLength": 40 - } - }, - "required": [ - "provider", - "accountSid" - ] - }, - "CreateVonageCredentialDTO": { - "type": "object", - "properties": { - "provider": { + "pcapS3PathPrefix": { "type": "string", - "enum": [ - "vonage" - ] + "description": "This is the path where the SIP packet capture will be uploaded. This is only used if you have provided S3 or GCP credentials on the Provider Credentials page in the Dashboard.\n\nIf credential.s3PathPrefix or credential.bucketPlan.path is set, this will append to it.\n\nUsage:\n- If you want to upload the packet capture to a specific path, set this to the path. Example: `/my-assistant-captures`.\n- If you want to upload the packet capture to the root of the bucket, set this to `/`.\n\n@default '/'", + "example": "/pcaps" }, - "apiSecret": { - "type": "string", - "description": "This is not returned in the API." + "pcapUseCustomStorageEnabled": { + "type": "boolean", + "description": "This determines whether to use custom storage (S3 or GCP) for SIP packet captures when storage credentials are configured.\n\nWhen set to false, packet captures will be stored on Vapi's storage instead of your custom storage, even if you have custom storage credentials configured.\n\nUsage:\n- Set to false if you have custom storage configured but want to store packet captures on Vapi's storage for this assistant.\n- Set to true (or leave unset) to use your custom storage for packet captures when available.\n\nIf your organization has ZDR (zero data retention) or PCI enabled, packet captures are never written to Vapi storage. In that case, false means \"do not use my custom storage\", so nothing is stored at all.\n\n@default true", + "example": true }, - "apiKey": { - "type": "string" + "loggingEnabled": { + "type": "boolean", + "description": "This determines whether the call logs are enabled. Defaults to true.\n\n@default true", + "example": true }, - "name": { - "type": "string", - "description": "This is the name of credential. This is just for your reference.", - "minLength": 1, - "maxLength": 40 - } - }, - "required": [ - "provider", - "apiSecret", - "apiKey" - ] - }, - "CreateWebhookCredentialDTO": { - "type": "object", - "properties": { - "provider": { - "type": "string", - "enum": [ - "webhook" - ] + "loggingUseCustomStorageEnabled": { + "type": "boolean", + "description": "This determines whether to use custom storage (S3 or GCP) for call logs when storage credentials are configured.\n\nWhen set to false, logs will be stored on Vapi's storage instead of your custom storage, even if you have custom storage credentials configured.\n\nUsage:\n- Set to false if you have custom storage configured but want to store logs on Vapi's storage for this assistant.\n- Set to true (or leave unset) to use your custom storage for logs when available.\n\nIf your organization has ZDR (zero data retention) or PCI enabled, logs are never written to Vapi storage. In that case, false means \"do not use my custom storage\", so nothing is stored at all.\n\n@default true", + "example": true }, - "authenticationPlan": { - "description": "This is the authentication plan. Supports OAuth2 RFC 6749 and HMAC signing.", - "oneOf": [ - { - "$ref": "#/components/schemas/OAuth2AuthenticationPlan" - }, + "transcriptPlan": { + "description": "This is the plan for `call.artifact.transcript`. To disable, set `transcriptPlan.enabled` to false.", + "allOf": [ { - "$ref": "#/components/schemas/HMACAuthenticationPlan" - } - ], - "discriminator": { - "propertyName": "type", - "mapping": { - "oauth2": "#/components/schemas/OAuth2AuthenticationPlan", - "hmac": "#/components/schemas/HMACAuthenticationPlan" + "$ref": "#/components/schemas/TranscriptPlan" } - } - }, - "name": { - "type": "string", - "description": "This is the name of credential. This is just for your reference.", - "minLength": 1, - "maxLength": 40 - } - }, - "required": [ - "provider", - "authenticationPlan" - ] - }, - "CreateXAiCredentialDTO": { - "type": "object", - "properties": { - "provider": { - "type": "string", - "description": "This is the api key for Grok in XAi's console. Get it from here: https://console.x.ai", - "enum": [ - "xai" ] }, - "apiKey": { + "recordingPath": { "type": "string", - "maxLength": 10000, - "description": "This is not returned in the API." + "description": "This is the path where the recording will be uploaded. This is only used if you have provided S3 or GCP credentials on the Provider Credentials page in the Dashboard.\n\nIf credential.s3PathPrefix or credential.bucketPlan.path is set, this will append to it.\n\nUsage:\n- If you want to upload the recording to a specific path, set this to the path. Example: `/my-assistant-recordings`.\n- If you want to upload the recording to the root of the bucket, set this to `/`.\n\n@default '/'" }, - "name": { - "type": "string", - "description": "This is the name of credential. This is just for your reference.", - "minLength": 1, - "maxLength": 40 - } - }, - "required": [ - "provider", - "apiKey" - ] - }, - "CreateGoogleCalendarOAuth2ClientCredentialDTO": { - "type": "object", - "properties": { - "provider": { - "type": "string", - "enum": [ - "google.calendar.oauth2-client" - ] + "structuredOutputIds": { + "description": "This is an array of structured output IDs to be calculated during the call.\nThe outputs will be extracted and stored in `call.artifact.structuredOutputs` after the call is ended.", + "type": "array", + "items": { + "type": "string" + } }, - "name": { + "structuredOutputs": { + "description": "This is an array of transient structured outputs to be calculated during the call.\nThe outputs will be extracted and stored in `call.artifact.structuredOutputs` after the call is ended.\nUse this to provide inline structured output configurations instead of referencing existing ones via structuredOutputIds.", + "type": "array", + "items": { + "$ref": "#/components/schemas/CreateStructuredOutputDTO" + } + }, + "scorecardIds": { + "description": "This is an array of scorecard IDs that will be evaluated based on the structured outputs extracted during the call.\nThe scorecards will be evaluated and the results will be stored in `call.artifact.scorecards` after the call has ended.", + "type": "array", + "items": { + "type": "string" + } + }, + "scorecards": { + "description": "This is the array of scorecards that will be evaluated based on the structured outputs extracted during the call.\nThe scorecards will be evaluated and the results will be stored in `call.artifact.scorecards` after the call has ended.", + "type": "array", + "items": { + "$ref": "#/components/schemas/CreateScorecardDTO" + } + }, + "loggingPath": { "type": "string", - "description": "This is the name of credential. This is just for your reference.", - "minLength": 1, - "maxLength": 40 + "description": "This is the path where the call logs will be uploaded. This is only used if you have provided S3 or GCP credentials on the Provider Credentials page in the Dashboard.\n\nIf credential.s3PathPrefix or credential.bucketPlan.path is set, this will append to it.\n\nUsage:\n- If you want to upload the call logs to a specific path, set this to the path. Example: `/my-assistant-logs`.\n- If you want to upload the call logs to the root of the bucket, set this to `/`.\n\n@default '/'" } - }, - "required": [ - "provider" - ] + } }, - "CreateGoogleCalendarOAuth2AuthorizationCredentialDTO": { + "StopSpeakingPlan": { "type": "object", "properties": { - "provider": { - "type": "string", - "enum": [ - "google.calendar.oauth2-authorization" - ] + "numWords": { + "type": "number", + "description": "This is the number of words that the customer has to say before the assistant will stop talking.\n\nWords like \"stop\", \"actually\", \"no\", etc. will always interrupt immediately regardless of this value.\n\nWords like \"okay\", \"yeah\", \"right\" will never interrupt.\n\nWhen set to 0, `voiceSeconds` is used in addition to the transcriptions to determine the customer has started speaking.\n\nDefaults to 0.\n\n@default 0", + "minimum": 0, + "maximum": 10, + "example": 0 }, - "authorizationId": { - "type": "string", - "description": "The authorization ID for the OAuth2 authorization" + "voiceSeconds": { + "type": "number", + "description": "This is the seconds customer has to speak before the assistant stops talking. This uses the VAD (Voice Activity Detection) spike to determine if the customer has started speaking.\n\nConsiderations:\n- A lower value might be more responsive but could potentially pick up non-speech sounds.\n- A higher value reduces false positives but might slightly delay the detection of speech onset.\n\nThis is only used if `numWords` is set to 0.\n\nDefaults to 0.2\n\n@default 0.2", + "minimum": 0, + "maximum": 0.5, + "example": 0.2 }, - "name": { - "type": "string", - "description": "This is the name of credential. This is just for your reference.", - "minLength": 1, - "maxLength": 40 - } - }, - "required": [ - "provider", - "authorizationId" - ] - }, - "CreateGoogleSheetsOAuth2AuthorizationCredentialDTO": { - "type": "object", - "properties": { - "provider": { - "type": "string", - "enum": [ - "google.sheets.oauth2-authorization" - ] + "backoffSeconds": { + "type": "number", + "description": "This is the seconds to wait before the assistant will start talking again after being interrupted.\n\nDefaults to 1.\n\n@default 1", + "minimum": 0, + "maximum": 10, + "example": 1 }, - "authorizationId": { - "type": "string", - "description": "The authorization ID for the OAuth2 authorization" + "acknowledgementPhrases": { + "description": "These are the phrases that will never interrupt the assistant, even if numWords threshold is met.\nThese are typically acknowledgement or backchanneling phrases.", + "example": [ + "i understand", + "i see", + "i got it", + "i hear you", + "im listening", + "im with you", + "right", + "okay", + "ok", + "sure", + "alright", + "got it", + "understood", + "yeah", + "yes", + "uh-huh", + "mm-hmm", + "gotcha", + "mhmm", + "ah", + "yeah okay", + "yeah sure" + ], + "default": [ + "i understand", + "i see", + "i got it", + "i hear you", + "im listening", + "im with you", + "right", + "okay", + "ok", + "sure", + "alright", + "got it", + "understood", + "yeah", + "yes", + "uh-huh", + "mm-hmm", + "gotcha", + "mhmm", + "ah", + "yeah okay", + "yeah sure" + ], + "type": "array", + "items": { + "type": "string", + "maxLength": 240 + } }, - "name": { - "type": "string", - "description": "This is the name of credential. This is just for your reference.", - "minLength": 1, - "maxLength": 40 + "interruptionPhrases": { + "description": "These are the phrases that will always interrupt the assistant immediately, regardless of numWords.\nThese are typically phrases indicating disagreement or desire to stop.", + "example": [ + "stop", + "shut", + "up", + "enough", + "quiet", + "silence", + "but", + "dont", + "not", + "no", + "hold", + "wait", + "cut", + "pause", + "nope", + "nah", + "nevermind", + "never", + "bad", + "actually" + ], + "default": [ + "stop", + "shut", + "up", + "enough", + "quiet", + "silence", + "but", + "dont", + "not", + "no", + "hold", + "wait", + "cut", + "pause", + "nope", + "nah", + "nevermind", + "never", + "bad", + "actually" + ], + "type": "array", + "items": { + "type": "string", + "maxLength": 240 + } } - }, - "required": [ - "provider", - "authorizationId" - ] + } }, - "CreateSlackOAuth2AuthorizationCredentialDTO": { + "MonitorPlan": { "type": "object", "properties": { - "provider": { - "type": "string", - "enum": [ - "slack.oauth2-authorization" - ] - }, - "authorizationId": { - "type": "string", - "description": "The authorization ID for the OAuth2 authorization" + "listenEnabled": { + "type": "boolean", + "description": "This determines whether the assistant's calls allow live listening. Defaults to true.\n\nFetch `call.monitor.listenUrl` to get the live listening URL.\n\n@default true", + "example": false }, - "name": { - "type": "string", - "description": "This is the name of credential. This is just for your reference.", - "minLength": 1, - "maxLength": 40 - } - }, - "required": [ - "provider", - "authorizationId" - ] - }, - "CreateMinimaxCredentialDTO": { - "type": "object", - "properties": { - "provider": { - "type": "string", - "enum": [ - "minimax" - ] + "listenAuthenticationEnabled": { + "type": "boolean", + "description": "This enables authentication on the `call.monitor.listenUrl`.\n\nIf `listenAuthenticationEnabled` is `true`, the `call.monitor.listenUrl` will require an `Authorization: Bearer ` header.\n\n@default false", + "example": false }, - "apiKey": { - "type": "string", - "description": "This is not returned in the API." + "controlEnabled": { + "type": "boolean", + "description": "This determines whether the assistant's calls allow live control. Defaults to true.\n\nFetch `call.monitor.controlUrl` to get the live control URL.\n\nTo use, send any control message via a POST request to `call.monitor.controlUrl`. Here are the types of controls supported: https://docs.vapi.ai/api-reference/messages/client-inbound-message\n\n@default true", + "example": false }, - "groupId": { - "type": "string", - "description": "This is the Minimax Group ID." + "controlAuthenticationEnabled": { + "type": "boolean", + "description": "This enables authentication on the `call.monitor.controlUrl`.\n\nIf `controlAuthenticationEnabled` is `true`, the `call.monitor.controlUrl` will require an `Authorization: Bearer ` header.\n\n@default false", + "example": false }, - "name": { - "type": "string", - "description": "This is the name of credential. This is just for your reference.", - "minLength": 1, - "maxLength": 40 + "monitorIds": { + "description": "This the set of monitor ids that are attached to the assistant.\nThe source of truth for the monitor ids is the assistant_monitor join table.\nThis field can be used for transient assistants and to update assistants with new monitor ids.\n\n@default []", + "example": [ + "123e4567-e89b-12d3-a456-426614174000" + ], + "type": "array", + "items": { + "type": "string" + } } - }, - "required": [ - "provider", - "apiKey", - "groupId" - ] + } }, - "TransferHookAction": { + "KeypadInputPlan": { "type": "object", "properties": { - "type": { + "enabled": { + "type": "boolean", + "description": "This keeps track of whether the user has enabled keypad input.\nBy default, it is off.\n\n@default false" + }, + "timeoutSeconds": { + "type": "number", + "description": "This is the time in seconds to wait before processing the input.\nIf the input is not received within this time, the input will be ignored.\nIf set to \"off\", the input will be processed when the user enters a delimiter or immediately if no delimiter is used.\n\n@default 2", + "minimum": 0, + "maximum": 10 + }, + "delimiters": { "type": "string", - "description": "This is the type of action - must be \"transfer\"", + "description": "This is the delimiter(s) that will be used to process the input.\nCan be '#', '*', or an empty array.", "enum": [ - "transfer" - ] - }, - "destination": { - "description": "This is the destination details for the transfer - can be a phone number or SIP URI", - "oneOf": [ - { - "$ref": "#/components/schemas/TransferDestinationNumber", - "title": "NumberTransferDestination" - }, - { - "$ref": "#/components/schemas/TransferDestinationSip", - "title": "SipTransferDestination" - } + "#", + "*", + "" ] } - }, - "required": [ - "type" - ] + } }, - "FunctionCallHookAction": { + "WorkflowUserEditable": { "type": "object", "properties": { - "messages": { + "nodes": { "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", "items": { "oneOf": [ { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" + "$ref": "#/components/schemas/ConversationNode", + "title": "ConversationNode" }, { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" + "$ref": "#/components/schemas/ToolNode", + "title": "ToolNode" } ] } }, - "type": { - "type": "string", - "enum": [ - "function" - ], - "description": "The type of tool. \"function\" for Function tool." - }, - "async": { - "type": "boolean", - "example": false, - "description": "This determines if the tool is async.\n\n If async, the assistant will move forward without waiting for your server to respond. This is useful if you just want to trigger something on your server.\n\n If sync, the assistant will wait for your server to respond. This is useful if want assistant to respond with the result from your server.\n\n Defaults to synchronous (`false`)." + "model": { + "description": "This is the model for the workflow.\n\nThis can be overridden at node level using `nodes[n].model`.", + "oneOf": [ + { + "$ref": "#/components/schemas/WorkflowOpenAIModel", + "title": "WorkflowOpenAIModel" + }, + { + "$ref": "#/components/schemas/WorkflowAnthropicModel", + "title": "WorkflowAnthropicModel" + }, + { + "$ref": "#/components/schemas/WorkflowAnthropicBedrockModel", + "title": "WorkflowAnthropicBedrockModel" + }, + { + "$ref": "#/components/schemas/WorkflowGoogleModel", + "title": "WorkflowGoogleModel" + }, + { + "$ref": "#/components/schemas/WorkflowCustomModel", + "title": "WorkflowCustomModel" + } + ] }, - "server": { - "description": "\n This is the server where a `tool-calls` webhook will be sent.\n\n Notes:\n - Webhook is sent to this server when a tool call is made.\n - Webhook contains the call, assistant, and phone number objects.\n - Webhook contains the variables set on the assistant.\n - Webhook is sent to the first available URL in this order: {{tool.server.url}}, {{assistant.server.url}}, {{phoneNumber.server.url}}, {{org.server.url}}.\n - Webhook expects a response with tool call result.", - "allOf": [ + "transcriber": { + "description": "This is the transcriber for the workflow.\n\nThis can be overridden at node level using `nodes[n].transcriber`.", + "oneOf": [ { - "$ref": "#/components/schemas/Server" + "$ref": "#/components/schemas/AssemblyAITranscriber", + "title": "AssemblyAITranscriber" + }, + { + "$ref": "#/components/schemas/AzureSpeechTranscriber", + "title": "AzureSpeechTranscriber" + }, + { + "$ref": "#/components/schemas/CustomTranscriber", + "title": "CustomTranscriber" + }, + { + "$ref": "#/components/schemas/DeepgramTranscriber", + "title": "DeepgramTranscriber" + }, + { + "$ref": "#/components/schemas/ElevenLabsTranscriber", + "title": "ElevenLabsTranscriber" + }, + { + "$ref": "#/components/schemas/GladiaTranscriber", + "title": "GladiaTranscriber" + }, + { + "$ref": "#/components/schemas/GoogleTranscriber", + "title": "GoogleTranscriber" + }, + { + "$ref": "#/components/schemas/SpeechmaticsTranscriber", + "title": "SpeechmaticsTranscriber" + }, + { + "$ref": "#/components/schemas/TalkscriberTranscriber", + "title": "TalkscriberTranscriber" + }, + { + "$ref": "#/components/schemas/OpenAITranscriber", + "title": "OpenAITranscriber" + }, + { + "$ref": "#/components/schemas/CartesiaTranscriber", + "title": "CartesiaTranscriber" + }, + { + "$ref": "#/components/schemas/SonioxTranscriber", + "title": "SonioxTranscriber" + }, + { + "$ref": "#/components/schemas/XaiTranscriber", + "title": "XaiTranscriber" + }, + { + "$ref": "#/components/schemas/VapiTranscriber", + "title": "VapiTranscriber" } ] }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", - "allOf": [ + "voice": { + "description": "This is the voice for the workflow.\n\nThis can be overridden at node level using `nodes[n].voice`.", + "oneOf": [ { - "$ref": "#/components/schemas/ToolRejectionPlan" + "$ref": "#/components/schemas/AzureVoice", + "title": "AzureVoice" + }, + { + "$ref": "#/components/schemas/CartesiaVoice", + "title": "CartesiaVoice" + }, + { + "$ref": "#/components/schemas/CustomVoice", + "title": "CustomVoice" + }, + { + "$ref": "#/components/schemas/DeepgramVoice", + "title": "DeepgramVoice" + }, + { + "$ref": "#/components/schemas/ElevenLabsVoice", + "title": "ElevenLabsVoice" + }, + { + "$ref": "#/components/schemas/HumeVoice", + "title": "HumeVoice" + }, + { + "$ref": "#/components/schemas/LMNTVoice", + "title": "LMNTVoice" + }, + { + "$ref": "#/components/schemas/NeuphonicVoice", + "title": "NeuphonicVoice" + }, + { + "$ref": "#/components/schemas/OpenAIVoice", + "title": "OpenAIVoice" + }, + { + "$ref": "#/components/schemas/PlayHTVoice", + "title": "PlayHTVoice" + }, + { + "$ref": "#/components/schemas/WellSaidVoice", + "title": "WellSaidVoice" + }, + { + "$ref": "#/components/schemas/RimeAIVoice", + "title": "RimeAIVoice" + }, + { + "$ref": "#/components/schemas/SmallestAIVoice", + "title": "SmallestAIVoice" + }, + { + "$ref": "#/components/schemas/TavusVoice", + "title": "TavusVoice" + }, + { + "$ref": "#/components/schemas/VapiVoice", + "title": "VapiVoice" + }, + { + "$ref": "#/components/schemas/SesameVoice", + "title": "SesameVoice" + }, + { + "$ref": "#/components/schemas/InworldVoice", + "title": "InworldVoice" + }, + { + "$ref": "#/components/schemas/MinimaxVoice", + "title": "MinimaxVoice" + }, + { + "$ref": "#/components/schemas/XaiVoice", + "title": "XaiVoice" + }, + { + "$ref": "#/components/schemas/MicrosoftVoice", + "title": "MicrosoftVoice" } ] }, - "function": { - "description": "This is the function definition of the tool.", + "observabilityPlan": { + "description": "This is the plan for observability of workflow's calls.\n\nCurrently, only Langfuse is supported.", + "oneOf": [ + { + "$ref": "#/components/schemas/LangfuseObservabilityPlan", + "title": "Langfuse" + } + ], "allOf": [ { - "$ref": "#/components/schemas/OpenAIFunction" + "$ref": "#/components/schemas/LangfuseObservabilityPlan" } ] - } - }, - "required": [ - "type" - ] - }, - "SayHookAction": { - "type": "object", - "properties": { - "type": { - "type": "string", - "description": "This is the type of action - must be \"say\"", - "enum": [ - "say" - ] }, - "prompt": { - "description": "This is the prompt for the assistant to generate a response based on existing conversation.\nCan be a string or an array of chat messages.", + "backgroundSound": { + "description": "This is the background sound in the call. Default for phone calls is 'office' and default for web calls is 'off'.\nYou can also provide a custom sound by providing a URL to an audio file.", "oneOf": [ { "type": "string", - "title": "String" + "enum": [ + "off", + "office" + ], + "example": "office" }, { - "type": "array", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/SystemMessage", - "title": "SystemMessage" - }, - { - "$ref": "#/components/schemas/UserMessage", - "title": "UserMessage" - }, - { - "$ref": "#/components/schemas/AssistantMessage", - "title": "AssistantMessage" - }, - { - "$ref": "#/components/schemas/ToolMessage", - "title": "ToolMessage" - }, - { - "$ref": "#/components/schemas/DeveloperMessage", - "title": "DeveloperMessage" - } - ] - }, - "title": "MessageArray" + "type": "string", + "format": "uri", + "example": "https://www.soundjay.com/ambient/sounds/people-in-lounge-1.mp3" } - ], - "examples": [ - "Ask the user if they're still in the call", - [ - { - "role": "system", - "content": "You are a helpful assistant, and would like to know if the user is still in the call based on the conversation history in {{transcript}}" - } - ] ] }, - "exact": { - "type": "object", - "description": "This is the message to say" - } - }, - "required": [ - "type" - ] - }, - "CallHookFilter": { - "type": "object", - "properties": { - "type": { - "type": "string", - "description": "This is the type of filter - currently only \"oneOf\" is supported", - "enum": [ - "oneOf" - ], - "maxLength": 1000 - }, - "key": { - "type": "string", - "description": "This is the key to filter on (e.g. \"call.endedReason\")", - "maxLength": 1000 - }, - "oneOf": { - "description": "This is the array of possible values to match against", - "type": "array", - "items": { - "type": "string", - "maxLength": 1000 - } - } - }, - "required": [ - "type", - "key", - "oneOf" - ] - }, - "CallHookCallEnding": { - "type": "object", - "properties": { - "on": { - "type": "string", - "description": "This is the event that triggers this hook", - "enum": [ - "call.ending" - ], - "maxLength": 1000 - }, - "do": { + "hooks": { "type": "array", - "description": "This is the set of actions to perform when the hook triggers", + "description": "This is a set of actions that will be performed on certain events.", "items": { "oneOf": [ { - "$ref": "#/components/schemas/ToolCallHookAction", - "title": "ToolCallHookAction" - } - ] - } - }, - "filters": { - "description": "This is the set of filters that must match for the hook to trigger", - "type": "array", - "items": { - "$ref": "#/components/schemas/CallHookFilter" - } - } - }, - "required": [ - "on", - "do" - ] - }, - "CallHookAssistantSpeechInterrupted": { - "type": "object", - "properties": { - "on": { - "type": "string", - "description": "This is the event that triggers this hook", - "enum": [ - "assistant.speech.interrupted" - ], - "maxLength": 1000 - }, - "do": { - "type": "array", - "description": "This is the set of actions to perform when the hook triggers", - "items": { - "oneOf": [ + "$ref": "#/components/schemas/CallHookCallEnding", + "title": "CallHookCallEnding" + }, { - "$ref": "#/components/schemas/SayHookAction", - "title": "SayHookAction" + "$ref": "#/components/schemas/CallHookAssistantSpeechInterrupted", + "title": "CallHookAssistantSpeechInterrupted" }, { - "$ref": "#/components/schemas/ToolCallHookAction", - "title": "ToolCallHookAction" + "$ref": "#/components/schemas/CallHookCustomerSpeechInterrupted", + "title": "CallHookCustomerSpeechInterrupted" + }, + { + "$ref": "#/components/schemas/CallHookCustomerSpeechTimeout", + "title": "CallHookCustomerSpeechTimeout" + }, + { + "$ref": "#/components/schemas/CallHookModelResponseTimeout", + "title": "CallHookModelResponseTimeout" } ] } - } - }, - "required": [ - "on", - "do" - ] - }, - "CallHookCustomerSpeechInterrupted": { - "type": "object", - "properties": { - "on": { - "type": "string", - "description": "This is the event that triggers this hook", - "enum": [ - "customer.speech.interrupted" - ], - "maxLength": 1000 }, - "do": { + "credentials": { "type": "array", - "description": "This is the set of actions to perform when the hook triggers", + "description": "These are dynamic credentials that will be used for the workflow calls. By default, all the credentials are available for use in the call but you can supplement an additional credentials using this. Dynamic credentials override existing credentials.", "items": { "oneOf": [ { - "$ref": "#/components/schemas/SayHookAction", - "title": "SayHookAction" + "$ref": "#/components/schemas/CreateAnthropicCredentialDTO", + "title": "AnthropicCredential" }, { - "$ref": "#/components/schemas/ToolCallHookAction", - "title": "ToolCallHookAction" + "$ref": "#/components/schemas/CreateAnthropicBedrockCredentialDTO", + "title": "AnthropicBedrockCredential" + }, + { + "$ref": "#/components/schemas/CreateAnyscaleCredentialDTO", + "title": "AnyscaleCredential" + }, + { + "$ref": "#/components/schemas/CreateAssemblyAICredentialDTO", + "title": "AssemblyAICredential" + }, + { + "$ref": "#/components/schemas/CreateAzureCredentialDTO", + "title": "AzureCredential" + }, + { + "$ref": "#/components/schemas/CreateAzureOpenAICredentialDTO", + "title": "AzureOpenAICredential" + }, + { + "$ref": "#/components/schemas/CreateByoSipTrunkCredentialDTO", + "title": "ByoSipTrunkCredential" + }, + { + "$ref": "#/components/schemas/CreateCartesiaCredentialDTO", + "title": "CartesiaCredential" + }, + { + "$ref": "#/components/schemas/CreateCerebrasCredentialDTO", + "title": "CerebrasCredential" + }, + { + "$ref": "#/components/schemas/CreateCloudflareCredentialDTO", + "title": "CloudflareCredential" + }, + { + "$ref": "#/components/schemas/CreateCustomLLMCredentialDTO", + "title": "CustomLLMCredential" + }, + { + "$ref": "#/components/schemas/CreateDeepgramCredentialDTO", + "title": "DeepgramCredential" + }, + { + "$ref": "#/components/schemas/CreateDeepInfraCredentialDTO", + "title": "DeepInfraCredential" + }, + { + "$ref": "#/components/schemas/CreateDeepSeekCredentialDTO", + "title": "DeepSeekCredential" + }, + { + "$ref": "#/components/schemas/CreateElevenLabsCredentialDTO", + "title": "ElevenLabsCredential" + }, + { + "$ref": "#/components/schemas/CreateGcpCredentialDTO", + "title": "GcpCredential" + }, + { + "$ref": "#/components/schemas/CreateGladiaCredentialDTO", + "title": "GladiaCredential" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelCredentialDTO", + "title": "GhlCredential" + }, + { + "$ref": "#/components/schemas/CreateGoogleCredentialDTO", + "title": "GoogleCredential" + }, + { + "$ref": "#/components/schemas/CreateGroqCredentialDTO", + "title": "GroqCredential" + }, + { + "$ref": "#/components/schemas/CreateHumeCredentialDTO", + "title": "HumeCredential" + }, + { + "$ref": "#/components/schemas/CreateInflectionAICredentialDTO", + "title": "InflectionAICredential" + }, + { + "$ref": "#/components/schemas/CreateLangfuseCredentialDTO", + "title": "LangfuseCredential" + }, + { + "$ref": "#/components/schemas/CreateLmntCredentialDTO", + "title": "LmntCredential" + }, + { + "$ref": "#/components/schemas/CreateMakeCredentialDTO", + "title": "MakeCredential" + }, + { + "$ref": "#/components/schemas/CreateMistralCredentialDTO", + "title": "MistralCredential" + }, + { + "$ref": "#/components/schemas/CreateNeuphonicCredentialDTO", + "title": "NeuphonicCredential" + }, + { + "$ref": "#/components/schemas/CreateOpenAICredentialDTO", + "title": "OpenAICredential" + }, + { + "$ref": "#/components/schemas/CreateOpenRouterCredentialDTO", + "title": "OpenRouterCredential" + }, + { + "$ref": "#/components/schemas/CreatePerplexityAICredentialDTO", + "title": "PerplexityAICredential" + }, + { + "$ref": "#/components/schemas/CreatePlayHTCredentialDTO", + "title": "PlayHTCredential" + }, + { + "$ref": "#/components/schemas/CreateRimeAICredentialDTO", + "title": "RimeAICredential" + }, + { + "$ref": "#/components/schemas/CreateRunpodCredentialDTO", + "title": "RunpodCredential" + }, + { + "$ref": "#/components/schemas/CreateS3CredentialDTO", + "title": "S3Credential" + }, + { + "$ref": "#/components/schemas/CreateS3CompatibleCredentialDTO", + "title": "S3CompatibleStorageCredential" + }, + { + "$ref": "#/components/schemas/CreateSmallestAICredentialDTO", + "title": "SmallestAICredential" + }, + { + "$ref": "#/components/schemas/CreateSpeechmaticsCredentialDTO", + "title": "SpeechmaticsCredential" + }, + { + "$ref": "#/components/schemas/CreateSonioxCredentialDTO", + "title": "SonioxCredential" + }, + { + "$ref": "#/components/schemas/CreateSupabaseCredentialDTO", + "title": "SupabaseCredential" + }, + { + "$ref": "#/components/schemas/CreateTavusCredentialDTO", + "title": "TavusCredential" + }, + { + "$ref": "#/components/schemas/CreateTogetherAICredentialDTO", + "title": "TogetherAICredential" + }, + { + "$ref": "#/components/schemas/CreateTwilioCredentialDTO", + "title": "TwilioCredential" + }, + { + "$ref": "#/components/schemas/CreateVonageCredentialDTO", + "title": "VonageCredential" + }, + { + "$ref": "#/components/schemas/CreateWebhookCredentialDTO", + "title": "WebhookCredential" + }, + { + "$ref": "#/components/schemas/CreateCustomCredentialDTO", + "title": "CustomCredential" + }, + { + "$ref": "#/components/schemas/CreateXAiCredentialDTO", + "title": "XAiCredential" + }, + { + "$ref": "#/components/schemas/CreateMicrosoftCredentialDTO", + "title": "MicrosoftCredential" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarOAuth2ClientCredentialDTO", + "title": "GoogleCalendarOAuth2ClientCredential" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarOAuth2AuthorizationCredentialDTO", + "title": "GoogleCalendarOAuth2AuthorizationCredential" + }, + { + "$ref": "#/components/schemas/CreateGoogleSheetsOAuth2AuthorizationCredentialDTO", + "title": "GoogleSheetsOAuth2AuthorizationCredential" + }, + { + "$ref": "#/components/schemas/CreateSlackOAuth2AuthorizationCredentialDTO", + "title": "SlackOAuth2AuthorizationCredential" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelMCPCredentialDTO", + "title": "GoHighLevelMCPCredential" + }, + { + "$ref": "#/components/schemas/CreateInworldCredentialDTO", + "title": "InworldCredential" + }, + { + "$ref": "#/components/schemas/CreateMinimaxCredentialDTO", + "title": "MinimaxCredential" + }, + { + "$ref": "#/components/schemas/CreateWellSaidCredentialDTO", + "title": "WellSaidCredential" + }, + { + "$ref": "#/components/schemas/CreateEmailCredentialDTO", + "title": "EmailCredential" + }, + { + "$ref": "#/components/schemas/CreateSlackWebhookCredentialDTO", + "title": "SlackWebhookCredential" } - ] + ], + "discriminator": { + "propertyName": "provider", + "mapping": { + "11labs": "#/components/schemas/CreateElevenLabsCredentialDTO", + "anthropic": "#/components/schemas/CreateAnthropicCredentialDTO", + "anthropic-bedrock": "#/components/schemas/CreateAnthropicBedrockCredentialDTO", + "anyscale": "#/components/schemas/CreateAnyscaleCredentialDTO", + "assembly-ai": "#/components/schemas/CreateAssemblyAICredentialDTO", + "azure-openai": "#/components/schemas/CreateAzureOpenAICredentialDTO", + "azure": "#/components/schemas/CreateAzureCredentialDTO", + "byo-sip-trunk": "#/components/schemas/CreateByoSipTrunkCredentialDTO", + "cartesia": "#/components/schemas/CreateCartesiaCredentialDTO", + "cerebras": "#/components/schemas/CreateCerebrasCredentialDTO", + "cloudflare": "#/components/schemas/CreateCloudflareCredentialDTO", + "custom-llm": "#/components/schemas/CreateCustomLLMCredentialDTO", + "deepgram": "#/components/schemas/CreateDeepgramCredentialDTO", + "deepinfra": "#/components/schemas/CreateDeepInfraCredentialDTO", + "deep-seek": "#/components/schemas/CreateDeepSeekCredentialDTO", + "gcp": "#/components/schemas/CreateGcpCredentialDTO", + "gladia": "#/components/schemas/CreateGladiaCredentialDTO", + "gohighlevel": "#/components/schemas/CreateGoHighLevelCredentialDTO", + "google": "#/components/schemas/CreateGoogleCredentialDTO", + "groq": "#/components/schemas/CreateGroqCredentialDTO", + "inflection-ai": "#/components/schemas/CreateInflectionAICredentialDTO", + "langfuse": "#/components/schemas/CreateLangfuseCredentialDTO", + "lmnt": "#/components/schemas/CreateLmntCredentialDTO", + "make": "#/components/schemas/CreateMakeCredentialDTO", + "openai": "#/components/schemas/CreateOpenAICredentialDTO", + "openrouter": "#/components/schemas/CreateOpenRouterCredentialDTO", + "perplexity-ai": "#/components/schemas/CreatePerplexityAICredentialDTO", + "playht": "#/components/schemas/CreatePlayHTCredentialDTO", + "rime-ai": "#/components/schemas/CreateRimeAICredentialDTO", + "runpod": "#/components/schemas/CreateRunpodCredentialDTO", + "s3": "#/components/schemas/CreateS3CredentialDTO", + "s3-compatible": "#/components/schemas/CreateS3CompatibleCredentialDTO", + "supabase": "#/components/schemas/CreateSupabaseCredentialDTO", + "smallest-ai": "#/components/schemas/CreateSmallestAICredentialDTO", + "tavus": "#/components/schemas/CreateTavusCredentialDTO", + "together-ai": "#/components/schemas/CreateTogetherAICredentialDTO", + "twilio": "#/components/schemas/CreateTwilioCredentialDTO", + "vonage": "#/components/schemas/CreateVonageCredentialDTO", + "webhook": "#/components/schemas/CreateWebhookCredentialDTO", + "custom-credential": "#/components/schemas/CreateCustomCredentialDTO", + "xai": "#/components/schemas/CreateXAiCredentialDTO", + "microsoft": "#/components/schemas/CreateMicrosoftCredentialDTO", + "neuphonic": "#/components/schemas/CreateNeuphonicCredentialDTO", + "hume": "#/components/schemas/CreateHumeCredentialDTO", + "mistral": "#/components/schemas/CreateMistralCredentialDTO", + "speechmatics": "#/components/schemas/CreateSpeechmaticsCredentialDTO", + "soniox": "#/components/schemas/CreateSonioxCredentialDTO", + "google.calendar.oauth2-client": "#/components/schemas/CreateGoogleCalendarOAuth2ClientCredentialDTO", + "google.calendar.oauth2-authorization": "#/components/schemas/CreateGoogleCalendarOAuth2AuthorizationCredentialDTO", + "google.sheets.oauth2-authorization": "#/components/schemas/CreateGoogleSheetsOAuth2AuthorizationCredentialDTO", + "slack.oauth2-authorization": "#/components/schemas/CreateSlackOAuth2AuthorizationCredentialDTO", + "ghl.oauth2-authorization": "#/components/schemas/CreateGoHighLevelMCPCredentialDTO", + "inworld": "#/components/schemas/CreateInworldCredentialDTO", + "minimax": "#/components/schemas/CreateMinimaxCredentialDTO", + "wellsaid": "#/components/schemas/CreateWellSaidCredentialDTO", + "email": "#/components/schemas/CreateEmailCredentialDTO", + "slack-webhook": "#/components/schemas/CreateSlackWebhookCredentialDTO" + } + } } - } - }, - "required": [ - "on", - "do" - ] - }, - "ToolCallHookAction": { - "type": "object", - "properties": { - "type": { - "type": "string", - "description": "This is the type of action - must be \"tool\"", - "enum": [ - "tool" - ] }, - "tool": { - "description": "This is the tool to call. To use an existing tool, send `toolId` instead.", + "voicemailDetection": { + "description": "This is the voicemail detection plan for the workflow.", "oneOf": [ { - "$ref": "#/components/schemas/CreateApiRequestToolDTO", - "title": "ApiRequestTool" + "type": "string", + "enum": [ + "off" + ] }, { - "$ref": "#/components/schemas/CreateBashToolDTO", - "title": "BashTool" + "$ref": "#/components/schemas/GoogleVoicemailDetectionPlan", + "title": "Google" }, { - "$ref": "#/components/schemas/CreateComputerToolDTO", - "title": "ComputerTool" + "$ref": "#/components/schemas/OpenAIVoicemailDetectionPlan", + "title": "OpenAI" }, { - "$ref": "#/components/schemas/CreateDtmfToolDTO", - "title": "DtmfTool" + "$ref": "#/components/schemas/TwilioVoicemailDetectionPlan", + "title": "Twilio" }, { - "$ref": "#/components/schemas/CreateEndCallToolDTO", - "title": "EndCallTool" - }, + "$ref": "#/components/schemas/VapiVoicemailDetectionPlan", + "title": "Vapi" + } + ] + }, + "maxDurationSeconds": { + "type": "number", + "description": "This is the maximum duration of the call in seconds.\n\nAfter this duration, the call will automatically end.\n\nDefault is 1800 (30 minutes), max is 43200 (12 hours), and min is 10 seconds.", + "minimum": 10, + "maximum": 43200, + "example": 600 + }, + "name": { + "type": "string", + "maxLength": 80 + }, + "edges": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Edge" + } + }, + "globalPrompt": { + "type": "string", + "maxLength": 5000 + }, + "server": { + "description": "This is where Vapi will send webhooks. You can find all webhooks available along with their shape in ServerMessage schema.\n\nThe order of precedence is:\n\n1. tool.server\n2. workflow.server / assistant.server\n3. phoneNumber.server\n4. org.server", + "allOf": [ { - "$ref": "#/components/schemas/CreateFunctionToolDTO", - "title": "FunctionTool" - }, + "$ref": "#/components/schemas/Server" + } + ] + }, + "compliancePlan": { + "description": "This is the compliance plan for the workflow. It allows you to configure HIPAA and other compliance settings.", + "allOf": [ { - "$ref": "#/components/schemas/CreateGoHighLevelCalendarAvailabilityToolDTO", - "title": "GoHighLevelCalendarAvailabilityTool" - }, + "$ref": "#/components/schemas/CompliancePlan" + } + ] + }, + "analysisPlan": { + "description": "This is the plan for analysis of workflow's calls. Stored in `call.analysis`.", + "allOf": [ { - "$ref": "#/components/schemas/CreateGoHighLevelCalendarEventCreateToolDTO", - "title": "GoHighLevelCalendarEventCreateTool" - }, + "$ref": "#/components/schemas/AnalysisPlan" + } + ] + }, + "artifactPlan": { + "description": "This is the plan for artifacts generated during workflow's calls. Stored in `call.artifact`.", + "allOf": [ { - "$ref": "#/components/schemas/CreateGoHighLevelContactCreateToolDTO", - "title": "GoHighLevelContactCreateTool" - }, + "$ref": "#/components/schemas/ArtifactPlan" + } + ] + }, + "startSpeakingPlan": { + "description": "This is the plan for when the workflow nodes should start talking.\n\nYou should configure this if you're running into these issues:\n- The assistant is too slow to start talking after the customer is done speaking.\n- The assistant is too fast to start talking after the customer is done speaking.\n- The assistant is so fast that it's actually interrupting the customer.", + "allOf": [ { - "$ref": "#/components/schemas/CreateGoHighLevelContactGetToolDTO", - "title": "GoHighLevelContactGetTool" - }, - { - "$ref": "#/components/schemas/CreateGoogleCalendarCheckAvailabilityToolDTO", - "title": "GoogleCalendarCheckAvailabilityTool" - }, - { - "$ref": "#/components/schemas/CreateGoogleCalendarCreateEventToolDTO", - "title": "GoogleCalendarCreateEventTool" - }, - { - "$ref": "#/components/schemas/CreateGoogleSheetsRowAppendToolDTO", - "title": "GoogleSheetsRowAppendTool" - }, - { - "$ref": "#/components/schemas/CreateHandoffToolDTO", - "title": "HandoffTool" - }, - { - "$ref": "#/components/schemas/CreateMcpToolDTO", - "title": "McpTool" - }, - { - "$ref": "#/components/schemas/CreateQueryToolDTO", - "title": "QueryTool" - }, - { - "$ref": "#/components/schemas/CreateSlackSendMessageToolDTO", - "title": "SlackSendMessageTool" - }, + "$ref": "#/components/schemas/StartSpeakingPlan" + } + ] + }, + "stopSpeakingPlan": { + "description": "This is the plan for when workflow nodes should stop talking on customer interruption.\n\nYou should configure this if you're running into these issues:\n- The assistant is too slow to recognize customer's interruption.\n- The assistant is too fast to recognize customer's interruption.\n- The assistant is getting interrupted by phrases that are just acknowledgments.\n- The assistant is getting interrupted by background noises.\n- The assistant is not properly stopping -- it starts talking right after getting interrupted.", + "allOf": [ { - "$ref": "#/components/schemas/CreateSmsToolDTO", - "title": "SmsTool" - }, + "$ref": "#/components/schemas/StopSpeakingPlan" + } + ] + }, + "monitorPlan": { + "description": "This is the plan for real-time monitoring of the workflow's calls.\n\nUsage:\n- To enable live listening of the workflow's calls, set `monitorPlan.listenEnabled` to `true`.\n- To enable live control of the workflow's calls, set `monitorPlan.controlEnabled` to `true`.", + "allOf": [ { - "$ref": "#/components/schemas/CreateTextEditorToolDTO", - "title": "TextEditorTool" - }, + "$ref": "#/components/schemas/MonitorPlan" + } + ] + }, + "backgroundSpeechDenoisingPlan": { + "description": "This enables filtering of noise and background speech while the user is talking.\n\nFeatures:\n- Smart denoising using Krisp\n- Fourier denoising\n\nBoth can be used together. Order of precedence:\n- Smart denoising\n- Fourier denoising", + "allOf": [ { - "$ref": "#/components/schemas/CreateTransferCallToolDTO", - "title": "TransferCallTool" + "$ref": "#/components/schemas/BackgroundSpeechDenoisingPlan" } ] }, - "toolId": { - "type": "string", - "description": "This is the tool to call. To use a transient tool, send `tool` instead." - } - }, - "required": [ - "type" - ] - }, - "CustomerSpeechTimeoutOptions": { - "type": "object", - "properties": { - "timeoutSeconds": { - "type": "number", - "description": "This is the timeout in seconds before action is triggered.\nThe clock starts when the assistant finishes speaking and remains active until the user speaks.\n\n@default 7.5", - "minimum": 1, - "maximum": 1000 + "credentialIds": { + "description": "These are the credentials that will be used for the workflow calls. By default, all the credentials are available for use in the call but you can provide a subset using this.", + "type": "array", + "items": { + "type": "string" + } }, - "triggerMaxCount": { - "type": "number", - "description": "This is the maximum number of times the hook will trigger in a call.\n\n@default 3", - "minimum": 1, - "maximum": 10 + "keypadInputPlan": { + "description": "This is the plan for keypad input handling during workflow calls.", + "allOf": [ + { + "$ref": "#/components/schemas/KeypadInputPlan" + } + ] }, - "triggerResetMode": { - "type": "object", - "description": "This is whether the counter for hook trigger resets the user speaks.\n\n@default never" + "voicemailMessage": { + "type": "string", + "description": "This is the message that the assistant will say if the call is forwarded to voicemail.\n\nIf unspecified, it will hang up.", + "maxLength": 1000 } }, "required": [ - "timeoutSeconds" + "nodes", + "name", + "edges" ] }, - "CallHookCustomerSpeechTimeout": { + "VapiModel": { "type": "object", "properties": { - "on": { - "type": "string", - "description": "Must be either \"customer.speech.timeout\" or match the pattern \"customer.speech.timeout[property=value]\"", - "maxLength": 1000 + "messages": { + "description": "This is the starting state for the conversation.", + "type": "array", + "items": { + "$ref": "#/components/schemas/OpenAIMessage" + } }, - "do": { + "tools": { "type": "array", - "description": "This is the set of actions to perform when the hook triggers", + "description": "These are the tools that the assistant can use during the call. To use existing tools, use `toolIds`.\n\nBoth `tools` and `toolIds` can be used together.", "items": { "oneOf": [ { - "$ref": "#/components/schemas/SayHookAction", - "title": "SayHookAction" + "$ref": "#/components/schemas/CreateApiRequestToolDTO", + "title": "ApiRequestTool" }, { - "$ref": "#/components/schemas/ToolCallHookAction", - "title": "ToolCallHookAction" + "$ref": "#/components/schemas/CreateBashToolDTO", + "title": "BashTool" + }, + { + "$ref": "#/components/schemas/CreateCodeToolDTO", + "title": "CodeTool" + }, + { + "$ref": "#/components/schemas/CreateComputerToolDTO", + "title": "ComputerTool" + }, + { + "$ref": "#/components/schemas/CreateDtmfToolDTO", + "title": "DtmfTool" + }, + { + "$ref": "#/components/schemas/CreateEndCallToolDTO", + "title": "EndCallTool" + }, + { + "$ref": "#/components/schemas/CreateFunctionToolDTO", + "title": "FunctionTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelCalendarAvailabilityToolDTO", + "title": "GoHighLevelCalendarAvailabilityTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelCalendarEventCreateToolDTO", + "title": "GoHighLevelCalendarEventCreateTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelContactCreateToolDTO", + "title": "GoHighLevelContactCreateTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelContactGetToolDTO", + "title": "GoHighLevelContactGetTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarCheckAvailabilityToolDTO", + "title": "GoogleCalendarCheckAvailabilityTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarCreateEventToolDTO", + "title": "GoogleCalendarCreateEventTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleSheetsRowAppendToolDTO", + "title": "GoogleSheetsRowAppendTool" + }, + { + "$ref": "#/components/schemas/CreateHandoffToolDTO", + "title": "HandoffTool" + }, + { + "$ref": "#/components/schemas/CreateMcpToolDTO", + "title": "McpTool" + }, + { + "$ref": "#/components/schemas/CreateQueryToolDTO", + "title": "QueryTool" + }, + { + "$ref": "#/components/schemas/CreateSlackSendMessageToolDTO", + "title": "SlackSendMessageTool" + }, + { + "$ref": "#/components/schemas/CreateSmsToolDTO", + "title": "SmsTool" + }, + { + "$ref": "#/components/schemas/CreateTextEditorToolDTO", + "title": "TextEditorTool" + }, + { + "$ref": "#/components/schemas/CreateTransferCallToolDTO", + "title": "TransferCallTool" + }, + { + "$ref": "#/components/schemas/CreateSipRequestToolDTO", + "title": "SipRequestTool" + }, + { + "$ref": "#/components/schemas/CreateVoicemailToolDTO", + "title": "VoicemailTool" } ] } }, - "options": { - "description": "This is the set of filters that must match for the hook to trigger", - "allOf": [ + "toolIds": { + "description": "These are the tools that the assistant can use during the call. To use transient tools, use `tools`.\n\nBoth `tools` and `toolIds` can be used together.", + "type": "array", + "items": { + "type": "string" + } + }, + "toolRefs": { + "description": "These are version-pinned references to tools. Each entry pins a specific\nversion of a tool by `(toolId, version)`. When the same `toolId` appears\nin both `toolIds` and `toolRefs[]`, the `toolRefs` pin wins (the\n`toolIds` entry is dropped at write time).", + "type": "array", + "items": { + "$ref": "#/components/schemas/ToolRef" + } + }, + "knowledgeBase": { + "description": "These are the options for the knowledge base.", + "oneOf": [ { - "$ref": "#/components/schemas/CustomerSpeechTimeoutOptions" + "$ref": "#/components/schemas/CreateCustomKnowledgeBaseDTO", + "title": "Custom" } ] }, - "name": { + "model": { "type": "string", - "description": "This is the name of the hook, it can be set by the user to identify the hook.\nIf no name is provided, the hook will be auto generated as UUID.\n\n@default UUID", - "maxLength": 1000 - } - }, - "required": [ - "on", - "do" - ] - }, - "VoicemailDetectionBackoffPlan": { - "type": "object", - "properties": { - "startAtSeconds": { + "description": "White-label Vapi models are selected by `version`, not a model name, so\n`model` is optional here (the runtime already accepts a version-only Vapi\npayload). Overriding the required `ModelBase.model`: the declared type stays\n`string` to match the base (avoids TS2416) and the `= undefined!` initializer\nsatisfies TS2612 for the field override, while `@IsOptional` +\n`@ApiPropertyOptional` make validation and the generated OpenAPI schema treat\nit as optional (so `VapiModel.required` is `['provider']`)." + }, + "version": { + "type": "string", + "description": "Vapi-managed model version (update channel). When set, this is a Vapi-managed\nLLM routed by the registry; when absent, this is the legacy workflow form\nbelow (`steps` / `workflow`).", + "enum": [ + "latest", + "1" + ] + }, + "provider": { + "type": "string", + "enum": [ + "vapi" + ] + }, + "workflowId": { + "type": "string", + "description": "This is the workflow that will be used for the call. To use a transient workflow, use `workflow` instead." + }, + "workflow": { + "description": "This is the workflow that will be used for the call. To use an existing workflow, use `workflowId` instead.", + "allOf": [ + { + "$ref": "#/components/schemas/WorkflowUserEditable" + } + ] + }, + "temperature": { "type": "number", - "description": "This is the number of seconds to wait before starting the first retry attempt.", + "description": "This is the temperature that will be used for calls. Default is 0.5.", "minimum": 0, - "default": 5 + "maximum": 2 }, - "frequencySeconds": { - "type": "number", - "description": "This is the interval in seconds between retry attempts.", - "minimum": 2.5, - "default": 5 + "emotionRecognitionEnabled": { + "type": "boolean", + "description": "This determines whether we detect user's emotion while they speak and send it as an additional info to model.\n\nDefault `false` because the model is usually are good at understanding the user's emotion from text.\n\n@default false" }, - "maxRetries": { + "numFastTurns": { "type": "number", - "description": "This is the maximum number of retry attempts before giving up.", - "minimum": 1, - "maximum": 10, - "default": 6 + "description": "This sets how many turns at the start of the conversation to use a smaller, faster model from the same provider before switching to the primary model. Example, gpt-3.5-turbo if provider is openai.\n\nDefault is 0.\n\n@default 0", + "minimum": 0 } - } + }, + "required": [ + "provider" + ] }, - "GoogleVoicemailDetectionPlan": { + "XaiModel": { "type": "object", "properties": { - "beepMaxAwaitSeconds": { - "type": "number", - "description": "This is the maximum duration from the start of the call that we will wait for a voicemail beep, before speaking our message\n\n- If we detect a voicemail beep before this, we will speak the message at that point.\n\n- Setting too low a value means that the bot will start speaking its voicemail message too early. If it does so before the actual beep, it will get cut off. You should definitely tune this to your use case.\n\n@default 30\n@min 0\n@max 60", - "minimum": 0, - "maximum": 30, - "default": 30 + "messages": { + "description": "This is the starting state for the conversation.", + "type": "array", + "items": { + "$ref": "#/components/schemas/OpenAIMessage" + } }, - "provider": { - "type": "string", - "description": "This is the provider to use for voicemail detection.", - "enum": [ - "google" - ] + "tools": { + "type": "array", + "description": "These are the tools that the assistant can use during the call. To use existing tools, use `toolIds`.\n\nBoth `tools` and `toolIds` can be used together.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/CreateApiRequestToolDTO", + "title": "ApiRequestTool" + }, + { + "$ref": "#/components/schemas/CreateBashToolDTO", + "title": "BashTool" + }, + { + "$ref": "#/components/schemas/CreateCodeToolDTO", + "title": "CodeTool" + }, + { + "$ref": "#/components/schemas/CreateComputerToolDTO", + "title": "ComputerTool" + }, + { + "$ref": "#/components/schemas/CreateDtmfToolDTO", + "title": "DtmfTool" + }, + { + "$ref": "#/components/schemas/CreateEndCallToolDTO", + "title": "EndCallTool" + }, + { + "$ref": "#/components/schemas/CreateFunctionToolDTO", + "title": "FunctionTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelCalendarAvailabilityToolDTO", + "title": "GoHighLevelCalendarAvailabilityTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelCalendarEventCreateToolDTO", + "title": "GoHighLevelCalendarEventCreateTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelContactCreateToolDTO", + "title": "GoHighLevelContactCreateTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelContactGetToolDTO", + "title": "GoHighLevelContactGetTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarCheckAvailabilityToolDTO", + "title": "GoogleCalendarCheckAvailabilityTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarCreateEventToolDTO", + "title": "GoogleCalendarCreateEventTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleSheetsRowAppendToolDTO", + "title": "GoogleSheetsRowAppendTool" + }, + { + "$ref": "#/components/schemas/CreateHandoffToolDTO", + "title": "HandoffTool" + }, + { + "$ref": "#/components/schemas/CreateMcpToolDTO", + "title": "McpTool" + }, + { + "$ref": "#/components/schemas/CreateQueryToolDTO", + "title": "QueryTool" + }, + { + "$ref": "#/components/schemas/CreateSlackSendMessageToolDTO", + "title": "SlackSendMessageTool" + }, + { + "$ref": "#/components/schemas/CreateSmsToolDTO", + "title": "SmsTool" + }, + { + "$ref": "#/components/schemas/CreateTextEditorToolDTO", + "title": "TextEditorTool" + }, + { + "$ref": "#/components/schemas/CreateTransferCallToolDTO", + "title": "TransferCallTool" + }, + { + "$ref": "#/components/schemas/CreateSipRequestToolDTO", + "title": "SipRequestTool" + }, + { + "$ref": "#/components/schemas/CreateVoicemailToolDTO", + "title": "VoicemailTool" + } + ] + } }, - "backoffPlan": { - "description": "This is the backoff plan for the voicemail detection.", - "allOf": [ + "toolIds": { + "description": "These are the tools that the assistant can use during the call. To use transient tools, use `tools`.\n\nBoth `tools` and `toolIds` can be used together.", + "type": "array", + "items": { + "type": "string" + } + }, + "toolRefs": { + "description": "These are version-pinned references to tools. Each entry pins a specific\nversion of a tool by `(toolId, version)`. When the same `toolId` appears\nin both `toolIds` and `toolRefs[]`, the `toolRefs` pin wins (the\n`toolIds` entry is dropped at write time).", + "type": "array", + "items": { + "$ref": "#/components/schemas/ToolRef" + } + }, + "knowledgeBase": { + "description": "These are the options for the knowledge base.", + "oneOf": [ { - "$ref": "#/components/schemas/VoicemailDetectionBackoffPlan" + "$ref": "#/components/schemas/CreateCustomKnowledgeBaseDTO", + "title": "Custom" } ] }, - "type": { + "model": { "type": "string", - "description": "This is the detection type to use for voicemail detection.\n- 'audio': Uses native audio models (default)\n- 'transcript': Uses ASR/transcript-based detection\n@default 'audio' (audio detection)", + "description": "This is the name of the model. Ex. cognitivecomputations/dolphin-mixtral-8x7b", "enum": [ - "audio", - "transcript" + "grok-beta", + "grok-2", + "grok-3", + "grok-4-fast-reasoning", + "grok-4-fast-non-reasoning", + "grok-4.20-0309-reasoning", + "grok-4.20-0309-non-reasoning", + "grok-4.3" + ] + }, + "provider": { + "type": "string", + "enum": [ + "xai" ] + }, + "temperature": { + "type": "number", + "description": "This is the temperature that will be used for calls. Default is 0.5.", + "minimum": 0, + "maximum": 2 + }, + "maxTokens": { + "type": "number", + "description": "This is the max number of tokens that the assistant will be allowed to generate in each turn of the conversation. Default is 250.", + "minimum": 50, + "maximum": 10000 + }, + "emotionRecognitionEnabled": { + "type": "boolean", + "description": "This determines whether we detect user's emotion while they speak and send it as an additional info to model.\n\nDefault `false` because the model is usually are good at understanding the user's emotion from text.\n\n@default false" + }, + "numFastTurns": { + "type": "number", + "description": "This sets how many turns at the start of the conversation to use a smaller, faster model from the same provider before switching to the primary model. Example, gpt-3.5-turbo if provider is openai.\n\nDefault is 0.\n\n@default 0", + "minimum": 0 } }, "required": [ + "model", "provider" ] }, - "OpenAIVoicemailDetectionPlan": { + "ExactReplacement": { "type": "object", "properties": { - "beepMaxAwaitSeconds": { - "type": "number", - "description": "This is the maximum duration from the start of the call that we will wait for a voicemail beep, before speaking our message\n\n- If we detect a voicemail beep before this, we will speak the message at that point.\n\n- Setting too low a value means that the bot will start speaking its voicemail message too early. If it does so before the actual beep, it will get cut off. You should definitely tune this to your use case.\n\n@default 30\n@min 0\n@max 60", - "minimum": 0, - "maximum": 30, - "default": 30 - }, - "provider": { + "type": { "type": "string", - "description": "This is the provider to use for voicemail detection.", + "description": "This is the exact replacement type. You can use this to replace a specific word or phrase with a different word or phrase.\n\nUsage:\n- Replace \"hello\" with \"hi\": { type: 'exact', key: 'hello', value: 'hi' }\n- Replace \"good morning\" with \"good day\": { type: 'exact', key: 'good morning', value: 'good day' }\n- Replace a specific name: { type: 'exact', key: 'John Doe', value: 'Jane Smith' }\n- Replace an acronym: { type: 'exact', key: 'AI', value: 'Artificial Intelligence' }\n- Replace a company name with its phonetic pronunciation: { type: 'exact', key: 'Vapi', value: 'Vappy' }", "enum": [ - "openai" + "exact" ] }, - "backoffPlan": { - "description": "This is the backoff plan for the voicemail detection.", - "allOf": [ - { - "$ref": "#/components/schemas/VoicemailDetectionBackoffPlan" - } - ] + "replaceAllEnabled": { + "type": "boolean", + "description": "This option let's you control whether to replace all instances of the key or only the first one. By default, it only replaces the first instance.\nExamples:\n- For { type: 'exact', key: 'hello', value: 'hi', replaceAllEnabled: false }. Before: \"hello world, hello universe\" | After: \"hi world, hello universe\"\n- For { type: 'exact', key: 'hello', value: 'hi', replaceAllEnabled: true }. Before: \"hello world, hello universe\" | After: \"hi world, hi universe\"\n@default false", + "default": false }, - "type": { + "key": { "type": "string", - "description": "This is the detection type to use for voicemail detection.\n- 'audio': Uses native audio models (default)\n- 'transcript': Uses ASR/transcript-based detection\n@default 'audio' (audio detection)", - "enum": [ - "audio", - "transcript" - ] + "description": "This is the key to replace." + }, + "value": { + "type": "string", + "description": "This is the value that will replace the match.", + "maxLength": 1000 } }, "required": [ - "provider" + "type", + "key", + "value" ] }, - "TwilioVoicemailDetectionPlan": { + "RegexReplacement": { "type": "object", "properties": { - "provider": { + "type": { "type": "string", - "description": "This is the provider to use for voicemail detection.", + "description": "This is the regex replacement type. You can use this to replace a word or phrase that matches a pattern.\n\nUsage:\n- Replace all numbers with \"some number\": { type: 'regex', regex: '\\\\d+', value: 'some number' }\n- Replace email addresses with \"[EMAIL]\": { type: 'regex', regex: '\\\\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\\\.[A-Z|a-z]{2,}\\\\b', value: '[EMAIL]' }\n- Replace phone numbers with a formatted version: { type: 'regex', regex: '(\\\\d{3})(\\\\d{3})(\\\\d{4})', value: '($1) $2-$3' }\n- Replace all instances of \"color\" or \"colour\" with \"hue\": { type: 'regex', regex: 'colou?r', value: 'hue' }\n- Capitalize the first letter of every sentence: { type: 'regex', regex: '(?<=\\\\. |^)[a-z]', value: (match) => match.toUpperCase() }", "enum": [ - "twilio" + "regex" ] }, - "voicemailDetectionTypes": { - "type": "array", - "description": "These are the AMD messages from Twilio that are considered as voicemail. Default is ['machine_end_beep', 'machine_end_silence'].\n\n@default {Array} ['machine_end_beep', 'machine_end_silence']", - "enum": [ - "machine_start", - "human", - "fax", - "unknown", - "machine_end_beep", - "machine_end_silence", - "machine_end_other" - ], - "example": [ - "machine_end_beep", - "machine_end_silence" - ], + "regex": { + "type": "string", + "description": "This is the regex pattern to replace.\n\nNote:\n- This works by using the `string.replace` method in Node.JS. Eg. `\"hello there\".replace(/hello/g, \"hi\")` will return `\"hi there\"`.\n\nHot tip:\n- In JavaScript, escape `\\` when sending the regex pattern. Eg. `\"hello\\sthere\"` will be sent over the wire as `\"hellosthere\"`. Send `\"hello\\\\sthere\"` instead." + }, + "options": { + "description": "These are the options for the regex replacement. Defaults to all disabled.\n\n@default []", + "type": "array", "items": { - "type": "string", - "enum": [ - "machine_start", - "human", - "fax", - "unknown", - "machine_end_beep", - "machine_end_silence", - "machine_end_other" - ] + "$ref": "#/components/schemas/RegexOption" } }, + "value": { + "type": "string", + "description": "This is the value that will replace the match.", + "maxLength": 1000 + } + }, + "required": [ + "type", + "regex", + "value" + ] + }, + "FormatPlan": { + "type": "object", + "properties": { "enabled": { "type": "boolean", - "description": "This sets whether the assistant should detect voicemail. Defaults to true.\n\n@default true" - }, - "machineDetectionTimeout": { - "type": "number", - "description": "The number of seconds that Twilio should attempt to perform answering machine detection before timing out and returning AnsweredBy as unknown. Default is 30 seconds.\n\nIncreasing this value will provide the engine more time to make a determination. This can be useful when DetectMessageEnd is provided in the MachineDetection parameter and there is an expectation of long answering machine greetings that can exceed 30 seconds.\n\nDecreasing this value will reduce the amount of time the engine has to make a determination. This can be particularly useful when the Enable option is provided in the MachineDetection parameter and you want to limit the time for initial detection.\n\nCheck the [Twilio docs](https://www.twilio.com/docs/voice/answering-machine-detection#optional-api-tuning-parameters) for more info.\n\n@default 30", - "minimum": 3, - "maximum": 59 + "description": "This determines whether the chunk is formatted before being sent to the voice provider. This helps with enunciation. This includes phone numbers, emails and addresses. Default `true`.\n\nUsage:\n- To rely on the voice provider's formatting logic, set this to `false`.\n\nIf `voice.chunkPlan.enabled` is `false`, this is automatically `false` since there's no chunk to format.\n\n@default true", + "example": true }, - "machineDetectionSpeechThreshold": { + "numberToDigitsCutoff": { "type": "number", - "description": "The number of milliseconds that is used as the measuring stick for the length of the speech activity. Durations lower than this value will be interpreted as a human, longer as a machine. Default is 2400 milliseconds.\n\nIncreasing this value will reduce the chance of a False Machine (detected machine, actually human) for a long human greeting (e.g., a business greeting) but increase the time it takes to detect a machine.\n\nDecreasing this value will reduce the chances of a False Human (detected human, actually machine) for short voicemail greetings. The value of this parameter may need to be reduced by more than 1000ms to detect very short voicemail greetings. A reduction of that significance can result in increased False Machine detections. Adjusting the MachineDetectionSpeechEndThreshold is likely the better approach for short voicemails. Decreasing MachineDetectionSpeechThreshold will also reduce the time it takes to detect a machine.\n\nCheck the [Twilio docs](https://www.twilio.com/docs/voice/answering-machine-detection#optional-api-tuning-parameters) for more info.\n\n@default 2400", - "minimum": 1000, - "maximum": 6000 + "description": "This is the cutoff after which a number is converted to individual digits instead of being spoken as words.\n\nExample:\n- If cutoff 2025, \"12345\" is converted to \"1 2 3 4 5\" while \"1200\" is converted to \"twelve hundred\".\n\nUsage:\n- If your use case doesn't involve IDs like zip codes, set this to a high value.\n- If your use case involves IDs that are shorter than 5 digits, set this to a lower value.\n\n@default 2025", + "minimum": 0, + "example": 2025 }, - "machineDetectionSpeechEndThreshold": { - "type": "number", - "description": "The number of milliseconds of silence after speech activity at which point the speech activity is considered complete. Default is 1200 milliseconds.\n\nIncreasing this value will typically be used to better address the short voicemail greeting scenarios. For short voicemails, there is typically 1000-2000ms of audio followed by 1200-2400ms of silence and then additional audio before the beep. Increasing the MachineDetectionSpeechEndThreshold to ~2500ms will treat the 1200-2400ms of silence as a gap in the greeting but not the end of the greeting and will result in a machine detection. The downsides of such a change include:\n- Increasing the delay for human detection by the amount you increase this parameter, e.g., a change of 1200ms to 2500ms increases human detection delay by 1300ms.\n- Cases where a human has two utterances separated by a period of silence (e.g. a \"Hello\", then 2000ms of silence, and another \"Hello\") may be interpreted as a machine.\n\nDecreasing this value will result in faster human detection. The consequence is that it can lead to increased False Human (detected human, actually machine) detections because a silence gap in a voicemail greeting (not necessarily just in short voicemail scenarios) can be incorrectly interpreted as the end of speech.\n\nCheck the [Twilio docs](https://www.twilio.com/docs/voice/answering-machine-detection#optional-api-tuning-parameters) for more info.\n\n@default 1200", - "minimum": 500, - "maximum": 5000 + "replacements": { + "type": "array", + "description": "These are the custom replacements you can make to the chunk before it is sent to the voice provider.\n\nUsage:\n- To replace a specific word or phrase with a different word or phrase, use the `ExactReplacement` type. Eg. `{ type: 'exact', key: 'hello', value: 'hi' }`\n- To replace a word or phrase that matches a pattern, use the `RegexReplacement` type. Eg. `{ type: 'regex', regex: '\\\\b[a-zA-Z]{5}\\\\b', value: 'hi' }`\n\n@default []", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/ExactReplacement", + "title": "ExactReplacement" + }, + { + "$ref": "#/components/schemas/RegexReplacement", + "title": "RegexReplacement" + } + ] + } }, - "machineDetectionSilenceTimeout": { - "type": "number", - "description": "The number of milliseconds of initial silence after which an unknown AnsweredBy result will be returned. Default is 5000 milliseconds.\n\nIncreasing this value will result in waiting for a longer period of initial silence before returning an 'unknown' AMD result.\n\nDecreasing this value will result in waiting for a shorter period of initial silence before returning an 'unknown' AMD result.\n\nCheck the [Twilio docs](https://www.twilio.com/docs/voice/answering-machine-detection#optional-api-tuning-parameters) for more info.\n\n@default 5000", - "minimum": 2000, - "maximum": 10000 + "formattersEnabled": { + "type": "array", + "description": "List of formatters to apply. If not provided, all default formatters will be applied.\nIf provided, only the specified formatters will be applied.\nNote: Some essential formatters like angle bracket removal will always be applied.\n@default undefined", + "enum": [ + "markdown", + "asterisk", + "quote", + "dash", + "newline", + "colon", + "acronym", + "dollarAmount", + "email", + "date", + "time", + "distance", + "unit", + "percentage", + "phoneNumber", + "number", + "stripAsterisk" + ], + "items": { + "type": "string", + "enum": [ + "markdown", + "asterisk", + "quote", + "dash", + "newline", + "colon", + "acronym", + "dollarAmount", + "email", + "date", + "time", + "distance", + "unit", + "percentage", + "phoneNumber", + "number", + "stripAsterisk" + ] + } } - }, - "required": [ - "provider" - ] + } }, - "VapiVoicemailDetectionPlan": { + "ChunkPlan": { "type": "object", "properties": { - "beepMaxAwaitSeconds": { + "enabled": { + "type": "boolean", + "description": "This determines whether the model output is chunked before being sent to the voice provider. Default `true`.\n\nUsage:\n- To rely on the voice provider's audio generation logic, set this to `false`.\n- If seeing issues with quality, set this to `true`.\n\nIf disabled, Vapi-provided audio control tokens like will not work.\n\n@default true", + "example": true + }, + "minCharacters": { "type": "number", - "description": "This is the maximum duration from the start of the call that we will wait for a voicemail beep, before speaking our message\n\n- If we detect a voicemail beep before this, we will speak the message at that point.\n\n- Setting too low a value means that the bot will start speaking its voicemail message too early. If it does so before the actual beep, it will get cut off. You should definitely tune this to your use case.\n\n@default 30\n@min 0\n@max 60", - "minimum": 0, - "maximum": 30, - "default": 30 + "description": "This is the minimum number of characters in a chunk.\n\nUsage:\n- To increase quality, set this to a higher value.\n- To decrease latency, set this to a lower value.\n\n@default 30", + "minimum": 1, + "maximum": 80, + "example": 30 }, - "provider": { - "type": "string", - "description": "This is the provider to use for voicemail detection.", + "punctuationBoundaries": { + "type": "array", + "description": "These are the punctuations that are considered valid boundaries for a chunk to be created.\n\nUsage:\n- To increase quality, constrain to fewer boundaries.\n- To decrease latency, enable all.\n\nDefault is automatically set to balance the trade-off between quality and latency based on the provider.", "enum": [ - "vapi" - ] + "。", + ",", + ".", + "!", + "?", + ";", + ")", + "،", + "۔", + "।", + "॥", + "|", + "||", + ",", + ":" + ], + "example": [ + "。", + ",", + ".", + "!", + "?", + ";", + "،", + "۔", + "।", + "॥", + "|", + "||", + ",", + ":" + ], + "items": { + "type": "string", + "enum": [ + "。", + ",", + ".", + "!", + "?", + ";", + ")", + "،", + "۔", + "।", + "॥", + "|", + "||", + ",", + ":" + ] + } }, - "backoffPlan": { - "description": "This is the backoff plan for the voicemail detection.", + "formatPlan": { + "description": "This is the plan for formatting the chunk before it is sent to the voice provider.", "allOf": [ { - "$ref": "#/components/schemas/VoicemailDetectionBackoffPlan" + "$ref": "#/components/schemas/FormatPlan" } ] - }, - "type": { - "type": "string", - "description": "This is the detection type to use for voicemail detection.\n- 'audio': Uses native audio models (default)\n- 'transcript': Uses ASR/transcript-based detection\n@default 'audio' (audio detection)", - "enum": [ - "audio", - "transcript" - ] } - }, - "required": [ - "provider" - ] + } }, - "SQLInjectionSecurityFilter": { + "FallbackPlan": { "type": "object", "properties": { - "type": { - "type": "string", - "description": "The type of security threat to filter.", - "enum": [ - "sql-injection" - ] + "voices": { + "type": "array", + "description": "This is the list of voices to fallback to in the event that the primary voice provider fails.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/FallbackAzureVoice", + "title": "Azure" + }, + { + "$ref": "#/components/schemas/FallbackCartesiaVoice", + "title": "Cartesia" + }, + { + "$ref": "#/components/schemas/FallbackHumeVoice", + "title": "Hume" + }, + { + "$ref": "#/components/schemas/FallbackCustomVoice", + "title": "CustomVoice" + }, + { + "$ref": "#/components/schemas/FallbackDeepgramVoice", + "title": "Deepgram" + }, + { + "$ref": "#/components/schemas/FallbackElevenLabsVoice", + "title": "ElevenLabs" + }, + { + "$ref": "#/components/schemas/FallbackVapiVoice", + "title": "Vapi" + }, + { + "$ref": "#/components/schemas/FallbackLMNTVoice", + "title": "LMNT" + }, + { + "$ref": "#/components/schemas/FallbackOpenAIVoice", + "title": "OpenAI" + }, + { + "$ref": "#/components/schemas/FallbackPlayHTVoice", + "title": "PlayHT" + }, + { + "$ref": "#/components/schemas/FallbackWellSaidVoice", + "title": "WellSaid" + }, + { + "$ref": "#/components/schemas/FallbackRimeAIVoice", + "title": "RimeAI" + }, + { + "$ref": "#/components/schemas/FallbackSmallestAIVoice", + "title": "Smallest AI" + }, + { + "$ref": "#/components/schemas/FallbackTavusVoice", + "title": "TavusVoice" + }, + { + "$ref": "#/components/schemas/FallbackNeuphonicVoice", + "title": "Neuphonic" + }, + { + "$ref": "#/components/schemas/FallbackSesameVoice", + "title": "Sesame" + }, + { + "$ref": "#/components/schemas/FallbackInworldVoice", + "title": "Inworld" + }, + { + "$ref": "#/components/schemas/FallbackXaiVoice", + "title": "xAI" + }, + { + "$ref": "#/components/schemas/FallbackMicrosoftVoice", + "title": "Microsoft" + } + ] + } } }, "required": [ - "type" + "voices" ] }, - "XSSSecurityFilter": { + "AzureVoice": { "type": "object", "properties": { - "type": { + "cachingEnabled": { + "type": "boolean", + "description": "This is the flag to toggle voice caching for the assistant.", + "example": true, + "default": true + }, + "provider": { "type": "string", - "description": "The type of security threat to filter.", + "description": "This is the voice provider that will be used.", "enum": [ - "xss" + "azure" + ] + }, + "voiceId": { + "description": "This is the provider-specific ID that will be used.", + "oneOf": [ + { + "type": "string", + "enum": [ + "andrew", + "brian", + "emma" + ], + "title": "Preset Voice Options" + }, + { + "type": "string", + "title": "Azure Voice ID" + } + ] + }, + "chunkPlan": { + "description": "This is the plan for chunking the model output before it is sent to the voice provider.", + "allOf": [ + { + "$ref": "#/components/schemas/ChunkPlan" + } + ] + }, + "speed": { + "type": "number", + "description": "This is the speed multiplier that will be used.", + "minimum": 0.5, + "maximum": 2 + }, + "fallbackPlan": { + "description": "This is the plan for voice provider fallbacks in the event that the primary voice provider fails.", + "allOf": [ + { + "$ref": "#/components/schemas/FallbackPlan" + } ] } }, "required": [ - "type" + "provider", + "voiceId" ] }, - "SSRFSecurityFilter": { + "CartesiaExperimentalControls": { "type": "object", "properties": { - "type": { + "speed": { + "oneOf": [ + { + "type": "string", + "enum": [ + "slowest", + "slow", + "normal", + "fast", + "fastest" + ], + "example": "normal" + }, + { + "type": "number", + "minimum": -1, + "maximum": 1, + "example": 0.5 + } + ] + }, + "emotion": { "type": "string", - "description": "The type of security threat to filter.", "enum": [ - "ssrf" + "anger:lowest", + "anger:low", + "anger:high", + "anger:highest", + "positivity:lowest", + "positivity:low", + "positivity:high", + "positivity:highest", + "surprise:lowest", + "surprise:low", + "surprise:high", + "surprise:highest", + "sadness:lowest", + "sadness:low", + "sadness:high", + "sadness:highest", + "curiosity:lowest", + "curiosity:low", + "curiosity:high", + "curiosity:highest" + ], + "example": [ + "happiness:high" ] } - }, - "required": [ - "type" - ] + } }, - "RCESecurityFilter": { + "CartesiaGenerationConfigExperimental": { "type": "object", "properties": { - "type": { - "type": "string", - "description": "The type of security threat to filter.", - "enum": [ - "rce" - ] + "accentLocalization": { + "type": "integer", + "description": "Toggle accent localization for sonic-3: 0 (disabled, default) or 1 (enabled). When enabled, the voice adapts to match the transcript language accent while preserving vocal characteristics.", + "example": 0, + "minimum": 0, + "maximum": 1, + "default": 0 } - }, - "required": [ - "type" - ] + } }, - "PromptInjectionSecurityFilter": { + "CartesiaGenerationConfig": { "type": "object", "properties": { - "type": { - "type": "string", - "description": "The type of security threat to filter.", - "enum": [ - "prompt-injection" + "speed": { + "type": "number", + "description": "Fine-grained speed control for sonic-3. Only available for sonic-3 model.", + "example": 1, + "minimum": 0.6, + "maximum": 1.5, + "default": 1 + }, + "volume": { + "type": "number", + "description": "Fine-grained volume control for sonic-3. Only available for sonic-3 model.", + "example": 1, + "minimum": 0.5, + "maximum": 2, + "default": 1 + }, + "experimental": { + "description": "Experimental model controls for sonic-3. These are subject to breaking changes.", + "allOf": [ + { + "$ref": "#/components/schemas/CartesiaGenerationConfigExperimental" + } ] } - }, - "required": [ - "type" - ] + } }, - "RegexSecurityFilter": { + "CartesiaVoice": { "type": "object", "properties": { - "type": { + "cachingEnabled": { + "type": "boolean", + "description": "This is the flag to toggle voice caching for the assistant.", + "example": true, + "default": true + }, + "provider": { "type": "string", - "description": "The type of security threat to filter.", + "description": "This is the voice provider that will be used.", "enum": [ - "regex" + "cartesia" ] }, - "regex": { + "voiceId": { "type": "string", - "description": "The regex pattern to filter.", - "example": "badword1|badword2" - } - }, - "required": [ - "type", - "regex" - ] - }, - "CreateAssistantDTO": { - "type": "object", - "properties": { - "transcriber": { - "description": "These are the options for the assistant's transcriber.", - "oneOf": [ - { - "$ref": "#/components/schemas/AssemblyAITranscriber", - "title": "AssemblyAITranscriber" - }, - { - "$ref": "#/components/schemas/AzureSpeechTranscriber", - "title": "AzureSpeechTranscriber" - }, - { - "$ref": "#/components/schemas/CustomTranscriber", - "title": "CustomTranscriber" - }, - { - "$ref": "#/components/schemas/DeepgramTranscriber", - "title": "DeepgramTranscriber" - }, + "description": "The ID of the particular voice you want to use." + }, + "model": { + "type": "string", + "description": "This is the model that will be used. This is optional and will default to the correct model for the voiceId.", + "enum": [ + "sonic-3.5", + "sonic-3.5-2026-05-04", + "sonic-3", + "sonic-3-2026-01-12", + "sonic-3-2025-10-27", + "sonic-2", + "sonic-2-2025-06-11", + "sonic-english", + "sonic-multilingual", + "sonic-preview", + "sonic" + ], + "example": "sonic-english" + }, + "language": { + "type": "string", + "description": "This is the language that will be used. This is optional and will default to the correct language for the voiceId.", + "enum": [ + "ar", + "bg", + "bn", + "cs", + "da", + "de", + "el", + "en", + "es", + "fi", + "fr", + "gu", + "he", + "hi", + "hr", + "hu", + "id", + "it", + "ja", + "ka", + "kn", + "ko", + "ml", + "mr", + "ms", + "nl", + "no", + "pa", + "pl", + "pt", + "ro", + "ru", + "sk", + "sv", + "ta", + "te", + "th", + "tl", + "tr", + "uk", + "vi", + "zh" + ], + "example": "en" + }, + "experimentalControls": { + "description": "Experimental controls for Cartesia voice generation", + "allOf": [ { - "$ref": "#/components/schemas/ElevenLabsTranscriber", - "title": "ElevenLabsTranscriber" - }, + "$ref": "#/components/schemas/CartesiaExperimentalControls" + } + ] + }, + "generationConfig": { + "description": "Generation config for fine-grained control of sonic-3 voice output (speed, volume, and experimental controls). Only available for sonic-3 model.", + "allOf": [ { - "$ref": "#/components/schemas/GladiaTranscriber", - "title": "GladiaTranscriber" - }, + "$ref": "#/components/schemas/CartesiaGenerationConfig" + } + ] + }, + "pronunciationDictId": { + "type": "string", + "description": "Pronunciation dictionary ID for sonic-3. Allows custom pronunciations for specific words. Only available for sonic-3 model.", + "example": "dict_abc123" + }, + "chunkPlan": { + "description": "This is the plan for chunking the model output before it is sent to the voice provider.", + "allOf": [ { - "$ref": "#/components/schemas/GoogleTranscriber", - "title": "GoogleTranscriber" - }, + "$ref": "#/components/schemas/ChunkPlan" + } + ] + }, + "fallbackPlan": { + "description": "This is the plan for voice provider fallbacks in the event that the primary voice provider fails.", + "allOf": [ { - "$ref": "#/components/schemas/SpeechmaticsTranscriber", - "title": "SpeechmaticsTranscriber" - }, + "$ref": "#/components/schemas/FallbackPlan" + } + ] + } + }, + "required": [ + "provider", + "voiceId" + ] + }, + "CustomVoice": { + "type": "object", + "properties": { + "cachingEnabled": { + "type": "boolean", + "description": "This is the flag to toggle voice caching for the assistant.", + "example": true, + "default": true + }, + "provider": { + "type": "string", + "description": "This is the voice provider that will be used. Use `custom-voice` for providers that are not natively supported.", + "enum": [ + "custom-voice" + ] + }, + "voiceId": { + "type": "string", + "description": "This is the provider-specific ID that will be used. This is passed in the voice request payload to identify the voice to use." + }, + "chunkPlan": { + "description": "This is the plan for chunking the model output before it is sent to the voice provider.", + "allOf": [ { - "$ref": "#/components/schemas/TalkscriberTranscriber", - "title": "TalkscriberTranscriber" - }, + "$ref": "#/components/schemas/ChunkPlan" + } + ] + }, + "server": { + "description": "This is where the voice request will be sent.\n\nRequest Example:\n\nPOST https://{server.url}\nContent-Type: application/json\n\n{\n \"message\": {\n \"type\": \"voice-request\",\n \"text\": \"Hello, world!\",\n \"sampleRate\": 24000,\n ...other metadata about the call...\n }\n}\n\nResponse Expected: 1-channel 16-bit raw PCM audio at the sample rate specified in the request. Here is how the response will be piped to the transport:\n```\nresponse.on('data', (chunk: Buffer) => {\n outputStream.write(chunk);\n});\n```", + "allOf": [ { - "$ref": "#/components/schemas/OpenAITranscriber", - "title": "OpenAITranscriber" - }, + "$ref": "#/components/schemas/Server" + } + ] + }, + "fallbackPlan": { + "description": "This is the plan for voice provider fallbacks in the event that the primary voice provider fails.", + "allOf": [ { - "$ref": "#/components/schemas/CartesiaTranscriber", - "title": "CartesiaTranscriber" + "$ref": "#/components/schemas/FallbackPlan" } ] + } + }, + "required": [ + "provider", + "server" + ] + }, + "DeepgramVoice": { + "type": "object", + "properties": { + "cachingEnabled": { + "type": "boolean", + "description": "This is the flag to toggle voice caching for the assistant.", + "example": true, + "default": true + }, + "provider": { + "type": "string", + "description": "This is the voice provider that will be used.", + "enum": [ + "deepgram" + ] + }, + "voiceId": { + "type": "string", + "description": "This is the provider-specific ID that will be used.", + "enum": [ + "asteria", + "luna", + "stella", + "athena", + "hera", + "orion", + "arcas", + "perseus", + "angus", + "orpheus", + "helios", + "zeus", + "thalia", + "andromeda", + "helena", + "apollo", + "arcas", + "aries", + "amalthea", + "asteria", + "athena", + "atlas", + "aurora", + "callista", + "cora", + "cordelia", + "delia", + "draco", + "electra", + "harmonia", + "hera", + "hermes", + "hyperion", + "iris", + "janus", + "juno", + "jupiter", + "luna", + "mars", + "minerva", + "neptune", + "odysseus", + "ophelia", + "orion", + "orpheus", + "pandora", + "phoebe", + "pluto", + "saturn", + "selene", + "theia", + "vesta", + "zeus", + "celeste", + "estrella", + "nestor", + "sirio", + "carina", + "alvaro", + "diana", + "aquila", + "selena", + "javier", + "viktoria", + "kara", + "fabian", + "julius", + "lara", + "elara", + "aurelia" + ], + "title": "This is the Deepgram Voice ID" }, "model": { - "description": "These are the options for the assistant's LLM.", - "oneOf": [ - { - "$ref": "#/components/schemas/AnthropicModel", - "title": "Anthropic" - }, - { - "$ref": "#/components/schemas/AnyscaleModel", - "title": "Anyscale" - }, - { - "$ref": "#/components/schemas/CerebrasModel", - "title": "Cerebras" - }, - { - "$ref": "#/components/schemas/CustomLLMModel", - "title": "CustomLLM" - }, - { - "$ref": "#/components/schemas/DeepInfraModel", - "title": "DeepInfra" - }, - { - "$ref": "#/components/schemas/DeepSeekModel", - "title": "DeepSeek" - }, - { - "$ref": "#/components/schemas/GoogleModel", - "title": "Google" - }, - { - "$ref": "#/components/schemas/GroqModel", - "title": "Groq" - }, - { - "$ref": "#/components/schemas/InflectionAIModel", - "title": "InflectionAI" - }, - { - "$ref": "#/components/schemas/OpenAIModel", - "title": "OpenAI" - }, - { - "$ref": "#/components/schemas/OpenRouterModel", - "title": "OpenRouter" - }, - { - "$ref": "#/components/schemas/PerplexityAIModel", - "title": "PerplexityAI" - }, - { - "$ref": "#/components/schemas/TogetherAIModel", - "title": "Together" - }, + "type": "string", + "description": "This is the model that will be used. Defaults to 'aura-2' when not specified.", + "enum": [ + "aura", + "aura-2" + ], + "example": "aura-2" + }, + "mipOptOut": { + "type": "boolean", + "description": "If set to true, this will add mip_opt_out=true as a query parameter of all API requests. See https://developers.deepgram.com/docs/the-deepgram-model-improvement-partnership-program#want-to-opt-out\n\nThis will only be used if you are using your own Deepgram API key.\n\n@default false", + "example": false, + "default": false + }, + "chunkPlan": { + "description": "This is the plan for chunking the model output before it is sent to the voice provider.", + "allOf": [ { - "$ref": "#/components/schemas/XaiModel", - "title": "XAI" + "$ref": "#/components/schemas/ChunkPlan" } ] }, - "voice": { - "description": "These are the options for the assistant's voice.", - "oneOf": [ - { - "$ref": "#/components/schemas/AzureVoice", - "title": "AzureVoice" - }, - { - "$ref": "#/components/schemas/CartesiaVoice", - "title": "CartesiaVoice" - }, - { - "$ref": "#/components/schemas/CustomVoice", - "title": "CustomVoice" - }, - { - "$ref": "#/components/schemas/DeepgramVoice", - "title": "DeepgramVoice" - }, - { - "$ref": "#/components/schemas/ElevenLabsVoice", - "title": "ElevenLabsVoice" - }, - { - "$ref": "#/components/schemas/HumeVoice", - "title": "HumeVoice" - }, - { - "$ref": "#/components/schemas/LMNTVoice", - "title": "LMNTVoice" - }, - { - "$ref": "#/components/schemas/NeuphonicVoice", - "title": "NeuphonicVoice" - }, - { - "$ref": "#/components/schemas/OpenAIVoice", - "title": "OpenAIVoice" - }, - { - "$ref": "#/components/schemas/PlayHTVoice", - "title": "PlayHTVoice" - }, - { - "$ref": "#/components/schemas/RimeAIVoice", - "title": "RimeAIVoice" - }, - { - "$ref": "#/components/schemas/SmallestAIVoice", - "title": "SmallestAIVoice" - }, - { - "$ref": "#/components/schemas/TavusVoice", - "title": "TavusVoice" - }, - { - "$ref": "#/components/schemas/VapiVoice", - "title": "VapiVoice" - }, - { - "$ref": "#/components/schemas/SesameVoice", - "title": "SesameVoice" - }, - { - "$ref": "#/components/schemas/InworldVoice", - "title": "InworldVoice" - }, + "fallbackPlan": { + "description": "This is the plan for voice provider fallbacks in the event that the primary voice provider fails.", + "allOf": [ { - "$ref": "#/components/schemas/MinimaxVoice", - "title": "MinimaxVoice" + "$ref": "#/components/schemas/FallbackPlan" } ] - }, - "firstMessage": { + } + }, + "required": [ + "provider", + "voiceId" + ] + }, + "ElevenLabsPronunciationDictionaryLocator": { + "type": "object", + "properties": { + "pronunciationDictionaryId": { "type": "string", - "description": "This is the first message that the assistant will say. This can also be a URL to a containerized audio file (mp3, wav, etc.).\n\nIf unspecified, assistant will wait for user to speak and use the model to respond once they speak.", - "example": "Hello! How can I help you today?" + "description": "This is the ID of the pronunciation dictionary to use.", + "title": "This is the ElevenLabs Pronunciation Dictionary ID" }, - "firstMessageInterruptionsEnabled": { + "versionId": { + "type": "string", + "description": "This is the version ID of the pronunciation dictionary to use.\n\nOmit to use the dictionary's latest version.", + "title": "This is the ElevenLabs Pronunciation Dictionary Version ID" + } + }, + "required": [ + "pronunciationDictionaryId" + ] + }, + "ElevenLabsVoice": { + "type": "object", + "properties": { + "cachingEnabled": { "type": "boolean", - "default": false + "description": "This is the flag to toggle voice caching for the assistant.", + "example": true, + "default": true }, - "firstMessageMode": { + "provider": { "type": "string", - "description": "This is the mode for the first message. Default is 'assistant-speaks-first'.\n\nUse:\n- 'assistant-speaks-first' to have the assistant speak first.\n- 'assistant-waits-for-user' to have the assistant wait for the user to speak first.\n- 'assistant-speaks-first-with-model-generated-message' to have the assistant speak first with a message generated by the model based on the conversation state. (`assistant.model.messages` at call start, `call.messages` at squad transfer points).\n\n@default 'assistant-speaks-first'", + "description": "This is the voice provider that will be used.", "enum": [ - "assistant-speaks-first", - "assistant-speaks-first-with-model-generated-message", - "assistant-waits-for-user" - ], - "example": "assistant-speaks-first" + "11labs" + ] }, - "voicemailDetection": { - "description": "These are the settings to configure or disable voicemail detection. Alternatively, voicemail detection can be configured using the model.tools=[VoicemailTool].\nThis uses Twilio's built-in detection while the VoicemailTool relies on the model to detect if a voicemail was reached.\nYou can use neither of them, one of them, or both of them. By default, Twilio built-in detection is enabled while VoicemailTool is not.", + "voiceId": { + "description": "This is the provider-specific ID that will be used. Ensure the Voice is present in your 11Labs Voice Library.", "oneOf": [ { - "$ref": "#/components/schemas/GoogleVoicemailDetectionPlan", - "title": "Google" - }, - { - "$ref": "#/components/schemas/OpenAIVoicemailDetectionPlan", - "title": "OpenAI" - }, - { - "$ref": "#/components/schemas/TwilioVoicemailDetectionPlan", - "title": "Twilio" + "type": "string", + "enum": [ + "burt", + "marissa", + "andrea", + "sarah", + "phillip", + "steve", + "joseph", + "myra", + "paula", + "ryan", + "drew", + "paul", + "mrb", + "matilda", + "mark" + ], + "title": "Preset Voice Options" }, { - "$ref": "#/components/schemas/VapiVoicemailDetectionPlan", - "title": "Vapi" + "type": "string", + "title": "11Labs Voice ID" } ] }, - "clientMessages": { - "type": "array", - "enum": [ - "conversation-update", - "function-call", - "function-call-result", - "hang", - "language-changed", - "metadata", - "model-output", - "speech-update", - "status-update", - "transcript", - "tool-calls", - "tool-calls-result", - "tool.completed", - "transfer-update", - "user-interrupted", - "voice-input", - "workflow.node.started" - ], - "example": [ - "conversation-update", - "function-call", - "hang", - "model-output", - "speech-update", - "status-update", - "transfer-update", - "transcript", - "tool-calls", - "user-interrupted", - "voice-input", - "workflow.node.started" - ], - "description": "These are the messages that will be sent to your Client SDKs. Default is conversation-update,function-call,hang,model-output,speech-update,status-update,transfer-update,transcript,tool-calls,user-interrupted,voice-input,workflow.node.started. You can check the shape of the messages in ClientMessage schema.", - "items": { - "type": "string", - "enum": [ - "conversation-update", - "function-call", - "function-call-result", - "hang", - "language-changed", - "metadata", - "model-output", - "speech-update", - "status-update", - "transcript", - "tool-calls", - "tool-calls-result", - "tool.completed", - "transfer-update", - "user-interrupted", - "voice-input", - "workflow.node.started" - ] - } + "stability": { + "type": "number", + "description": "Defines the stability for voice settings.", + "minimum": 0, + "maximum": 1, + "example": 0.5 }, - "serverMessages": { - "type": "array", - "enum": [ - "conversation-update", - "end-of-call-report", - "function-call", - "hang", - "language-changed", - "language-change-detected", - "model-output", - "phone-call-control", - "speech-update", - "status-update", - "transcript", - "transcript[transcriptType=\"final\"]", - "tool-calls", - "transfer-destination-request", - "handoff-destination-request", - "transfer-update", - "user-interrupted", - "voice-input", - "chat.created", - "chat.deleted", - "session.created", - "session.updated", - "session.deleted" - ], - "example": [ - "conversation-update", - "end-of-call-report", - "function-call", - "hang", - "speech-update", - "status-update", - "tool-calls", - "transfer-destination-request", - "handoff-destination-request", - "user-interrupted" - ], - "description": "These are the messages that will be sent to your Server URL. Default is conversation-update,end-of-call-report,function-call,hang,speech-update,status-update,tool-calls,transfer-destination-request,handoff-destination-request,user-interrupted. You can check the shape of the messages in ServerMessage schema.", - "items": { - "type": "string", - "enum": [ - "conversation-update", - "end-of-call-report", - "function-call", - "hang", - "language-changed", - "language-change-detected", - "model-output", - "phone-call-control", - "speech-update", - "status-update", - "transcript", - "transcript[transcriptType=\"final\"]", - "tool-calls", - "transfer-destination-request", - "handoff-destination-request", - "transfer-update", - "user-interrupted", - "voice-input", - "chat.created", - "chat.deleted", - "session.created", - "session.updated", - "session.deleted" - ] - } + "similarityBoost": { + "type": "number", + "description": "Defines the similarity boost for voice settings.", + "minimum": 0, + "maximum": 1, + "example": 0.75 }, - "maxDurationSeconds": { + "style": { "type": "number", - "description": "This is the maximum number of seconds that the call will last. When the call reaches this duration, it will be ended.\n\n@default 600 (10 minutes)", - "minimum": 10, - "maximum": 43200, - "example": 600 + "description": "Defines the style for voice settings.", + "minimum": 0, + "maximum": 1, + "example": 0 }, - "backgroundSound": { - "description": "This is the background sound in the call. Default for phone calls is 'office' and default for web calls is 'off'.\nYou can also provide a custom sound by providing a URL to an audio file.", - "oneOf": [ - { - "type": "enum", - "enum": [ - "off", - "office" - ], - "example": "office" - }, - { - "type": "string", - "format": "uri", - "example": "https://www.soundjay.com/ambient/sounds/people-in-lounge-1.mp3" - } - ] + "useSpeakerBoost": { + "type": "boolean", + "description": "Defines the use speaker boost for voice settings.", + "example": false }, - "modelOutputInMessagesEnabled": { + "speed": { + "type": "number", + "description": "Defines the speed for voice settings.", + "minimum": 0.7, + "maximum": 1.2, + "example": 0.9 + }, + "optimizeStreamingLatency": { + "type": "number", + "description": "Defines the optimize streaming latency for voice settings. Defaults to 3.", + "minimum": 0, + "maximum": 4, + "example": 3 + }, + "enableSsmlParsing": { "type": "boolean", - "description": "This determines whether the model's output is used in conversation history rather than the transcription of assistant's speech.\n\nDefault `false` while in beta.\n\n@default false", + "description": "This enables the use of https://elevenlabs.io/docs/speech-synthesis/prompting#pronunciation. Defaults to false to save latency.\n\n@default false", "example": false }, - "transportConfigurations": { - "type": "array", - "description": "These are the configurations to be passed to the transport providers of assistant's calls, like Twilio. You can store multiple configurations for different transport providers. For a call, only the configuration matching the call transport provider is used.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/TransportConfigurationTwilio", - "title": "Twilio" - } - ] - } + "autoMode": { + "type": "boolean", + "description": "Defines the auto mode for voice settings. Defaults to false.", + "example": false }, - "observabilityPlan": { - "description": "This is the plan for observability of assistant's calls.\n\nCurrently, only Langfuse is supported.", - "oneOf": [ - { - "$ref": "#/components/schemas/LangfuseObservabilityPlan", - "title": "Langfuse" - } + "model": { + "type": "string", + "description": "This is the model that will be used. Defaults to 'eleven_turbo_v2' if not specified.", + "enum": [ + "eleven_multilingual_v2", + "eleven_turbo_v2", + "eleven_turbo_v2_5", + "eleven_flash_v2", + "eleven_flash_v2_5", + "eleven_monolingual_v1", + "eleven_v3" ], + "example": "eleven_turbo_v2_5" + }, + "language": { + "type": "string", + "description": "This is the language (ISO 639-1) that is enforced for the model. Currently only Turbo v2.5 supports language enforcement. For other models, an error will be returned if language code is provided." + }, + "chunkPlan": { + "description": "This is the plan for chunking the model output before it is sent to the voice provider.", "allOf": [ { - "$ref": "#/components/schemas/LangfuseObservabilityPlan" + "$ref": "#/components/schemas/ChunkPlan" } ] }, - "credentials": { + "pronunciationDictionaryLocators": { + "description": "This is the pronunciation dictionary locators to use.", "type": "array", - "description": "These are dynamic credentials that will be used for the assistant calls. By default, all the credentials are available for use in the call but you can supplement an additional credentials using this. Dynamic credentials override existing credentials.", "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/CreateAnthropicCredentialDTO", - "title": "AnthropicCredential" - }, - { - "$ref": "#/components/schemas/CreateAnyscaleCredentialDTO", - "title": "AnyscaleCredential" - }, - { - "$ref": "#/components/schemas/CreateAssemblyAICredentialDTO", - "title": "AssemblyAICredential" - }, - { - "$ref": "#/components/schemas/CreateAzureCredentialDTO", - "title": "AzureCredential" - }, - { - "$ref": "#/components/schemas/CreateAzureOpenAICredentialDTO", - "title": "AzureOpenAICredential" - }, - { - "$ref": "#/components/schemas/CreateByoSipTrunkCredentialDTO", - "title": "ByoSipTrunkCredential" - }, - { - "$ref": "#/components/schemas/CreateCartesiaCredentialDTO", - "title": "CartesiaCredential" - }, - { - "$ref": "#/components/schemas/CreateCerebrasCredentialDTO", - "title": "CerebrasCredential" - }, - { - "$ref": "#/components/schemas/CreateCloudflareCredentialDTO", - "title": "CloudflareCredential" - }, - { - "$ref": "#/components/schemas/CreateCustomLLMCredentialDTO", - "title": "CustomLLMCredential" - }, - { - "$ref": "#/components/schemas/CreateDeepgramCredentialDTO", - "title": "DeepgramCredential" - }, - { - "$ref": "#/components/schemas/CreateDeepInfraCredentialDTO", - "title": "DeepInfraCredential" - }, - { - "$ref": "#/components/schemas/CreateDeepSeekCredentialDTO", - "title": "DeepSeekCredential" - }, - { - "$ref": "#/components/schemas/CreateElevenLabsCredentialDTO", - "title": "ElevenLabsCredential" - }, - { - "$ref": "#/components/schemas/CreateGcpCredentialDTO", - "title": "GcpCredential" - }, - { - "$ref": "#/components/schemas/CreateGladiaCredentialDTO", - "title": "GladiaCredential" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelCredentialDTO", - "title": "GhlCredential" - }, - { - "$ref": "#/components/schemas/CreateGoogleCredentialDTO", - "title": "GoogleCredential" - }, - { - "$ref": "#/components/schemas/CreateGroqCredentialDTO", - "title": "GroqCredential" - }, - { - "$ref": "#/components/schemas/CreateHumeCredentialDTO", - "title": "HumeCredential" - }, - { - "$ref": "#/components/schemas/CreateInflectionAICredentialDTO", - "title": "InflectionAICredential" - }, - { - "$ref": "#/components/schemas/CreateLangfuseCredentialDTO", - "title": "LangfuseCredential" - }, - { - "$ref": "#/components/schemas/CreateLmntCredentialDTO", - "title": "LmntCredential" - }, - { - "$ref": "#/components/schemas/CreateMakeCredentialDTO", - "title": "MakeCredential" - }, - { - "$ref": "#/components/schemas/CreateMistralCredentialDTO", - "title": "MistralCredential" - }, - { - "$ref": "#/components/schemas/CreateNeuphonicCredentialDTO", - "title": "NeuphonicCredential" - }, - { - "$ref": "#/components/schemas/CreateOpenAICredentialDTO", - "title": "OpenAICredential" - }, - { - "$ref": "#/components/schemas/CreateOpenRouterCredentialDTO", - "title": "OpenRouterCredential" - }, - { - "$ref": "#/components/schemas/CreatePerplexityAICredentialDTO", - "title": "PerplexityAICredential" - }, - { - "$ref": "#/components/schemas/CreatePlayHTCredentialDTO", - "title": "PlayHTCredential" - }, - { - "$ref": "#/components/schemas/CreateRimeAICredentialDTO", - "title": "RimeAICredential" - }, - { - "$ref": "#/components/schemas/CreateRunpodCredentialDTO", - "title": "RunpodCredential" - }, - { - "$ref": "#/components/schemas/CreateS3CredentialDTO", - "title": "S3Credential" - }, - { - "$ref": "#/components/schemas/CreateSmallestAICredentialDTO", - "title": "SmallestAICredential" - }, - { - "$ref": "#/components/schemas/CreateSpeechmaticsCredentialDTO", - "title": "SpeechmaticsCredential" - }, - { - "$ref": "#/components/schemas/CreateSupabaseCredentialDTO", - "title": "SupabaseCredential" - }, - { - "$ref": "#/components/schemas/CreateTavusCredentialDTO", - "title": "TavusCredential" - }, - { - "$ref": "#/components/schemas/CreateTogetherAICredentialDTO", - "title": "TogetherAICredential" - }, - { - "$ref": "#/components/schemas/CreateTrieveCredentialDTO", - "title": "TrieveCredential" - }, - { - "$ref": "#/components/schemas/CreateTwilioCredentialDTO", - "title": "TwilioCredential" - }, - { - "$ref": "#/components/schemas/CreateVonageCredentialDTO", - "title": "VonageCredential" - }, - { - "$ref": "#/components/schemas/CreateWebhookCredentialDTO", - "title": "WebhookCredential" - }, - { - "$ref": "#/components/schemas/CreateXAiCredentialDTO", - "title": "XAiCredential" - }, - { - "$ref": "#/components/schemas/CreateGoogleCalendarOAuth2ClientCredentialDTO", - "title": "GoogleCalendarOAuth2ClientCredential" - }, - { - "$ref": "#/components/schemas/CreateGoogleCalendarOAuth2AuthorizationCredentialDTO", - "title": "GoogleCalendarOAuth2AuthorizationCredential" - }, - { - "$ref": "#/components/schemas/CreateGoogleSheetsOAuth2AuthorizationCredentialDTO", - "title": "GoogleSheetsOAuth2AuthorizationCredential" - }, - { - "$ref": "#/components/schemas/CreateSlackOAuth2AuthorizationCredentialDTO", - "title": "SlackOAuth2AuthorizationCredential" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelMCPCredentialDTO", - "title": "GoHighLevelMCPCredential" - }, - { - "$ref": "#/components/schemas/CreateInworldCredentialDTO", - "title": "InworldCredential" - } - ], - "discriminator": { - "propertyName": "provider", - "mapping": { - "11labs": "#/components/schemas/CreateElevenLabsCredentialDTO", - "anthropic": "#/components/schemas/CreateAnthropicCredentialDTO", - "anyscale": "#/components/schemas/CreateAnyscaleCredentialDTO", - "assembly-ai": "#/components/schemas/CreateAssemblyAICredentialDTO", - "azure-openai": "#/components/schemas/CreateAzureOpenAICredentialDTO", - "azure": "#/components/schemas/CreateAzureCredentialDTO", - "byo-sip-trunk": "#/components/schemas/CreateByoSipTrunkCredentialDTO", - "cartesia": "#/components/schemas/CreateCartesiaCredentialDTO", - "cerebras": "#/components/schemas/CreateCerebrasCredentialDTO", - "cloudflare": "#/components/schemas/CreateCloudflareCredentialDTO", - "custom-llm": "#/components/schemas/CreateCustomLLMCredentialDTO", - "deepgram": "#/components/schemas/CreateDeepgramCredentialDTO", - "deepinfra": "#/components/schemas/CreateDeepInfraCredentialDTO", - "deep-seek": "#/components/schemas/CreateDeepSeekCredentialDTO", - "gcp": "#/components/schemas/CreateGcpCredentialDTO", - "gladia": "#/components/schemas/CreateGladiaCredentialDTO", - "gohighlevel": "#/components/schemas/CreateGoHighLevelCredentialDTO", - "google": "#/components/schemas/CreateGoogleCredentialDTO", - "groq": "#/components/schemas/CreateGroqCredentialDTO", - "inflection-ai": "#/components/schemas/CreateInflectionAICredentialDTO", - "langfuse": "#/components/schemas/CreateLangfuseCredentialDTO", - "lmnt": "#/components/schemas/CreateLmntCredentialDTO", - "make": "#/components/schemas/CreateMakeCredentialDTO", - "openai": "#/components/schemas/CreateOpenAICredentialDTO", - "openrouter": "#/components/schemas/CreateOpenRouterCredentialDTO", - "perplexity-ai": "#/components/schemas/CreatePerplexityAICredentialDTO", - "playht": "#/components/schemas/CreatePlayHTCredentialDTO", - "rime-ai": "#/components/schemas/CreateRimeAICredentialDTO", - "runpod": "#/components/schemas/CreateRunpodCredentialDTO", - "s3": "#/components/schemas/CreateS3CredentialDTO", - "supabase": "#/components/schemas/CreateSupabaseCredentialDTO", - "smallest-ai": "#/components/schemas/CreateSmallestAICredentialDTO", - "tavus": "#/components/schemas/CreateTavusCredentialDTO", - "together-ai": "#/components/schemas/CreateTogetherAICredentialDTO", - "twilio": "#/components/schemas/CreateTwilioCredentialDTO", - "vonage": "#/components/schemas/CreateVonageCredentialDTO", - "webhook": "#/components/schemas/CreateWebhookCredentialDTO", - "xai": "#/components/schemas/CreateXAiCredentialDTO", - "neuphonic": "#/components/schemas/CreateNeuphonicCredentialDTO", - "hume": "#/components/schemas/CreateHumeCredentialDTO", - "mistral": "#/components/schemas/CreateMistralCredentialDTO", - "speechmatics": "#/components/schemas/CreateSpeechmaticsCredentialDTO", - "trieve": "#/components/schemas/CreateTrieveCredentialDTO", - "google.calendar.oauth2-client": "#/components/schemas/CreateGoogleCalendarOAuth2ClientCredentialDTO", - "google.calendar.oauth2-authorization": "#/components/schemas/CreateGoogleCalendarOAuth2AuthorizationCredentialDTO", - "google.sheets.oauth2-authorization": "#/components/schemas/CreateGoogleSheetsOAuth2AuthorizationCredentialDTO", - "slack.oauth2-authorization": "#/components/schemas/CreateSlackOAuth2AuthorizationCredentialDTO", - "ghl.oauth2-authorization": "#/components/schemas/CreateGoHighLevelMCPCredentialDTO", - "inworld": "#/components/schemas/CreateInworldCredentialDTO", - "minimax": "#/components/schemas/CreateMinimaxCredentialDTO" - } - } + "$ref": "#/components/schemas/ElevenLabsPronunciationDictionaryLocator" } }, - "hooks": { - "type": "array", - "description": "This is a set of actions that will be performed on certain events.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/CallHookCallEnding", - "title": "CallHookCallEnding" - }, - { - "$ref": "#/components/schemas/CallHookAssistantSpeechInterrupted", - "title": "CallHookAssistantSpeechInterrupted" - }, - { - "$ref": "#/components/schemas/CallHookCustomerSpeechInterrupted", - "title": "CallHookCustomerSpeechInterrupted" - }, - { - "$ref": "#/components/schemas/CallHookCustomerSpeechTimeout", - "title": "CallHookCustomerSpeechTimeout" - } - ] - } + "fallbackPlan": { + "description": "This is the plan for voice provider fallbacks in the event that the primary voice provider fails.", + "allOf": [ + { + "$ref": "#/components/schemas/FallbackPlan" + } + ] + } + }, + "required": [ + "provider", + "voiceId" + ] + }, + "WellSaidVoice": { + "type": "object", + "properties": { + "cachingEnabled": { + "type": "boolean", + "description": "This is the flag to toggle voice caching for the assistant.", + "example": true, + "default": true }, - "name": { + "provider": { "type": "string", - "description": "This is the name of the assistant.\n\nThis is required when you want to transfer between assistants in a call.", - "maxLength": 40 + "description": "This is the voice provider that will be used.", + "enum": [ + "wellsaid" + ] }, - "voicemailMessage": { + "voiceId": { "type": "string", - "description": "This is the message that the assistant will say if the call is forwarded to voicemail.\n\nIf unspecified, it will hang up.", - "maxLength": 1000 + "description": "The WellSaid speaker ID to synthesize." }, - "endCallMessage": { + "model": { "type": "string", - "description": "This is the message that the assistant will say if it ends the call.\n\nIf unspecified, it will hang up without saying anything.", - "maxLength": 1000 + "description": "This is the model that will be used.", + "enum": [ + "caruso", + "legacy" + ] }, - "endCallPhrases": { - "description": "This list contains phrases that, if spoken by the assistant, will trigger the call to be hung up. Case insensitive.", + "enableSsml": { + "type": "boolean", + "description": "Enables limited SSML translation for input text." + }, + "libraryIds": { + "description": "Array of library IDs to use for voice synthesis.", "type": "array", "items": { - "type": "string", - "maxLength": 140, - "minLength": 2 + "type": "string" } }, - "compliancePlan": { - "$ref": "#/components/schemas/CompliancePlan" - }, - "metadata": { - "type": "object", - "description": "This is for metadata you want to store on the assistant." - }, - "backgroundSpeechDenoisingPlan": { - "description": "This enables filtering of noise and background speech while the user is talking.\n\nFeatures:\n- Smart denoising using Krisp\n- Fourier denoising\n\nSmart denoising can be combined with or used independently of Fourier denoising.\n\nOrder of precedence:\n- Smart denoising\n- Fourier denoising", + "chunkPlan": { + "description": "This is the plan for chunking the model output before it is sent to the voice provider.", "allOf": [ { - "$ref": "#/components/schemas/BackgroundSpeechDenoisingPlan" + "$ref": "#/components/schemas/ChunkPlan" } ] }, - "analysisPlan": { - "description": "This is the plan for analysis of assistant's calls. Stored in `call.analysis`.", + "fallbackPlan": { + "description": "This is the plan for voice provider fallbacks in the event that the primary voice provider fails.", "allOf": [ { - "$ref": "#/components/schemas/AnalysisPlan" + "$ref": "#/components/schemas/FallbackPlan" } ] + } + }, + "required": [ + "provider", + "voiceId" + ] + }, + "HumeVoice": { + "type": "object", + "properties": { + "cachingEnabled": { + "type": "boolean", + "description": "This is the flag to toggle voice caching for the assistant.", + "example": true, + "default": true }, - "artifactPlan": { - "description": "This is the plan for artifacts generated during assistant's calls. Stored in `call.artifact`.", - "allOf": [ - { - "$ref": "#/components/schemas/ArtifactPlan" - } + "provider": { + "type": "string", + "description": "This is the voice provider that will be used.", + "enum": [ + "hume" ] }, - "startSpeakingPlan": { - "description": "This is the plan for when the assistant should start talking.\n\nYou should configure this if you're running into these issues:\n- The assistant is too slow to start talking after the customer is done speaking.\n- The assistant is too fast to start talking after the customer is done speaking.\n- The assistant is so fast that it's actually interrupting the customer.", - "allOf": [ - { - "$ref": "#/components/schemas/StartSpeakingPlan" - } - ] + "model": { + "type": "string", + "description": "This is the model that will be used.", + "enum": [ + "octave", + "octave2" + ], + "example": "octave2" }, - "stopSpeakingPlan": { - "description": "This is the plan for when assistant should stop talking on customer interruption.\n\nYou should configure this if you're running into these issues:\n- The assistant is too slow to recognize customer's interruption.\n- The assistant is too fast to recognize customer's interruption.\n- The assistant is getting interrupted by phrases that are just acknowledgments.\n- The assistant is getting interrupted by background noises.\n- The assistant is not properly stopping -- it starts talking right after getting interrupted.", - "allOf": [ - { - "$ref": "#/components/schemas/StopSpeakingPlan" - } - ] + "voiceId": { + "type": "string", + "description": "The ID of the particular voice you want to use." }, - "monitorPlan": { - "description": "This is the plan for real-time monitoring of the assistant's calls.\n\nUsage:\n- To enable live listening of the assistant's calls, set `monitorPlan.listenEnabled` to `true`.\n- To enable live control of the assistant's calls, set `monitorPlan.controlEnabled` to `true`.", + "isCustomHumeVoice": { + "type": "boolean", + "description": "Indicates whether the chosen voice is a preset Hume AI voice or a custom voice.", + "example": false + }, + "chunkPlan": { + "description": "This is the plan for chunking the model output before it is sent to the voice provider.", "allOf": [ { - "$ref": "#/components/schemas/MonitorPlan" + "$ref": "#/components/schemas/ChunkPlan" } ] }, - "credentialIds": { - "description": "These are the credentials that will be used for the assistant calls. By default, all the credentials are available for use in the call but you can provide a subset using this.", - "type": "array", - "items": { - "type": "string" - } + "description": { + "type": "string", + "description": "Natural language instructions describing how the synthesized speech should sound, including but not limited to tone, intonation, pacing, and accent (e.g., 'a soft, gentle voice with a strong British accent').\n\nIf a Voice is specified in the request, this description serves as acting instructions.\nIf no Voice is specified, a new voice is generated based on this description." }, - "server": { - "description": "This is where Vapi will send webhooks. You can find all webhooks available along with their shape in ServerMessage schema.\n\nThe order of precedence is:\n\n1. assistant.server.url\n2. phoneNumber.serverUrl\n3. org.serverUrl", + "fallbackPlan": { + "description": "This is the plan for voice provider fallbacks in the event that the primary voice provider fails.", "allOf": [ { - "$ref": "#/components/schemas/Server" + "$ref": "#/components/schemas/FallbackPlan" } ] - }, - "keypadInputPlan": { - "$ref": "#/components/schemas/KeypadInputPlan" } - } + }, + "required": [ + "provider", + "voiceId" + ] }, - "AssistantOverrides": { + "LMNTVoice": { "type": "object", "properties": { - "transcriber": { - "description": "These are the options for the assistant's transcriber.", - "oneOf": [ - { - "$ref": "#/components/schemas/AssemblyAITranscriber", - "title": "AssemblyAITranscriber" - }, - { - "$ref": "#/components/schemas/AzureSpeechTranscriber", - "title": "AzureSpeechTranscriber" - }, - { - "$ref": "#/components/schemas/CustomTranscriber", - "title": "CustomTranscriber" - }, - { - "$ref": "#/components/schemas/DeepgramTranscriber", - "title": "DeepgramTranscriber" - }, - { - "$ref": "#/components/schemas/ElevenLabsTranscriber", - "title": "ElevenLabsTranscriber" - }, - { - "$ref": "#/components/schemas/GladiaTranscriber", - "title": "GladiaTranscriber" - }, - { - "$ref": "#/components/schemas/GoogleTranscriber", - "title": "GoogleTranscriber" - }, - { - "$ref": "#/components/schemas/SpeechmaticsTranscriber", - "title": "SpeechmaticsTranscriber" - }, - { - "$ref": "#/components/schemas/TalkscriberTranscriber", - "title": "TalkscriberTranscriber" - }, - { - "$ref": "#/components/schemas/OpenAITranscriber", - "title": "OpenAITranscriber" - }, - { - "$ref": "#/components/schemas/CartesiaTranscriber", - "title": "CartesiaTranscriber" - } - ] - }, - "model": { - "description": "These are the options for the assistant's LLM.", - "oneOf": [ - { - "$ref": "#/components/schemas/AnthropicModel", - "title": "Anthropic" - }, - { - "$ref": "#/components/schemas/AnyscaleModel", - "title": "Anyscale" - }, - { - "$ref": "#/components/schemas/CerebrasModel", - "title": "Cerebras" - }, - { - "$ref": "#/components/schemas/CustomLLMModel", - "title": "CustomLLM" - }, - { - "$ref": "#/components/schemas/DeepInfraModel", - "title": "DeepInfra" - }, - { - "$ref": "#/components/schemas/DeepSeekModel", - "title": "DeepSeek" - }, - { - "$ref": "#/components/schemas/GoogleModel", - "title": "Google" - }, - { - "$ref": "#/components/schemas/GroqModel", - "title": "Groq" - }, - { - "$ref": "#/components/schemas/InflectionAIModel", - "title": "InflectionAI" - }, - { - "$ref": "#/components/schemas/OpenAIModel", - "title": "OpenAI" - }, - { - "$ref": "#/components/schemas/OpenRouterModel", - "title": "OpenRouter" - }, - { - "$ref": "#/components/schemas/PerplexityAIModel", - "title": "PerplexityAI" - }, - { - "$ref": "#/components/schemas/TogetherAIModel", - "title": "Together" - }, - { - "$ref": "#/components/schemas/XaiModel", - "title": "XAI" - } - ] - }, - "voice": { - "description": "These are the options for the assistant's voice.", - "oneOf": [ - { - "$ref": "#/components/schemas/AzureVoice", - "title": "AzureVoice" - }, - { - "$ref": "#/components/schemas/CartesiaVoice", - "title": "CartesiaVoice" - }, - { - "$ref": "#/components/schemas/CustomVoice", - "title": "CustomVoice" - }, - { - "$ref": "#/components/schemas/DeepgramVoice", - "title": "DeepgramVoice" - }, - { - "$ref": "#/components/schemas/ElevenLabsVoice", - "title": "ElevenLabsVoice" - }, - { - "$ref": "#/components/schemas/HumeVoice", - "title": "HumeVoice" - }, - { - "$ref": "#/components/schemas/LMNTVoice", - "title": "LMNTVoice" - }, - { - "$ref": "#/components/schemas/NeuphonicVoice", - "title": "NeuphonicVoice" - }, - { - "$ref": "#/components/schemas/OpenAIVoice", - "title": "OpenAIVoice" - }, - { - "$ref": "#/components/schemas/PlayHTVoice", - "title": "PlayHTVoice" - }, - { - "$ref": "#/components/schemas/RimeAIVoice", - "title": "RimeAIVoice" - }, - { - "$ref": "#/components/schemas/SmallestAIVoice", - "title": "SmallestAIVoice" - }, - { - "$ref": "#/components/schemas/TavusVoice", - "title": "TavusVoice" - }, - { - "$ref": "#/components/schemas/VapiVoice", - "title": "VapiVoice" - }, - { - "$ref": "#/components/schemas/SesameVoice", - "title": "SesameVoice" - }, - { - "$ref": "#/components/schemas/InworldVoice", - "title": "InworldVoice" - }, - { - "$ref": "#/components/schemas/MinimaxVoice", - "title": "MinimaxVoice" - } - ] - }, - "firstMessage": { - "type": "string", - "description": "This is the first message that the assistant will say. This can also be a URL to a containerized audio file (mp3, wav, etc.).\n\nIf unspecified, assistant will wait for user to speak and use the model to respond once they speak.", - "example": "Hello! How can I help you today?" - }, - "firstMessageInterruptionsEnabled": { + "cachingEnabled": { "type": "boolean", - "default": false + "description": "This is the flag to toggle voice caching for the assistant.", + "example": true, + "default": true }, - "firstMessageMode": { + "provider": { "type": "string", - "description": "This is the mode for the first message. Default is 'assistant-speaks-first'.\n\nUse:\n- 'assistant-speaks-first' to have the assistant speak first.\n- 'assistant-waits-for-user' to have the assistant wait for the user to speak first.\n- 'assistant-speaks-first-with-model-generated-message' to have the assistant speak first with a message generated by the model based on the conversation state. (`assistant.model.messages` at call start, `call.messages` at squad transfer points).\n\n@default 'assistant-speaks-first'", + "description": "This is the voice provider that will be used.", "enum": [ - "assistant-speaks-first", - "assistant-speaks-first-with-model-generated-message", - "assistant-waits-for-user" - ], - "example": "assistant-speaks-first" - }, - "voicemailDetection": { - "description": "These are the settings to configure or disable voicemail detection. Alternatively, voicemail detection can be configured using the model.tools=[VoicemailTool].\nThis uses Twilio's built-in detection while the VoicemailTool relies on the model to detect if a voicemail was reached.\nYou can use neither of them, one of them, or both of them. By default, Twilio built-in detection is enabled while VoicemailTool is not.", - "oneOf": [ - { - "$ref": "#/components/schemas/GoogleVoicemailDetectionPlan", - "title": "Google" - }, - { - "$ref": "#/components/schemas/OpenAIVoicemailDetectionPlan", - "title": "OpenAI" - }, - { - "$ref": "#/components/schemas/TwilioVoicemailDetectionPlan", - "title": "Twilio" - }, - { - "$ref": "#/components/schemas/VapiVoicemailDetectionPlan", - "title": "Vapi" - } + "lmnt" ] }, - "clientMessages": { - "type": "array", - "enum": [ - "conversation-update", - "function-call", - "function-call-result", - "hang", - "language-changed", - "metadata", - "model-output", - "speech-update", - "status-update", - "transcript", - "tool-calls", - "tool-calls-result", - "tool.completed", - "transfer-update", - "user-interrupted", - "voice-input", - "workflow.node.started" - ], - "example": [ - "conversation-update", - "function-call", - "hang", - "model-output", - "speech-update", - "status-update", - "transfer-update", - "transcript", - "tool-calls", - "user-interrupted", - "voice-input", - "workflow.node.started" - ], - "description": "These are the messages that will be sent to your Client SDKs. Default is conversation-update,function-call,hang,model-output,speech-update,status-update,transfer-update,transcript,tool-calls,user-interrupted,voice-input,workflow.node.started. You can check the shape of the messages in ClientMessage schema.", - "items": { - "type": "string", - "enum": [ - "conversation-update", - "function-call", - "function-call-result", - "hang", - "language-changed", - "metadata", - "model-output", - "speech-update", - "status-update", - "transcript", - "tool-calls", - "tool-calls-result", - "tool.completed", - "transfer-update", - "user-interrupted", - "voice-input", - "workflow.node.started" - ] - } - }, - "serverMessages": { - "type": "array", - "enum": [ - "conversation-update", - "end-of-call-report", - "function-call", - "hang", - "language-changed", - "language-change-detected", - "model-output", - "phone-call-control", - "speech-update", - "status-update", - "transcript", - "transcript[transcriptType=\"final\"]", - "tool-calls", - "transfer-destination-request", - "handoff-destination-request", - "transfer-update", - "user-interrupted", - "voice-input", - "chat.created", - "chat.deleted", - "session.created", - "session.updated", - "session.deleted" - ], - "example": [ - "conversation-update", - "end-of-call-report", - "function-call", - "hang", - "speech-update", - "status-update", - "tool-calls", - "transfer-destination-request", - "handoff-destination-request", - "user-interrupted" - ], - "description": "These are the messages that will be sent to your Server URL. Default is conversation-update,end-of-call-report,function-call,hang,speech-update,status-update,tool-calls,transfer-destination-request,handoff-destination-request,user-interrupted. You can check the shape of the messages in ServerMessage schema.", - "items": { - "type": "string", - "enum": [ - "conversation-update", - "end-of-call-report", - "function-call", - "hang", - "language-changed", - "language-change-detected", - "model-output", - "phone-call-control", - "speech-update", - "status-update", - "transcript", - "transcript[transcriptType=\"final\"]", - "tool-calls", - "transfer-destination-request", - "handoff-destination-request", - "transfer-update", - "user-interrupted", - "voice-input", - "chat.created", - "chat.deleted", - "session.created", - "session.updated", - "session.deleted" - ] - } - }, - "maxDurationSeconds": { - "type": "number", - "description": "This is the maximum number of seconds that the call will last. When the call reaches this duration, it will be ended.\n\n@default 600 (10 minutes)", - "minimum": 10, - "maximum": 43200, - "example": 600 - }, - "backgroundSound": { - "description": "This is the background sound in the call. Default for phone calls is 'office' and default for web calls is 'off'.\nYou can also provide a custom sound by providing a URL to an audio file.", + "voiceId": { + "description": "This is the provider-specific ID that will be used.", "oneOf": [ { - "type": "enum", + "type": "string", "enum": [ - "off", - "office" + "amy", + "ansel", + "autumn", + "ava", + "brandon", + "caleb", + "cassian", + "chloe", + "dalton", + "daniel", + "dustin", + "elowen", + "evander", + "huxley", + "james", + "juniper", + "kennedy", + "lauren", + "leah", + "lily", + "lucas", + "magnus", + "miles", + "morgan", + "natalie", + "nathan", + "noah", + "nyssa", + "oliver", + "paige", + "ryan", + "sadie", + "sophie", + "stella", + "terrence", + "tyler", + "vesper", + "violet", + "warrick", + "zain", + "zeke", + "zoe" ], - "example": "office" + "title": "Preset Voice Options" }, { "type": "string", - "format": "uri", - "example": "https://www.soundjay.com/ambient/sounds/people-in-lounge-1.mp3" + "title": "LMNT Voice ID" } ] }, - "modelOutputInMessagesEnabled": { - "type": "boolean", - "description": "This determines whether the model's output is used in conversation history rather than the transcription of assistant's speech.\n\nDefault `false` while in beta.\n\n@default false", - "example": false - }, - "transportConfigurations": { - "type": "array", - "description": "These are the configurations to be passed to the transport providers of assistant's calls, like Twilio. You can store multiple configurations for different transport providers. For a call, only the configuration matching the call transport provider is used.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/TransportConfigurationTwilio", - "title": "Twilio" - } - ] - } + "speed": { + "type": "number", + "description": "This is the speed multiplier that will be used.", + "minimum": 0.25, + "maximum": 2, + "example": null }, - "observabilityPlan": { - "description": "This is the plan for observability of assistant's calls.\n\nCurrently, only Langfuse is supported.", + "language": { + "description": "Two letter ISO 639-1 language code. Use \"auto\" for auto-detection.", + "enum": [ + "aa", + "ab", + "ae", + "af", + "ak", + "am", + "an", + "ar", + "as", + "av", + "ay", + "az", + "ba", + "be", + "bg", + "bh", + "bi", + "bm", + "bn", + "bo", + "br", + "bs", + "ca", + "ce", + "ch", + "co", + "cr", + "cs", + "cu", + "cv", + "cy", + "da", + "de", + "dv", + "dz", + "ee", + "el", + "en", + "eo", + "es", + "et", + "eu", + "fa", + "ff", + "fi", + "fj", + "fo", + "fr", + "fy", + "ga", + "gd", + "gl", + "gn", + "gu", + "gv", + "ha", + "he", + "hi", + "ho", + "hr", + "ht", + "hu", + "hy", + "hz", + "ia", + "id", + "ie", + "ig", + "ii", + "ik", + "io", + "is", + "it", + "iu", + "ja", + "jv", + "ka", + "kg", + "ki", + "kj", + "kk", + "kl", + "km", + "kn", + "ko", + "kr", + "ks", + "ku", + "kv", + "kw", + "ky", + "la", + "lb", + "lg", + "li", + "ln", + "lo", + "lt", + "lu", + "lv", + "mg", + "mh", + "mi", + "mk", + "ml", + "mn", + "mr", + "ms", + "mt", + "my", + "na", + "nb", + "nd", + "ne", + "ng", + "nl", + "nn", + "no", + "nr", + "nv", + "ny", + "oc", + "oj", + "om", + "or", + "os", + "pa", + "pi", + "pl", + "ps", + "pt", + "qu", + "rm", + "rn", + "ro", + "ru", + "rw", + "sa", + "sc", + "sd", + "se", + "sg", + "si", + "sk", + "sl", + "sm", + "sn", + "so", + "sq", + "sr", + "ss", + "st", + "su", + "sv", + "sw", + "ta", + "te", + "tg", + "th", + "ti", + "tk", + "tl", + "tn", + "to", + "tr", + "ts", + "tt", + "tw", + "ty", + "ug", + "uk", + "ur", + "uz", + "ve", + "vi", + "vo", + "wa", + "wo", + "xh", + "yi", + "yue", + "yo", + "za", + "zh", + "zu", + "auto" + ], + "example": "en", "oneOf": [ { - "$ref": "#/components/schemas/LangfuseObservabilityPlan", - "title": "Langfuse" + "type": "string", + "enum": [ + "aa", + "ab", + "ae", + "af", + "ak", + "am", + "an", + "ar", + "as", + "av", + "ay", + "az", + "ba", + "be", + "bg", + "bh", + "bi", + "bm", + "bn", + "bo", + "br", + "bs", + "ca", + "ce", + "ch", + "co", + "cr", + "cs", + "cu", + "cv", + "cy", + "da", + "de", + "dv", + "dz", + "ee", + "el", + "en", + "eo", + "es", + "et", + "eu", + "fa", + "ff", + "fi", + "fj", + "fo", + "fr", + "fy", + "ga", + "gd", + "gl", + "gn", + "gu", + "gv", + "ha", + "he", + "hi", + "ho", + "hr", + "ht", + "hu", + "hy", + "hz", + "ia", + "id", + "ie", + "ig", + "ii", + "ik", + "io", + "is", + "it", + "iu", + "ja", + "jv", + "ka", + "kg", + "ki", + "kj", + "kk", + "kl", + "km", + "kn", + "ko", + "kr", + "ks", + "ku", + "kv", + "kw", + "ky", + "la", + "lb", + "lg", + "li", + "ln", + "lo", + "lt", + "lu", + "lv", + "mg", + "mh", + "mi", + "mk", + "ml", + "mn", + "mr", + "ms", + "mt", + "my", + "na", + "nb", + "nd", + "ne", + "ng", + "nl", + "nn", + "no", + "nr", + "nv", + "ny", + "oc", + "oj", + "om", + "or", + "os", + "pa", + "pi", + "pl", + "ps", + "pt", + "qu", + "rm", + "rn", + "ro", + "ru", + "rw", + "sa", + "sc", + "sd", + "se", + "sg", + "si", + "sk", + "sl", + "sm", + "sn", + "so", + "sq", + "sr", + "ss", + "st", + "su", + "sv", + "sw", + "ta", + "te", + "tg", + "th", + "ti", + "tk", + "tl", + "tn", + "to", + "tr", + "ts", + "tt", + "tw", + "ty", + "ug", + "uk", + "ur", + "uz", + "ve", + "vi", + "vo", + "wa", + "wo", + "xh", + "yi", + "yue", + "yo", + "za", + "zh", + "zu" + ], + "title": "ISO 639-1 Language Code" + }, + { + "type": "string", + "enum": [ + "auto" + ], + "title": "Auto-detect" + } + ] + }, + "chunkPlan": { + "description": "This is the plan for chunking the model output before it is sent to the voice provider.", + "allOf": [ + { + "$ref": "#/components/schemas/ChunkPlan" + } + ] + }, + "fallbackPlan": { + "description": "This is the plan for voice provider fallbacks in the event that the primary voice provider fails.", + "allOf": [ + { + "$ref": "#/components/schemas/FallbackPlan" + } + ] + } + }, + "required": [ + "provider", + "voiceId" + ] + }, + "NeuphonicVoice": { + "type": "object", + "properties": { + "cachingEnabled": { + "type": "boolean", + "description": "This is the flag to toggle voice caching for the assistant.", + "example": true, + "default": true + }, + "provider": { + "type": "string", + "description": "This is the voice provider that will be used.", + "enum": [ + "neuphonic" + ] + }, + "voiceId": { + "description": "This is the provider-specific ID that will be used.", + "oneOf": [ + { + "type": "string", + "enum": [], + "title": "Preset Voice Options" + }, + { + "type": "string", + "title": "Neuphonic Voice ID" } + ] + }, + "model": { + "type": "string", + "description": "This is the model that will be used. Defaults to 'neu_fast' if not specified.", + "enum": [ + "neu_hq", + "neu_fast" ], + "example": "neu_fast" + }, + "language": { + "type": "object", + "description": "This is the language (ISO 639-1) that is enforced for the model.", + "example": "en" + }, + "speed": { + "type": "number", + "description": "This is the speed multiplier that will be used.", + "minimum": 0.25, + "maximum": 2, + "example": null + }, + "chunkPlan": { + "description": "This is the plan for chunking the model output before it is sent to the voice provider.", "allOf": [ { - "$ref": "#/components/schemas/LangfuseObservabilityPlan" + "$ref": "#/components/schemas/ChunkPlan" } ] }, - "credentials": { - "type": "array", - "description": "These are dynamic credentials that will be used for the assistant calls. By default, all the credentials are available for use in the call but you can supplement an additional credentials using this. Dynamic credentials override existing credentials.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/CreateAnthropicCredentialDTO", - "title": "AnthropicCredential" - }, - { - "$ref": "#/components/schemas/CreateAnyscaleCredentialDTO", - "title": "AnyscaleCredential" - }, - { - "$ref": "#/components/schemas/CreateAssemblyAICredentialDTO", - "title": "AssemblyAICredential" - }, - { - "$ref": "#/components/schemas/CreateAzureCredentialDTO", - "title": "AzureCredential" - }, - { - "$ref": "#/components/schemas/CreateAzureOpenAICredentialDTO", - "title": "AzureOpenAICredential" - }, - { - "$ref": "#/components/schemas/CreateByoSipTrunkCredentialDTO", - "title": "ByoSipTrunkCredential" - }, - { - "$ref": "#/components/schemas/CreateCartesiaCredentialDTO", - "title": "CartesiaCredential" - }, - { - "$ref": "#/components/schemas/CreateCerebrasCredentialDTO", - "title": "CerebrasCredential" - }, - { - "$ref": "#/components/schemas/CreateCloudflareCredentialDTO", - "title": "CloudflareCredential" - }, - { - "$ref": "#/components/schemas/CreateCustomLLMCredentialDTO", - "title": "CustomLLMCredential" - }, - { - "$ref": "#/components/schemas/CreateDeepgramCredentialDTO", - "title": "DeepgramCredential" - }, - { - "$ref": "#/components/schemas/CreateDeepInfraCredentialDTO", - "title": "DeepInfraCredential" - }, - { - "$ref": "#/components/schemas/CreateDeepSeekCredentialDTO", - "title": "DeepSeekCredential" - }, - { - "$ref": "#/components/schemas/CreateElevenLabsCredentialDTO", - "title": "ElevenLabsCredential" - }, - { - "$ref": "#/components/schemas/CreateGcpCredentialDTO", - "title": "GcpCredential" - }, - { - "$ref": "#/components/schemas/CreateGladiaCredentialDTO", - "title": "GladiaCredential" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelCredentialDTO", - "title": "GhlCredential" - }, - { - "$ref": "#/components/schemas/CreateGoogleCredentialDTO", - "title": "GoogleCredential" - }, - { - "$ref": "#/components/schemas/CreateGroqCredentialDTO", - "title": "GroqCredential" - }, - { - "$ref": "#/components/schemas/CreateHumeCredentialDTO", - "title": "HumeCredential" - }, - { - "$ref": "#/components/schemas/CreateInflectionAICredentialDTO", - "title": "InflectionAICredential" - }, - { - "$ref": "#/components/schemas/CreateLangfuseCredentialDTO", - "title": "LangfuseCredential" - }, - { - "$ref": "#/components/schemas/CreateLmntCredentialDTO", - "title": "LmntCredential" - }, - { - "$ref": "#/components/schemas/CreateMakeCredentialDTO", - "title": "MakeCredential" - }, - { - "$ref": "#/components/schemas/CreateMistralCredentialDTO", - "title": "MistralCredential" - }, - { - "$ref": "#/components/schemas/CreateNeuphonicCredentialDTO", - "title": "NeuphonicCredential" - }, - { - "$ref": "#/components/schemas/CreateOpenAICredentialDTO", - "title": "OpenAICredential" - }, - { - "$ref": "#/components/schemas/CreateOpenRouterCredentialDTO", - "title": "OpenRouterCredential" - }, - { - "$ref": "#/components/schemas/CreatePerplexityAICredentialDTO", - "title": "PerplexityAICredential" - }, - { - "$ref": "#/components/schemas/CreatePlayHTCredentialDTO", - "title": "PlayHTCredential" - }, - { - "$ref": "#/components/schemas/CreateRimeAICredentialDTO", - "title": "RimeAICredential" - }, - { - "$ref": "#/components/schemas/CreateRunpodCredentialDTO", - "title": "RunpodCredential" - }, - { - "$ref": "#/components/schemas/CreateS3CredentialDTO", - "title": "S3Credential" - }, - { - "$ref": "#/components/schemas/CreateSmallestAICredentialDTO", - "title": "SmallestAICredential" - }, - { - "$ref": "#/components/schemas/CreateSpeechmaticsCredentialDTO", - "title": "SpeechmaticsCredential" - }, - { - "$ref": "#/components/schemas/CreateSupabaseCredentialDTO", - "title": "SupabaseCredential" - }, - { - "$ref": "#/components/schemas/CreateTavusCredentialDTO", - "title": "TavusCredential" - }, - { - "$ref": "#/components/schemas/CreateTogetherAICredentialDTO", - "title": "TogetherAICredential" - }, - { - "$ref": "#/components/schemas/CreateTrieveCredentialDTO", - "title": "TrieveCredential" - }, - { - "$ref": "#/components/schemas/CreateTwilioCredentialDTO", - "title": "TwilioCredential" - }, - { - "$ref": "#/components/schemas/CreateVonageCredentialDTO", - "title": "VonageCredential" - }, - { - "$ref": "#/components/schemas/CreateWebhookCredentialDTO", - "title": "WebhookCredential" - }, - { - "$ref": "#/components/schemas/CreateXAiCredentialDTO", - "title": "XAiCredential" - }, - { - "$ref": "#/components/schemas/CreateGoogleCalendarOAuth2ClientCredentialDTO", - "title": "GoogleCalendarOAuth2ClientCredential" - }, - { - "$ref": "#/components/schemas/CreateGoogleCalendarOAuth2AuthorizationCredentialDTO", - "title": "GoogleCalendarOAuth2AuthorizationCredential" - }, - { - "$ref": "#/components/schemas/CreateGoogleSheetsOAuth2AuthorizationCredentialDTO", - "title": "GoogleSheetsOAuth2AuthorizationCredential" - }, - { - "$ref": "#/components/schemas/CreateSlackOAuth2AuthorizationCredentialDTO", - "title": "SlackOAuth2AuthorizationCredential" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelMCPCredentialDTO", - "title": "GoHighLevelMCPCredential" - }, - { - "$ref": "#/components/schemas/CreateInworldCredentialDTO", - "title": "InworldCredential" - } - ], - "discriminator": { - "propertyName": "provider", - "mapping": { - "11labs": "#/components/schemas/CreateElevenLabsCredentialDTO", - "anthropic": "#/components/schemas/CreateAnthropicCredentialDTO", - "anyscale": "#/components/schemas/CreateAnyscaleCredentialDTO", - "assembly-ai": "#/components/schemas/CreateAssemblyAICredentialDTO", - "azure-openai": "#/components/schemas/CreateAzureOpenAICredentialDTO", - "azure": "#/components/schemas/CreateAzureCredentialDTO", - "byo-sip-trunk": "#/components/schemas/CreateByoSipTrunkCredentialDTO", - "cartesia": "#/components/schemas/CreateCartesiaCredentialDTO", - "cerebras": "#/components/schemas/CreateCerebrasCredentialDTO", - "cloudflare": "#/components/schemas/CreateCloudflareCredentialDTO", - "custom-llm": "#/components/schemas/CreateCustomLLMCredentialDTO", - "deepgram": "#/components/schemas/CreateDeepgramCredentialDTO", - "deepinfra": "#/components/schemas/CreateDeepInfraCredentialDTO", - "deep-seek": "#/components/schemas/CreateDeepSeekCredentialDTO", - "gcp": "#/components/schemas/CreateGcpCredentialDTO", - "gladia": "#/components/schemas/CreateGladiaCredentialDTO", - "gohighlevel": "#/components/schemas/CreateGoHighLevelCredentialDTO", - "google": "#/components/schemas/CreateGoogleCredentialDTO", - "groq": "#/components/schemas/CreateGroqCredentialDTO", - "inflection-ai": "#/components/schemas/CreateInflectionAICredentialDTO", - "langfuse": "#/components/schemas/CreateLangfuseCredentialDTO", - "lmnt": "#/components/schemas/CreateLmntCredentialDTO", - "make": "#/components/schemas/CreateMakeCredentialDTO", - "openai": "#/components/schemas/CreateOpenAICredentialDTO", - "openrouter": "#/components/schemas/CreateOpenRouterCredentialDTO", - "perplexity-ai": "#/components/schemas/CreatePerplexityAICredentialDTO", - "playht": "#/components/schemas/CreatePlayHTCredentialDTO", - "rime-ai": "#/components/schemas/CreateRimeAICredentialDTO", - "runpod": "#/components/schemas/CreateRunpodCredentialDTO", - "s3": "#/components/schemas/CreateS3CredentialDTO", - "supabase": "#/components/schemas/CreateSupabaseCredentialDTO", - "smallest-ai": "#/components/schemas/CreateSmallestAICredentialDTO", - "tavus": "#/components/schemas/CreateTavusCredentialDTO", - "together-ai": "#/components/schemas/CreateTogetherAICredentialDTO", - "twilio": "#/components/schemas/CreateTwilioCredentialDTO", - "vonage": "#/components/schemas/CreateVonageCredentialDTO", - "webhook": "#/components/schemas/CreateWebhookCredentialDTO", - "xai": "#/components/schemas/CreateXAiCredentialDTO", - "neuphonic": "#/components/schemas/CreateNeuphonicCredentialDTO", - "hume": "#/components/schemas/CreateHumeCredentialDTO", - "mistral": "#/components/schemas/CreateMistralCredentialDTO", - "speechmatics": "#/components/schemas/CreateSpeechmaticsCredentialDTO", - "trieve": "#/components/schemas/CreateTrieveCredentialDTO", - "google.calendar.oauth2-client": "#/components/schemas/CreateGoogleCalendarOAuth2ClientCredentialDTO", - "google.calendar.oauth2-authorization": "#/components/schemas/CreateGoogleCalendarOAuth2AuthorizationCredentialDTO", - "google.sheets.oauth2-authorization": "#/components/schemas/CreateGoogleSheetsOAuth2AuthorizationCredentialDTO", - "slack.oauth2-authorization": "#/components/schemas/CreateSlackOAuth2AuthorizationCredentialDTO", - "ghl.oauth2-authorization": "#/components/schemas/CreateGoHighLevelMCPCredentialDTO", - "inworld": "#/components/schemas/CreateInworldCredentialDTO", - "minimax": "#/components/schemas/CreateMinimaxCredentialDTO" - } - } - } - }, - "hooks": { - "type": "array", - "description": "This is a set of actions that will be performed on certain events.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/CallHookCallEnding", - "title": "CallHookCallEnding" - }, - { - "$ref": "#/components/schemas/CallHookAssistantSpeechInterrupted", - "title": "CallHookAssistantSpeechInterrupted" - }, - { - "$ref": "#/components/schemas/CallHookCustomerSpeechInterrupted", - "title": "CallHookCustomerSpeechInterrupted" - }, - { - "$ref": "#/components/schemas/CallHookCustomerSpeechTimeout", - "title": "CallHookCustomerSpeechTimeout" - } - ] - } - }, - "variableValues": { - "type": "object", - "description": "These are values that will be used to replace the template variables in the assistant messages and other text-based fields.\nThis uses LiquidJS syntax. https://liquidjs.com/tutorials/intro-to-liquid.html\n\nSo for example, `{{ name }}` will be replaced with the value of `name` in `variableValues`.\n`{{\"now\" | date: \"%b %d, %Y, %I:%M %p\", \"America/New_York\"}}` will be replaced with the current date and time in New York.\n Some VAPI reserved defaults:\n - *customer* - the customer object" - }, - "name": { - "type": "string", - "description": "This is the name of the assistant.\n\nThis is required when you want to transfer between assistants in a call.", - "maxLength": 40 - }, - "voicemailMessage": { - "type": "string", - "description": "This is the message that the assistant will say if the call is forwarded to voicemail.\n\nIf unspecified, it will hang up.", - "maxLength": 1000 - }, - "endCallMessage": { - "type": "string", - "description": "This is the message that the assistant will say if it ends the call.\n\nIf unspecified, it will hang up without saying anything.", - "maxLength": 1000 - }, - "endCallPhrases": { - "description": "This list contains phrases that, if spoken by the assistant, will trigger the call to be hung up. Case insensitive.", - "type": "array", - "items": { - "type": "string", - "maxLength": 140, - "minLength": 2 - } - }, - "compliancePlan": { - "$ref": "#/components/schemas/CompliancePlan" - }, - "metadata": { - "type": "object", - "description": "This is for metadata you want to store on the assistant." - }, - "backgroundSpeechDenoisingPlan": { - "description": "This enables filtering of noise and background speech while the user is talking.\n\nFeatures:\n- Smart denoising using Krisp\n- Fourier denoising\n\nSmart denoising can be combined with or used independently of Fourier denoising.\n\nOrder of precedence:\n- Smart denoising\n- Fourier denoising", - "allOf": [ - { - "$ref": "#/components/schemas/BackgroundSpeechDenoisingPlan" - } - ] - }, - "analysisPlan": { - "description": "This is the plan for analysis of assistant's calls. Stored in `call.analysis`.", - "allOf": [ - { - "$ref": "#/components/schemas/AnalysisPlan" - } - ] - }, - "artifactPlan": { - "description": "This is the plan for artifacts generated during assistant's calls. Stored in `call.artifact`.", + "fallbackPlan": { + "description": "This is the plan for voice provider fallbacks in the event that the primary voice provider fails.", "allOf": [ { - "$ref": "#/components/schemas/ArtifactPlan" + "$ref": "#/components/schemas/FallbackPlan" } ] + } + }, + "required": [ + "provider", + "voiceId", + "language" + ] + }, + "OpenAIVoice": { + "type": "object", + "properties": { + "cachingEnabled": { + "type": "boolean", + "description": "This is the flag to toggle voice caching for the assistant.", + "example": true, + "default": true }, - "startSpeakingPlan": { - "description": "This is the plan for when the assistant should start talking.\n\nYou should configure this if you're running into these issues:\n- The assistant is too slow to start talking after the customer is done speaking.\n- The assistant is too fast to start talking after the customer is done speaking.\n- The assistant is so fast that it's actually interrupting the customer.", - "allOf": [ - { - "$ref": "#/components/schemas/StartSpeakingPlan" - } + "provider": { + "type": "string", + "description": "This is the voice provider that will be used.", + "enum": [ + "openai" ] }, - "stopSpeakingPlan": { - "description": "This is the plan for when assistant should stop talking on customer interruption.\n\nYou should configure this if you're running into these issues:\n- The assistant is too slow to recognize customer's interruption.\n- The assistant is too fast to recognize customer's interruption.\n- The assistant is getting interrupted by phrases that are just acknowledgments.\n- The assistant is getting interrupted by background noises.\n- The assistant is not properly stopping -- it starts talking right after getting interrupted.", - "allOf": [ + "voiceId": { + "description": "This is the provider-specific ID that will be used.\nPlease note that ash, ballad, coral, sage, and verse may only be used with realtime models.", + "oneOf": [ { - "$ref": "#/components/schemas/StopSpeakingPlan" - } - ] - }, - "monitorPlan": { - "description": "This is the plan for real-time monitoring of the assistant's calls.\n\nUsage:\n- To enable live listening of the assistant's calls, set `monitorPlan.listenEnabled` to `true`.\n- To enable live control of the assistant's calls, set `monitorPlan.controlEnabled` to `true`.", - "allOf": [ + "type": "string", + "enum": [ + "alloy", + "echo", + "fable", + "onyx", + "nova", + "shimmer", + "marin", + "cedar" + ], + "title": "Preset Voice Options" + }, { - "$ref": "#/components/schemas/MonitorPlan" + "type": "string", + "title": "OpenAI Voice ID" } ] }, - "credentialIds": { - "description": "These are the credentials that will be used for the assistant calls. By default, all the credentials are available for use in the call but you can provide a subset using this.", - "type": "array", - "items": { - "type": "string" - } - }, - "server": { - "description": "This is where Vapi will send webhooks. You can find all webhooks available along with their shape in ServerMessage schema.\n\nThe order of precedence is:\n\n1. assistant.server.url\n2. phoneNumber.serverUrl\n3. org.serverUrl", - "allOf": [ - { - "$ref": "#/components/schemas/Server" - } + "model": { + "type": "string", + "description": "This is the model that will be used for text-to-speech.", + "enum": [ + "tts-1", + "tts-1-hd", + "gpt-4o-mini-tts" ] }, - "keypadInputPlan": { - "$ref": "#/components/schemas/KeypadInputPlan" - } - } - }, - "SquadMemberDTO": { - "type": "object", - "properties": { - "assistantId": { + "instructions": { "type": "string", - "nullable": true, - "description": "This is the assistant that will be used for the call. To use a transient assistant, use `assistant` instead." + "description": "This is a prompt that allows you to control the voice of your generated audio.\nDoes not work with 'tts-1' or 'tts-1-hd' models.", + "maxLength": 10000 }, - "assistant": { - "description": "This is the assistant that will be used for the call. To use an existing assistant, use `assistantId` instead.", - "allOf": [ - { - "$ref": "#/components/schemas/CreateAssistantDTO" - } - ] + "speed": { + "type": "number", + "description": "This is the speed multiplier that will be used.", + "minimum": 0.25, + "maximum": 4, + "example": null }, - "assistantOverrides": { - "description": "This can be used to override the assistant's settings and provide values for it's template variables.", + "chunkPlan": { + "description": "This is the plan for chunking the model output before it is sent to the voice provider.", "allOf": [ { - "$ref": "#/components/schemas/AssistantOverrides" + "$ref": "#/components/schemas/ChunkPlan" } ] }, - "assistantDestinations": { - "description": "These are the others assistants that this assistant can transfer to.\n\nIf the assistant already has transfer call tool, these destinations are just appended to existing ones.", - "type": "array", - "items": { - "$ref": "#/components/schemas/TransferDestinationAssistant" - } - } - } - }, - "CreateSquadDTO": { - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "This is the name of the squad." - }, - "members": { - "description": "This is the list of assistants that make up the squad.\n\nThe call will start with the first assistant in the list.", - "type": "array", - "items": { - "$ref": "#/components/schemas/SquadMemberDTO" - } - }, - "membersOverrides": { - "description": "This can be used to override all the assistants' settings and provide values for their template variables.\n\nBoth `membersOverrides` and `members[n].assistantOverrides` can be used together. First, `members[n].assistantOverrides` is applied. Then, `membersOverrides` is applied as a global override.", + "fallbackPlan": { + "description": "This is the plan for voice provider fallbacks in the event that the primary voice provider fails.", "allOf": [ { - "$ref": "#/components/schemas/AssistantOverrides" + "$ref": "#/components/schemas/FallbackPlan" } ] } }, "required": [ - "members" + "provider", + "voiceId" ] }, - "CreateWorkflowDTO": { + "PlayHTVoice": { "type": "object", "properties": { - "nodes": { - "type": "array", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ConversationNode", - "title": "ConversationNode" - }, - { - "$ref": "#/components/schemas/ToolNode", - "title": "ToolNode" - } - ] - } + "cachingEnabled": { + "type": "boolean", + "description": "This is the flag to toggle voice caching for the assistant.", + "example": true, + "default": true }, - "model": { - "description": "This is the model for the workflow.\n\nThis can be overridden at node level using `nodes[n].model`.", + "provider": { + "type": "string", + "description": "This is the voice provider that will be used.", + "enum": [ + "playht" + ] + }, + "voiceId": { + "description": "This is the provider-specific ID that will be used.", "oneOf": [ { - "$ref": "#/components/schemas/WorkflowOpenAIModel", - "title": "WorkflowOpenAIModel" - }, - { - "$ref": "#/components/schemas/WorkflowAnthropicModel", - "title": "WorkflowAnthropicModel" - }, - { - "$ref": "#/components/schemas/WorkflowGoogleModel", - "title": "WorkflowGoogleModel" + "type": "string", + "enum": [ + "jennifer", + "melissa", + "will", + "chris", + "matt", + "jack", + "ruby", + "davis", + "donna", + "michael" + ], + "title": "Preset Voice Options" }, { - "$ref": "#/components/schemas/WorkflowCustomModel", - "title": "WorkflowCustomModel" + "type": "string", + "title": "PlayHT Voice ID" } ] }, - "transcriber": { - "description": "This is the transcriber for the workflow.\n\nThis can be overridden at node level using `nodes[n].transcriber`.", - "oneOf": [ - { - "$ref": "#/components/schemas/AssemblyAITranscriber", - "title": "AssemblyAITranscriber" - }, - { - "$ref": "#/components/schemas/AzureSpeechTranscriber", - "title": "AzureSpeechTranscriber" - }, - { - "$ref": "#/components/schemas/CustomTranscriber", - "title": "CustomTranscriber" - }, - { - "$ref": "#/components/schemas/DeepgramTranscriber", - "title": "DeepgramTranscriber" - }, - { - "$ref": "#/components/schemas/ElevenLabsTranscriber", - "title": "ElevenLabsTranscriber" - }, - { - "$ref": "#/components/schemas/GladiaTranscriber", - "title": "GladiaTranscriber" - }, - { - "$ref": "#/components/schemas/GoogleTranscriber", - "title": "GoogleTranscriber" - }, - { - "$ref": "#/components/schemas/SpeechmaticsTranscriber", - "title": "SpeechmaticsTranscriber" - }, - { - "$ref": "#/components/schemas/TalkscriberTranscriber", - "title": "TalkscriberTranscriber" - }, + "speed": { + "type": "number", + "description": "This is the speed multiplier that will be used.", + "minimum": 0.1, + "maximum": 5, + "example": null + }, + "temperature": { + "type": "number", + "description": "A floating point number between 0, exclusive, and 2, inclusive. If equal to null or not provided, the model's default temperature will be used. The temperature parameter controls variance. Lower temperatures result in more predictable results, higher temperatures allow each run to vary more, so the voice may sound less like the baseline voice.", + "minimum": 0.1, + "maximum": 2, + "example": null + }, + "emotion": { + "type": "string", + "description": "An emotion to be applied to the speech.", + "enum": [ + "female_happy", + "female_sad", + "female_angry", + "female_fearful", + "female_disgust", + "female_surprised", + "male_happy", + "male_sad", + "male_angry", + "male_fearful", + "male_disgust", + "male_surprised" + ], + "example": null + }, + "voiceGuidance": { + "type": "number", + "description": "A number between 1 and 6. Use lower numbers to reduce how unique your chosen voice will be compared to other voices.", + "minimum": 1, + "maximum": 6, + "example": null + }, + "styleGuidance": { + "type": "number", + "description": "A number between 1 and 30. Use lower numbers to to reduce how strong your chosen emotion will be. Higher numbers will create a very emotional performance.", + "minimum": 1, + "maximum": 30, + "example": null + }, + "textGuidance": { + "type": "number", + "description": "A number between 1 and 2. This number influences how closely the generated speech adheres to the input text. Use lower values to create more fluid speech, but with a higher chance of deviating from the input text. Higher numbers will make the generated speech more accurate to the input text, ensuring that the words spoken align closely with the provided text.", + "minimum": 1, + "maximum": 2, + "example": null + }, + "model": { + "type": "string", + "description": "Playht voice model/engine to use.", + "enum": [ + "PlayHT2.0", + "PlayHT2.0-turbo", + "Play3.0-mini", + "PlayDialog" + ] + }, + "language": { + "type": "string", + "description": "The language to use for the speech.", + "enum": [ + "afrikaans", + "albanian", + "amharic", + "arabic", + "bengali", + "bulgarian", + "catalan", + "croatian", + "czech", + "danish", + "dutch", + "english", + "french", + "galician", + "german", + "greek", + "hebrew", + "hindi", + "hungarian", + "indonesian", + "italian", + "japanese", + "korean", + "malay", + "mandarin", + "polish", + "portuguese", + "russian", + "serbian", + "spanish", + "swedish", + "tagalog", + "thai", + "turkish", + "ukrainian", + "urdu", + "xhosa" + ] + }, + "chunkPlan": { + "description": "This is the plan for chunking the model output before it is sent to the voice provider.", + "allOf": [ { - "$ref": "#/components/schemas/OpenAITranscriber", - "title": "OpenAITranscriber" - }, + "$ref": "#/components/schemas/ChunkPlan" + } + ] + }, + "fallbackPlan": { + "description": "This is the plan for voice provider fallbacks in the event that the primary voice provider fails.", + "allOf": [ { - "$ref": "#/components/schemas/CartesiaTranscriber", - "title": "CartesiaTranscriber" + "$ref": "#/components/schemas/FallbackPlan" } ] + } + }, + "required": [ + "provider", + "voiceId" + ] + }, + "RimeAIVoice": { + "type": "object", + "properties": { + "cachingEnabled": { + "type": "boolean", + "description": "This is the flag to toggle voice caching for the assistant.", + "example": true, + "default": true + }, + "provider": { + "type": "string", + "description": "This is the voice provider that will be used.", + "enum": [ + "rime-ai" + ] }, - "voice": { - "description": "This is the voice for the workflow.\n\nThis can be overridden at node level using `nodes[n].voice`.", + "voiceId": { + "description": "This is the provider-specific ID that will be used.", "oneOf": [ { - "$ref": "#/components/schemas/AzureVoice", - "title": "AzureVoice" - }, - { - "$ref": "#/components/schemas/CartesiaVoice", - "title": "CartesiaVoice" - }, - { - "$ref": "#/components/schemas/CustomVoice", - "title": "CustomVoice" - }, - { - "$ref": "#/components/schemas/DeepgramVoice", - "title": "DeepgramVoice" - }, - { - "$ref": "#/components/schemas/ElevenLabsVoice", - "title": "ElevenLabsVoice" - }, - { - "$ref": "#/components/schemas/HumeVoice", - "title": "HumeVoice" - }, - { - "$ref": "#/components/schemas/LMNTVoice", - "title": "LMNTVoice" - }, - { - "$ref": "#/components/schemas/NeuphonicVoice", - "title": "NeuphonicVoice" - }, - { - "$ref": "#/components/schemas/OpenAIVoice", - "title": "OpenAIVoice" - }, - { - "$ref": "#/components/schemas/PlayHTVoice", - "title": "PlayHTVoice" - }, - { - "$ref": "#/components/schemas/RimeAIVoice", - "title": "RimeAIVoice" - }, - { - "$ref": "#/components/schemas/SmallestAIVoice", - "title": "SmallestAIVoice" - }, - { - "$ref": "#/components/schemas/TavusVoice", - "title": "TavusVoice" - }, - { - "$ref": "#/components/schemas/VapiVoice", - "title": "VapiVoice" + "type": "string", + "enum": [ + "cove", + "moon", + "wildflower", + "eva", + "amber", + "maya", + "lagoon", + "breeze", + "helen", + "joy", + "marsh", + "creek", + "cedar", + "alpine", + "summit", + "nicholas", + "tyler", + "colin", + "hank", + "thunder", + "astra", + "eucalyptus", + "moraine", + "peak", + "tundra", + "mesa_extra", + "talon", + "marlu", + "glacier", + "falcon", + "luna", + "celeste", + "estelle", + "andromeda", + "esther", + "lyra", + "lintel", + "oculus", + "vespera", + "transom", + "bond", + "arcade", + "atrium", + "cupola", + "fern", + "sirius", + "orion", + "masonry", + "albion", + "parapet" + ], + "title": "Suggested Voice Options", + "description": "Popular Rime AI voices across mist, mistv2, and arcana models. Any valid Rime AI voice ID is accepted, not just these suggestions." }, { - "$ref": "#/components/schemas/SesameVoice", - "title": "SesameVoice" - }, + "type": "string", + "title": "Any Rime AI Voice ID", + "description": "Any valid Rime AI voice ID. See https://docs.rime.ai/docs/voices for the full catalog." + } + ] + }, + "model": { + "type": "string", + "description": "This is the model that will be used. Defaults to 'arcana' when not specified.", + "enum": [ + "arcana", + "mistv2", + "mist" + ], + "example": "arcana" + }, + "speed": { + "type": "number", + "description": "This is the speed multiplier that will be used.", + "minimum": 0.1, + "example": null + }, + "pauseBetweenBrackets": { + "type": "boolean", + "description": "This is a flag that controls whether to add slight pauses using angle brackets. Example: \"Hi. <200> I'd love to have a conversation with you.\" adds a 200ms pause between the first and second sentences.", + "example": false + }, + "phonemizeBetweenBrackets": { + "type": "boolean", + "description": "This is a flag that controls whether text inside brackets should be phonemized (converted to phonetic pronunciation) - Example: \"{h'El.o} World\" will pronounce \"Hello\" as expected.", + "example": false + }, + "reduceLatency": { + "type": "boolean", + "description": "This is a flag that controls whether to optimize for reduced latency in streaming. https://docs.rime.ai/api-reference/endpoint/websockets#param-reduce-latency", + "example": false + }, + "inlineSpeedAlpha": { + "type": "string", + "description": "This is a string that allows inline speed control using alpha notation. https://docs.rime.ai/api-reference/endpoint/websockets#param-inline-speed-alpha", + "example": null + }, + "language": { + "type": "string", + "description": "Language for speech synthesis. Uses ISO 639 codes. Supported: en, es, de, fr, ar, hi, ja, he, pt, ta, si.", + "enum": [ + "en", + "es", + "de", + "fr", + "ar", + "hi", + "ja", + "he", + "pt", + "ta", + "si" + ], + "example": "en" + }, + "chunkPlan": { + "description": "This is the plan for chunking the model output before it is sent to the voice provider.", + "allOf": [ { - "$ref": "#/components/schemas/InworldVoice", - "title": "InworldVoice" - }, + "$ref": "#/components/schemas/ChunkPlan" + } + ] + }, + "fallbackPlan": { + "description": "This is the plan for voice provider fallbacks in the event that the primary voice provider fails.", + "allOf": [ { - "$ref": "#/components/schemas/MinimaxVoice", - "title": "MinimaxVoice" + "$ref": "#/components/schemas/FallbackPlan" } ] + } + }, + "required": [ + "provider", + "voiceId" + ] + }, + "SesameVoice": { + "type": "object", + "properties": { + "cachingEnabled": { + "type": "boolean", + "description": "This is the flag to toggle voice caching for the assistant.", + "example": true, + "default": true }, - "observabilityPlan": { - "description": "This is the plan for observability of workflow's calls.\n\nCurrently, only Langfuse is supported.", - "oneOf": [ + "provider": { + "type": "string", + "description": "This is the voice provider that will be used.", + "enum": [ + "sesame" + ] + }, + "voiceId": { + "type": "string", + "description": "This is the provider-specific ID that will be used.", + "title": "Sesame Voice ID. This should be either a name (a built-in voice) or a UUID (a custom voice)." + }, + "model": { + "type": "string", + "description": "This is the model that will be used.", + "enum": [ + "csm-1b" + ] + }, + "chunkPlan": { + "description": "This is the plan for chunking the model output before it is sent to the voice provider.", + "allOf": [ { - "$ref": "#/components/schemas/LangfuseObservabilityPlan", - "title": "Langfuse" + "$ref": "#/components/schemas/ChunkPlan" } - ], + ] + }, + "fallbackPlan": { + "description": "This is the plan for voice provider fallbacks in the event that the primary voice provider fails.", "allOf": [ { - "$ref": "#/components/schemas/LangfuseObservabilityPlan" + "$ref": "#/components/schemas/FallbackPlan" } ] + } + }, + "required": [ + "provider", + "voiceId", + "model" + ] + }, + "SmallestAIVoice": { + "type": "object", + "properties": { + "cachingEnabled": { + "type": "boolean", + "description": "This is the flag to toggle voice caching for the assistant.", + "example": true, + "default": true }, - "backgroundSound": { - "description": "This is the background sound in the call. Default for phone calls is 'office' and default for web calls is 'off'.\nYou can also provide a custom sound by providing a URL to an audio file.", + "provider": { + "type": "string", + "description": "This is the voice provider that will be used.", + "enum": [ + "smallest-ai" + ] + }, + "voiceId": { + "description": "This is the provider-specific ID that will be used.", "oneOf": [ { - "type": "enum", + "type": "string", "enum": [ - "off", - "office" + "emily", + "jasmine", + "arman", + "james", + "mithali", + "aravind", + "raj", + "diya", + "raman", + "ananya", + "isha", + "william", + "aarav", + "monika", + "niharika", + "deepika", + "raghav", + "kajal", + "radhika", + "mansi", + "nisha", + "saurabh", + "pooja", + "saina", + "sanya" ], - "example": "office" + "title": "Preset Voice Options" }, { "type": "string", - "format": "uri", - "example": "https://www.soundjay.com/ambient/sounds/people-in-lounge-1.mp3" + "title": "Smallest AI Voice ID" } ] }, - "hooks": { - "type": "array", - "description": "This is a set of actions that will be performed on certain events.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/CallHookCallEnding", - "title": "CallHookCallEnding" - }, - { - "$ref": "#/components/schemas/CallHookAssistantSpeechInterrupted", - "title": "CallHookAssistantSpeechInterrupted" - }, - { - "$ref": "#/components/schemas/CallHookCustomerSpeechInterrupted", - "title": "CallHookCustomerSpeechInterrupted" - }, - { - "$ref": "#/components/schemas/CallHookCustomerSpeechTimeout", - "title": "CallHookCustomerSpeechTimeout" - } - ] - } + "model": { + "type": "string", + "description": "Smallest AI voice model to use. Defaults to 'lightning' when not specified.", + "enum": [ + "lightning" + ] }, - "credentials": { - "type": "array", - "description": "These are dynamic credentials that will be used for the workflow calls. By default, all the credentials are available for use in the call but you can supplement an additional credentials using this. Dynamic credentials override existing credentials.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/CreateAnthropicCredentialDTO", - "title": "AnthropicCredential" - }, - { - "$ref": "#/components/schemas/CreateAnyscaleCredentialDTO", - "title": "AnyscaleCredential" - }, - { - "$ref": "#/components/schemas/CreateAssemblyAICredentialDTO", - "title": "AssemblyAICredential" - }, - { - "$ref": "#/components/schemas/CreateAzureCredentialDTO", - "title": "AzureCredential" - }, - { - "$ref": "#/components/schemas/CreateAzureOpenAICredentialDTO", - "title": "AzureOpenAICredential" - }, - { - "$ref": "#/components/schemas/CreateByoSipTrunkCredentialDTO", - "title": "ByoSipTrunkCredential" - }, - { - "$ref": "#/components/schemas/CreateCartesiaCredentialDTO", - "title": "CartesiaCredential" - }, - { - "$ref": "#/components/schemas/CreateCerebrasCredentialDTO", - "title": "CerebrasCredential" - }, - { - "$ref": "#/components/schemas/CreateCloudflareCredentialDTO", - "title": "CloudflareCredential" - }, - { - "$ref": "#/components/schemas/CreateCustomLLMCredentialDTO", - "title": "CustomLLMCredential" - }, - { - "$ref": "#/components/schemas/CreateDeepgramCredentialDTO", - "title": "DeepgramCredential" - }, - { - "$ref": "#/components/schemas/CreateDeepInfraCredentialDTO", - "title": "DeepInfraCredential" - }, - { - "$ref": "#/components/schemas/CreateDeepSeekCredentialDTO", - "title": "DeepSeekCredential" - }, - { - "$ref": "#/components/schemas/CreateElevenLabsCredentialDTO", - "title": "ElevenLabsCredential" - }, - { - "$ref": "#/components/schemas/CreateGcpCredentialDTO", - "title": "GcpCredential" - }, - { - "$ref": "#/components/schemas/CreateGladiaCredentialDTO", - "title": "GladiaCredential" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelCredentialDTO", - "title": "GhlCredential" - }, - { - "$ref": "#/components/schemas/CreateGoogleCredentialDTO", - "title": "GoogleCredential" - }, - { - "$ref": "#/components/schemas/CreateGroqCredentialDTO", - "title": "GroqCredential" - }, - { - "$ref": "#/components/schemas/CreateHumeCredentialDTO", - "title": "HumeCredential" - }, - { - "$ref": "#/components/schemas/CreateInflectionAICredentialDTO", - "title": "InflectionAICredential" - }, - { - "$ref": "#/components/schemas/CreateLangfuseCredentialDTO", - "title": "LangfuseCredential" - }, - { - "$ref": "#/components/schemas/CreateLmntCredentialDTO", - "title": "LmntCredential" - }, - { - "$ref": "#/components/schemas/CreateMakeCredentialDTO", - "title": "MakeCredential" - }, - { - "$ref": "#/components/schemas/CreateMistralCredentialDTO", - "title": "MistralCredential" - }, - { - "$ref": "#/components/schemas/CreateNeuphonicCredentialDTO", - "title": "NeuphonicCredential" - }, - { - "$ref": "#/components/schemas/CreateOpenAICredentialDTO", - "title": "OpenAICredential" - }, - { - "$ref": "#/components/schemas/CreateOpenRouterCredentialDTO", - "title": "OpenRouterCredential" - }, - { - "$ref": "#/components/schemas/CreatePerplexityAICredentialDTO", - "title": "PerplexityAICredential" - }, - { - "$ref": "#/components/schemas/CreatePlayHTCredentialDTO", - "title": "PlayHTCredential" - }, - { - "$ref": "#/components/schemas/CreateRimeAICredentialDTO", - "title": "RimeAICredential" - }, - { - "$ref": "#/components/schemas/CreateRunpodCredentialDTO", - "title": "RunpodCredential" - }, - { - "$ref": "#/components/schemas/CreateS3CredentialDTO", - "title": "S3Credential" - }, - { - "$ref": "#/components/schemas/CreateSmallestAICredentialDTO", - "title": "SmallestAICredential" - }, - { - "$ref": "#/components/schemas/CreateSpeechmaticsCredentialDTO", - "title": "SpeechmaticsCredential" - }, - { - "$ref": "#/components/schemas/CreateSupabaseCredentialDTO", - "title": "SupabaseCredential" - }, - { - "$ref": "#/components/schemas/CreateTavusCredentialDTO", - "title": "TavusCredential" - }, - { - "$ref": "#/components/schemas/CreateTogetherAICredentialDTO", - "title": "TogetherAICredential" - }, - { - "$ref": "#/components/schemas/CreateTrieveCredentialDTO", - "title": "TrieveCredential" - }, - { - "$ref": "#/components/schemas/CreateTwilioCredentialDTO", - "title": "TwilioCredential" - }, - { - "$ref": "#/components/schemas/CreateVonageCredentialDTO", - "title": "VonageCredential" - }, - { - "$ref": "#/components/schemas/CreateWebhookCredentialDTO", - "title": "WebhookCredential" - }, - { - "$ref": "#/components/schemas/CreateXAiCredentialDTO", - "title": "XAiCredential" - }, - { - "$ref": "#/components/schemas/CreateGoogleCalendarOAuth2ClientCredentialDTO", - "title": "GoogleCalendarOAuth2ClientCredential" - }, - { - "$ref": "#/components/schemas/CreateGoogleCalendarOAuth2AuthorizationCredentialDTO", - "title": "GoogleCalendarOAuth2AuthorizationCredential" - }, - { - "$ref": "#/components/schemas/CreateGoogleSheetsOAuth2AuthorizationCredentialDTO", - "title": "GoogleSheetsOAuth2AuthorizationCredential" - }, - { - "$ref": "#/components/schemas/CreateSlackOAuth2AuthorizationCredentialDTO", - "title": "SlackOAuth2AuthorizationCredential" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelMCPCredentialDTO", - "title": "GoHighLevelMCPCredential" - }, - { - "$ref": "#/components/schemas/CreateInworldCredentialDTO", - "title": "InworldCredential" - } - ], - "discriminator": { - "propertyName": "provider", - "mapping": { - "11labs": "#/components/schemas/CreateElevenLabsCredentialDTO", - "anthropic": "#/components/schemas/CreateAnthropicCredentialDTO", - "anyscale": "#/components/schemas/CreateAnyscaleCredentialDTO", - "assembly-ai": "#/components/schemas/CreateAssemblyAICredentialDTO", - "azure-openai": "#/components/schemas/CreateAzureOpenAICredentialDTO", - "azure": "#/components/schemas/CreateAzureCredentialDTO", - "byo-sip-trunk": "#/components/schemas/CreateByoSipTrunkCredentialDTO", - "cartesia": "#/components/schemas/CreateCartesiaCredentialDTO", - "cerebras": "#/components/schemas/CreateCerebrasCredentialDTO", - "cloudflare": "#/components/schemas/CreateCloudflareCredentialDTO", - "custom-llm": "#/components/schemas/CreateCustomLLMCredentialDTO", - "deepgram": "#/components/schemas/CreateDeepgramCredentialDTO", - "deepinfra": "#/components/schemas/CreateDeepInfraCredentialDTO", - "deep-seek": "#/components/schemas/CreateDeepSeekCredentialDTO", - "gcp": "#/components/schemas/CreateGcpCredentialDTO", - "gladia": "#/components/schemas/CreateGladiaCredentialDTO", - "gohighlevel": "#/components/schemas/CreateGoHighLevelCredentialDTO", - "google": "#/components/schemas/CreateGoogleCredentialDTO", - "groq": "#/components/schemas/CreateGroqCredentialDTO", - "inflection-ai": "#/components/schemas/CreateInflectionAICredentialDTO", - "langfuse": "#/components/schemas/CreateLangfuseCredentialDTO", - "lmnt": "#/components/schemas/CreateLmntCredentialDTO", - "make": "#/components/schemas/CreateMakeCredentialDTO", - "openai": "#/components/schemas/CreateOpenAICredentialDTO", - "openrouter": "#/components/schemas/CreateOpenRouterCredentialDTO", - "perplexity-ai": "#/components/schemas/CreatePerplexityAICredentialDTO", - "playht": "#/components/schemas/CreatePlayHTCredentialDTO", - "rime-ai": "#/components/schemas/CreateRimeAICredentialDTO", - "runpod": "#/components/schemas/CreateRunpodCredentialDTO", - "s3": "#/components/schemas/CreateS3CredentialDTO", - "supabase": "#/components/schemas/CreateSupabaseCredentialDTO", - "smallest-ai": "#/components/schemas/CreateSmallestAICredentialDTO", - "tavus": "#/components/schemas/CreateTavusCredentialDTO", - "together-ai": "#/components/schemas/CreateTogetherAICredentialDTO", - "twilio": "#/components/schemas/CreateTwilioCredentialDTO", - "vonage": "#/components/schemas/CreateVonageCredentialDTO", - "webhook": "#/components/schemas/CreateWebhookCredentialDTO", - "xai": "#/components/schemas/CreateXAiCredentialDTO", - "neuphonic": "#/components/schemas/CreateNeuphonicCredentialDTO", - "hume": "#/components/schemas/CreateHumeCredentialDTO", - "mistral": "#/components/schemas/CreateMistralCredentialDTO", - "speechmatics": "#/components/schemas/CreateSpeechmaticsCredentialDTO", - "trieve": "#/components/schemas/CreateTrieveCredentialDTO", - "google.calendar.oauth2-client": "#/components/schemas/CreateGoogleCalendarOAuth2ClientCredentialDTO", - "google.calendar.oauth2-authorization": "#/components/schemas/CreateGoogleCalendarOAuth2AuthorizationCredentialDTO", - "google.sheets.oauth2-authorization": "#/components/schemas/CreateGoogleSheetsOAuth2AuthorizationCredentialDTO", - "slack.oauth2-authorization": "#/components/schemas/CreateSlackOAuth2AuthorizationCredentialDTO", - "ghl.oauth2-authorization": "#/components/schemas/CreateGoHighLevelMCPCredentialDTO", - "inworld": "#/components/schemas/CreateInworldCredentialDTO", - "minimax": "#/components/schemas/CreateMinimaxCredentialDTO" - } - } - } - }, - "name": { - "type": "string", - "maxLength": 80 - }, - "edges": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Edge" - } - }, - "globalPrompt": { - "type": "string", - "maxLength": 5000 + "speed": { + "type": "number", + "description": "This is the speed multiplier that will be used.", + "example": null }, - "server": { - "description": "This is where Vapi will send webhooks. You can find all webhooks available along with their shape in ServerMessage schema.\n\nThe order of precedence is:\n\n1. tool.server\n2. workflow.server / assistant.server\n3. phoneNumber.server\n4. org.server", + "chunkPlan": { + "description": "This is the plan for chunking the model output before it is sent to the voice provider.", "allOf": [ { - "$ref": "#/components/schemas/Server" + "$ref": "#/components/schemas/ChunkPlan" } ] }, - "compliancePlan": { - "description": "This is the compliance plan for the workflow. It allows you to configure HIPAA and other compliance settings.", + "fallbackPlan": { + "description": "This is the plan for voice provider fallbacks in the event that the primary voice provider fails.", "allOf": [ { - "$ref": "#/components/schemas/CompliancePlan" + "$ref": "#/components/schemas/FallbackPlan" } ] + } + }, + "required": [ + "provider", + "voiceId" + ] + }, + "TavusConversationProperties": { + "type": "object", + "properties": { + "maxCallDuration": { + "type": "number", + "description": "The maximum duration of the call in seconds. The default `maxCallDuration` is 3600 seconds (1 hour).\nOnce the time limit specified by this parameter has been reached, the conversation will automatically shut down." }, - "analysisPlan": { - "description": "This is the plan for analysis of workflow's calls. Stored in `call.analysis`.", - "allOf": [ - { - "$ref": "#/components/schemas/AnalysisPlan" - } - ] + "participantLeftTimeout": { + "type": "number", + "description": "The duration in seconds after which the call will be automatically shut down once the last participant leaves." }, - "artifactPlan": { - "description": "This is the plan for artifacts generated during workflow's calls. Stored in `call.artifact`.", - "allOf": [ - { - "$ref": "#/components/schemas/ArtifactPlan" - } - ] + "participantAbsentTimeout": { + "type": "number", + "description": "Starting from conversation creation, the duration in seconds after which the call will be automatically shut down if no participant joins the call.\nDefault is 300 seconds (5 minutes)." }, - "startSpeakingPlan": { - "description": "This is the plan for when the workflow nodes should start talking.\n\nYou should configure this if you're running into these issues:\n- The assistant is too slow to start talking after the customer is done speaking.\n- The assistant is too fast to start talking after the customer is done speaking.\n- The assistant is so fast that it's actually interrupting the customer.", - "allOf": [ - { - "$ref": "#/components/schemas/StartSpeakingPlan" - } - ] + "enableRecording": { + "type": "boolean", + "description": "If true, the user will be able to record the conversation." }, - "stopSpeakingPlan": { - "description": "This is the plan for when workflow nodes should stop talking on customer interruption.\n\nYou should configure this if you're running into these issues:\n- The assistant is too slow to recognize customer's interruption.\n- The assistant is too fast to recognize customer's interruption.\n- The assistant is getting interrupted by phrases that are just acknowledgments.\n- The assistant is getting interrupted by background noises.\n- The assistant is not properly stopping -- it starts talking right after getting interrupted.", - "allOf": [ - { - "$ref": "#/components/schemas/StopSpeakingPlan" - } + "enableTranscription": { + "type": "boolean", + "description": "If true, the user will be able to transcribe the conversation.\nYou can find more instructions on displaying transcriptions if you are using your custom DailyJS components here.\nYou need to have an event listener on Daily that listens for `app-messages`." + }, + "applyGreenscreen": { + "type": "boolean", + "description": "If true, the background will be replaced with a greenscreen (RGB values: `[0, 255, 155]`).\nYou can use WebGL on the frontend to make the greenscreen transparent or change its color." + }, + "language": { + "type": "string", + "description": "The language of the conversation. Please provide the **full language name**, not the two-letter code.\nIf you are using your own TTS voice, please ensure it supports the language you provide.\nIf you are using a stock replica or default persona, please note that only ElevenLabs and Cartesia supported languages are available.\nYou can find a full list of supported languages for Cartesia here, for ElevenLabs here, and for PlayHT here." + }, + "recordingS3BucketName": { + "type": "string", + "description": "The name of the S3 bucket where the recording will be stored." + }, + "recordingS3BucketRegion": { + "type": "string", + "description": "The region of the S3 bucket where the recording will be stored." + }, + "awsAssumeRoleArn": { + "type": "string", + "description": "The ARN of the role that will be assumed to access the S3 bucket." + } + } + }, + "TavusVoice": { + "type": "object", + "properties": { + "cachingEnabled": { + "type": "boolean", + "description": "This is the flag to toggle voice caching for the assistant.", + "example": true, + "default": true + }, + "provider": { + "type": "string", + "description": "This is the voice provider that will be used.", + "enum": [ + "tavus" ] }, - "monitorPlan": { - "description": "This is the plan for real-time monitoring of the workflow's calls.\n\nUsage:\n- To enable live listening of the workflow's calls, set `monitorPlan.listenEnabled` to `true`.\n- To enable live control of the workflow's calls, set `monitorPlan.controlEnabled` to `true`.", - "allOf": [ + "voiceId": { + "description": "This is the provider-specific ID that will be used.", + "oneOf": [ { - "$ref": "#/components/schemas/MonitorPlan" + "type": "string", + "enum": [ + "r52da2535a" + ], + "title": "Preset Voice Options" + }, + { + "type": "string", + "title": "Tavus Voice ID" } ] }, - "backgroundSpeechDenoisingPlan": { - "description": "This enables filtering of noise and background speech while the user is talking.\n\nFeatures:\n- Smart denoising using Krisp\n- Fourier denoising\n\nBoth can be used together. Order of precedence:\n- Smart denoising\n- Fourier denoising", + "chunkPlan": { + "description": "This is the plan for chunking the model output before it is sent to the voice provider.", "allOf": [ { - "$ref": "#/components/schemas/BackgroundSpeechDenoisingPlan" + "$ref": "#/components/schemas/ChunkPlan" } ] }, - "credentialIds": { - "description": "These are the credentials that will be used for the workflow calls. By default, all the credentials are available for use in the call but you can provide a subset using this.", - "type": "array", - "items": { - "type": "string" - } + "personaId": { + "type": "string", + "description": "This is the unique identifier for the persona that the replica will use in the conversation." }, - "keypadInputPlan": { - "description": "This is the plan for keypad input handling during workflow calls.", + "callbackUrl": { + "type": "string", + "description": "This is the url that will receive webhooks with updates regarding the conversation state." + }, + "conversationName": { + "type": "string", + "description": "This is the name for the conversation." + }, + "conversationalContext": { + "type": "string", + "description": "This is the context that will be appended to any context provided in the persona, if one is provided." + }, + "customGreeting": { + "type": "string", + "description": "This is the custom greeting that the replica will give once a participant joines the conversation." + }, + "properties": { + "description": "These are optional properties used to customize the conversation.", "allOf": [ { - "$ref": "#/components/schemas/KeypadInputPlan" + "$ref": "#/components/schemas/TavusConversationProperties" } ] - } - }, - "required": [ - "nodes", - "name", - "edges" - ] - }, - "WorkflowOverrides": { - "type": "object", - "properties": { - "variableValues": { - "type": "object", - "description": "These are values that will be used to replace the template variables in the workflow messages and other text-based fields.\nThis uses LiquidJS syntax. https://liquidjs.com/tutorials/intro-to-liquid.html\n\nSo for example, `{{ name }}` will be replaced with the value of `name` in `variableValues`.\n`{{\"now\" | date: \"%b %d, %Y, %I:%M %p\", \"America/New_York\"}}` will be replaced with the current date and time in New York.\n Some VAPI reserved defaults:\n - *customer* - the customer object" - } - } - }, - "TransferPhoneNumberHookAction": { - "type": "object", - "properties": { - "type": { - "type": "string", - "description": "This is the type of action - must be \"transfer\"", - "enum": [ - "transfer" - ] }, - "destination": { - "description": "This is the destination details for the transfer - can be a phone number or SIP URI", - "oneOf": [ - { - "$ref": "#/components/schemas/TransferDestinationNumber", - "title": "NumberTransferDestination" - }, + "fallbackPlan": { + "description": "This is the plan for voice provider fallbacks in the event that the primary voice provider fails.", + "allOf": [ { - "$ref": "#/components/schemas/TransferDestinationSip", - "title": "SipTransferDestination" + "$ref": "#/components/schemas/FallbackPlan" } ] } }, "required": [ - "type" + "provider", + "voiceId" ] }, - "SayPhoneNumberHookAction": { + "VapiPronunciationDictionaryLocator": { "type": "object", "properties": { - "type": { + "pronunciationDictId": { "type": "string", - "description": "This is the type of action - must be \"say\"", - "enum": [ - "say" - ] + "description": "The pronunciation dictionary ID", + "example": "pdict_abc123" }, - "exact": { + "versionId": { "type": "string", - "description": "This is the message to say", - "maxLength": 4000 - } - }, - "required": [ - "type", - "exact" - ] - }, - "PhoneNumberHookCallRinging": { - "type": "object", - "properties": { - "on": { + "description": "Version ID (only used by ElevenLabs, ignored for Cartesia)", + "example": "ver_abc123" + }, + "provider": { "type": "string", - "description": "This is the event to trigger the hook on", + "description": "Provider that hosts this pronunciation dictionary", "enum": [ - "call.ringing" + "cartesia", + "11labs" ], - "maxLength": 1000 - }, - "do": { - "type": "array", - "description": "Only the first action will be executed. Additional actions will be ignored.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/TransferPhoneNumberHookAction", - "title": "TransferPhoneNumberHookAction" - }, - { - "$ref": "#/components/schemas/SayPhoneNumberHookAction", - "title": "SayPhoneNumberHookAction" - } - ] - } + "example": "11labs" } }, "required": [ - "on", - "do" + "pronunciationDictId" ] }, - "PhoneNumberCallEndingHookFilter": { + "VapiVoice": { "type": "object", "properties": { - "type": { + "cachingEnabled": { + "type": "boolean", + "description": "This is the flag to toggle voice caching for the assistant.", + "example": true, + "default": true + }, + "provider": { "type": "string", - "description": "This is the type of filter - currently only \"oneOf\" is supported", + "description": "This is the voice provider that will be used.", "enum": [ - "oneOf" - ], - "maxLength": 1000 + "vapi" + ] }, - "key": { + "voiceId": { "type": "string", - "description": "This is the key to filter on - only \"call.endedReason\" is allowed for phone number call ending hooks", - "enum": [ - "call.endedReason" - ], - "maxLength": 1000 + "description": "The voice to use: a built-in Vapi voice name, or a cloned voice id (used with version 2).", + "example": "Clara" }, - "oneOf": { - "type": "array", - "description": "This is the array of assistant-request related ended reasons to match against", + "version": { + "description": "The Vapi voice routing generation. `latest` auto-updates to the newest generation; version 1 uses legacy mappings; version 2 can use xAI-backed voices when available. When omitted, Version 1 is used. Accepts the string channel ('latest', '1', '2'); legacy numeric values (1, 2) are also accepted and coerced to their string form.", "enum": [ - "assistant-request-failed", - "assistant-request-returned-error", - "assistant-request-returned-unspeakable-error", - "assistant-request-returned-invalid-assistant", - "assistant-request-returned-no-assistant", - "assistant-request-returned-forwarding-phone-number" + "1", + "2", + "latest" ], - "items": { - "type": "string", - "enum": [ - "assistant-request-failed", - "assistant-request-returned-error", - "assistant-request-returned-unspeakable-error", - "assistant-request-returned-invalid-assistant", - "assistant-request-returned-no-assistant", - "assistant-request-returned-forwarding-phone-number" - ] + "oneOf": [ + { + "type": "string", + "enum": [ + "1", + "2", + "latest" + ] + }, + { + "type": "number", + "enum": [ + 1, + 2 + ] + } + ] + }, + "speed": { + "type": "number", + "description": "This is the speed multiplier that will be used.\n\n@default 1", + "minimum": 0.25, + "maximum": 2, + "default": 1 + }, + "language": { + "type": "string", + "description": "Language for Vapi voice synthesis. For Version 2, omit this field or set `auto` for automatic language detection. Version 1 supports legacy Vapi language values.", + "enum": [ + "en-US", + "en-GB", + "en-AU", + "en-CA", + "ja", + "zh", + "de", + "hi", + "fr-FR", + "fr-CA", + "ko", + "pt-BR", + "pt-PT", + "it", + "es-ES", + "es-MX", + "id", + "nl", + "tr", + "fil", + "pl", + "sv", + "bg", + "ro", + "ar-SA", + "ar-AE", + "cs", + "el", + "fi", + "hr", + "ms", + "sk", + "da", + "ta", + "uk", + "ru", + "hu", + "no", + "vi", + "auto", + "en", + "ar", + "ar-EG", + "bn", + "es", + "fr", + "gu", + "he", + "ka", + "kn", + "ml", + "mr", + "pa", + "pt", + "te", + "th", + "tl" + ] + }, + "pronunciationDictionary": { + "description": "List of pronunciation dictionary locators for custom word pronunciations.", + "type": "array", + "items": { + "$ref": "#/components/schemas/VapiPronunciationDictionaryLocator" } + }, + "chunkPlan": { + "description": "This is the plan for chunking the model output before it is sent to the voice provider.", + "allOf": [ + { + "$ref": "#/components/schemas/ChunkPlan" + } + ] } }, "required": [ - "type", - "key", - "oneOf" + "provider", + "voiceId" ] }, - "PhoneNumberHookCallEnding": { + "InworldVoice": { "type": "object", "properties": { - "on": { + "cachingEnabled": { + "type": "boolean", + "description": "This is the flag to toggle voice caching for the assistant.", + "example": true, + "default": true + }, + "provider": { "type": "string", - "description": "This is the event to trigger the hook on", + "description": "This is the voice provider that will be used.", "enum": [ - "call.ending" + "inworld" + ] + }, + "voiceId": { + "type": "string", + "description": "Available voices by language:\n• en: Alex, Ashley, Craig, Deborah, Dennis, Edward, Elizabeth, Hades, Julia, Pixie, Mark, Olivia, Priya, Ronald, Sarah, Shaun, Theodore, Timothy, Wendy, Dominus, Hana, Clive, Carter, Blake, Luna\n• zh: Yichen, Xiaoyin, Xinyi, Jing\n• nl: Erik, Katrien, Lennart, Lore\n• fr: Alain, Hélène, Mathieu, Étienne\n• de: Johanna, Josef\n• it: Gianni, Orietta\n• ja: Asuka, Satoshi\n• ko: Hyunwoo, Minji, Seojun, Yoona\n• pl: Szymon, Wojciech\n• pt: Heitor, Maitê\n• es: Diego, Lupita, Miguel, Rafael\n• ru: Svetlana, Elena, Dmitry, Nikolai\n• hi: Riya, Manoj\n• he: Yael, Oren\n• ar: Nour, Omar", + "maxLength": 120, + "title": "Inworld Voice ID", + "enum": [ + "Alex", + "Ashley", + "Craig", + "Deborah", + "Dennis", + "Edward", + "Elizabeth", + "Hades", + "Julia", + "Pixie", + "Mark", + "Olivia", + "Priya", + "Ronald", + "Sarah", + "Shaun", + "Theodore", + "Timothy", + "Wendy", + "Dominus", + "Hana", + "Clive", + "Carter", + "Blake", + "Luna", + "Yichen", + "Xiaoyin", + "Xinyi", + "Jing", + "Erik", + "Katrien", + "Lennart", + "Lore", + "Alain", + "Hélène", + "Mathieu", + "Étienne", + "Johanna", + "Josef", + "Gianni", + "Orietta", + "Asuka", + "Satoshi", + "Hyunwoo", + "Minji", + "Seojun", + "Yoona", + "Szymon", + "Wojciech", + "Heitor", + "Maitê", + "Diego", + "Lupita", + "Miguel", + "Rafael", + "Svetlana", + "Elena", + "Dmitry", + "Nikolai", + "Riya", + "Manoj", + "Yael", + "Oren", + "Nour", + "Omar" ], - "maxLength": 1000 + "example": "Alex" }, - "filters": { - "type": "array", - "description": "Optional filters to decide when to trigger - restricted to assistant-request related ended reasons", - "items": { - "$ref": "#/components/schemas/PhoneNumberCallEndingHookFilter" - } + "model": { + "type": "string", + "description": "This is the model that will be used.", + "enum": [ + "inworld-tts-1" + ], + "default": "inworld-tts-1" }, - "do": { - "description": "This is the action to perform when the hook triggers", - "oneOf": [ + "languageCode": { + "type": "string", + "description": "Language code for Inworld TTS synthesis", + "default": "en", + "enum": [ + "en", + "zh", + "ko", + "nl", + "fr", + "es", + "ja", + "de", + "it", + "pl", + "pt", + "ru", + "hi", + "he", + "ar" + ] + }, + "temperature": { + "type": "number", + "description": "A floating point number between 0, exclusive, and 2, inclusive. If equal to null or not provided, the model's default temperature of 1.1 will be used. The temperature parameter controls variance.\nHigher values will make the output more random and can lead to more expressive results. Lower values will make it more deterministic.\nSee https://docs.inworld.ai/docs/tts/capabilities/generating-audio#additional-configurations for more details.", + "minimum": 0.1, + "maximum": 2, + "default": 1.1, + "example": null + }, + "speakingRate": { + "type": "number", + "description": "A floating point number between 0.5, inclusive, and 1.5, inclusive. If equal to null or not provided, the model's default speaking speed of 1.0 will be used.\nValues above 0.8 are recommended for higher quality.\nSee https://docs.inworld.ai/docs/tts/capabilities/generating-audio#additional-configurations for more details.", + "minimum": 0.5, + "maximum": 1.5, + "default": 1, + "example": null + }, + "chunkPlan": { + "description": "This is the plan for chunking the model output before it is sent to the voice provider.", + "allOf": [ { - "$ref": "#/components/schemas/TransferPhoneNumberHookAction", - "title": "TransferPhoneNumberHookAction" - }, + "$ref": "#/components/schemas/ChunkPlan" + } + ] + }, + "fallbackPlan": { + "description": "This is the plan for voice provider fallbacks in the event that the primary voice provider fails.", + "allOf": [ { - "$ref": "#/components/schemas/SayPhoneNumberHookAction", - "title": "SayPhoneNumberHookAction" + "$ref": "#/components/schemas/FallbackPlan" } ] } }, "required": [ - "on" + "provider", + "voiceId" ] }, - "ImportTwilioPhoneNumberDTO": { + "MinimaxVoice": { "type": "object", "properties": { - "fallbackDestination": { - "description": "This is the fallback destination an inbound call will be transferred to if:\n1. `assistantId` is not set\n2. `squadId` is not set\n3. and, `assistant-request` message to the `serverUrl` fails\n\nIf this is not set and above conditions are met, the inbound call is hung up with an error message.", - "oneOf": [ - { - "$ref": "#/components/schemas/TransferDestinationNumber", - "title": "NumberTransferDestination" - }, - { - "$ref": "#/components/schemas/TransferDestinationSip", - "title": "SipTransferDestination" - } - ] - }, - "hooks": { - "type": "array", - "description": "This is the hooks that will be used for incoming calls to this phone number.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/PhoneNumberHookCallRinging", - "title": "PhoneNumberHookCallRinging" - }, - { - "$ref": "#/components/schemas/PhoneNumberHookCallEnding", - "title": "PhoneNumberHookCallEnding" - } - ] - } - }, - "smsEnabled": { + "cachingEnabled": { "type": "boolean", - "description": "Controls whether Vapi sets the messaging webhook URL on the Twilio number during import.\n\nIf set to `false`, Vapi will not update the Twilio messaging URL, leaving it as is.\nIf `true` or omitted (default), Vapi will configure both the voice and messaging URLs.\n\n@default true", + "description": "This is the flag to toggle voice caching for the assistant.", + "example": true, "default": true }, - "twilioPhoneNumber": { + "provider": { "type": "string", - "description": "These are the digits of the phone number you own on your Twilio.", - "deprecated": true + "description": "This is the voice provider that will be used.", + "enum": [ + "minimax" + ] }, - "twilioAccountSid": { + "voiceId": { "type": "string", - "description": "This is your Twilio Account SID that will be used to handle this phone number." + "description": "This is the provider-specific ID that will be used. Use a voice from MINIMAX_PREDEFINED_VOICES or a custom cloned voice ID.", + "title": "This is the Minimax Voice ID" }, - "twilioAuthToken": { + "model": { "type": "string", - "description": "This is the Twilio Auth Token that will be used to handle this phone number." + "description": "This is the model that will be used. Options are 'speech-02-hd' and 'speech-02-turbo'.\nspeech-02-hd is optimized for high-fidelity applications like voiceovers and audiobooks.\nspeech-02-turbo is designed for real-time applications with low latency.\n\n@default \"speech-02-turbo\"", + "enum": [ + "speech-02-hd", + "speech-02-turbo", + "speech-2.5-turbo-preview" + ], + "example": "speech-02-turbo", + "default": "speech-02-turbo" }, - "twilioApiKey": { + "emotion": { "type": "string", - "description": "This is the Twilio API Key that will be used to handle this phone number. If AuthToken is provided, this will be ignored." + "description": "The emotion to use for the voice. If not provided, will use auto-detect mode.\nOptions include: 'happy', 'sad', 'angry', 'fearful', 'surprised', 'disgusted', 'neutral'", + "example": "happy" }, - "twilioApiSecret": { + "subtitleType": { "type": "string", - "description": "This is the Twilio API Secret that will be used to handle this phone number. If AuthToken is provided, this will be ignored." + "description": "Controls the granularity of subtitle/timing data returned by Minimax\nduring synthesis. Set to 'word' to receive per-word timestamps in\nassistant.speechStarted events for karaoke-style caption rendering.\n\n@default \"sentence\"", + "enum": [ + "word", + "sentence" + ], + "default": "sentence" }, - "name": { - "type": "string", - "description": "This is the name of the phone number. This is just for your own reference.", - "maxLength": 40 + "pitch": { + "type": "number", + "description": "Voice pitch adjustment. Range from -12 to 12 semitones.\n@default 0", + "minimum": -12, + "maximum": 12, + "example": 0, + "default": 0 }, - "assistantId": { - "type": "string", - "description": "This is the assistant that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId` nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + "speed": { + "type": "number", + "description": "Voice speed adjustment. Range from 0.5 to 2.0.\n@default 1.0", + "minimum": 0.5, + "maximum": 2, + "example": 1, + "default": 1 }, - "workflowId": { + "volume": { + "type": "number", + "description": "Voice volume adjustment. Range from 0.5 to 2.0.\n@default 1.0", + "minimum": 0.5, + "maximum": 2, + "example": 1, + "default": 1 + }, + "region": { "type": "string", - "description": "This is the workflow that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + "description": "The region for Minimax API. Defaults to \"worldwide\".", + "enum": [ + "worldwide", + "china" + ], + "default": "worldwide" }, - "squadId": { + "languageBoost": { "type": "string", - "description": "This is the squad that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + "description": "Language hint for MiniMax T2A. Example: yue (Cantonese), zh (Chinese), en (English).", + "enum": [ + "Chinese", + "Chinese,Yue", + "English", + "Arabic", + "Russian", + "Spanish", + "French", + "Portuguese", + "German", + "Turkish", + "Dutch", + "Ukrainian", + "Vietnamese", + "Indonesian", + "Japanese", + "Italian", + "Korean", + "Thai", + "Polish", + "Romanian", + "Greek", + "Czech", + "Finnish", + "Hindi", + "Bulgarian", + "Danish", + "Hebrew", + "Malay", + "Persian", + "Slovak", + "Swedish", + "Croatian", + "Filipino", + "Hungarian", + "Norwegian", + "Slovenian", + "Catalan", + "Nynorsk", + "Tamil", + "Afrikaans", + "auto" + ] }, - "server": { - "description": "This is where Vapi will send webhooks. You can find all webhooks available along with their shape in ServerMessage schema.\n\nThe order of precedence is:\n\n1. assistant.server\n2. phoneNumber.server\n3. org.server", + "textNormalizationEnabled": { + "type": "boolean", + "description": "Enable MiniMax text normalization to improve number reading and formatting.", + "default": true + }, + "chunkPlan": { + "description": "This is the plan for chunking the model output before it is sent to the voice provider.", "allOf": [ { - "$ref": "#/components/schemas/Server" + "$ref": "#/components/schemas/ChunkPlan" + } + ] + }, + "fallbackPlan": { + "description": "This is the plan for voice provider fallbacks in the event that the primary voice provider fails.", + "allOf": [ + { + "$ref": "#/components/schemas/FallbackPlan" } ] } }, "required": [ - "twilioPhoneNumber", - "twilioAccountSid" + "provider", + "voiceId" ] }, - "CreateCustomerDTO": { + "FallbackMinimaxVoice": { "type": "object", "properties": { - "numberE164CheckEnabled": { + "cachingEnabled": { "type": "boolean", - "description": "This is the flag to toggle the E164 check for the `number` field. This is an advanced property which should be used if you know your use case requires it.\n\nUse cases:\n- `false`: To allow non-E164 numbers like `+001234567890`, `1234`, or `abc`. This is useful for dialing out to non-E164 numbers on your SIP trunks.\n- `true` (default): To allow only E164 numbers like `+14155551234`. This is standard for PSTN calls.\n\nIf `false`, the `number` is still required to only contain alphanumeric characters (regex: `/^\\+?[a-zA-Z0-9]+$/`).\n\n@default true (E164 check is enabled)", + "description": "This is the flag to toggle voice caching for the assistant.", + "example": true, "default": true }, - "extension": { + "provider": { "type": "string", - "description": "This is the extension that will be dialed after the call is answered.", - "maxLength": 10, - "example": null - }, - "assistantOverrides": { - "description": "These are the overrides for the assistant's settings and template variables specific to this customer.\nThis allows customization of the assistant's behavior for individual customers in batch calls.", - "allOf": [ - { - "$ref": "#/components/schemas/AssistantOverrides" - } + "description": "This is the voice provider that will be used.", + "enum": [ + "minimax" ] }, - "number": { + "voiceId": { "type": "string", - "description": "This is the number of the customer.", - "minLength": 3, - "maxLength": 40 + "description": "This is the provider-specific ID that will be used. Use a voice from MINIMAX_PREDEFINED_VOICES or a custom cloned voice ID.", + "title": "This is the Minimax Voice ID" }, - "sipUri": { + "model": { "type": "string", - "description": "This is the SIP URI of the customer." + "description": "This is the model that will be used. Options are 'speech-02-hd' and 'speech-02-turbo'.\nspeech-02-hd is optimized for high-fidelity applications like voiceovers and audiobooks.\nspeech-02-turbo is designed for real-time applications with low latency.\n\n@default \"speech-02-turbo\"", + "enum": [ + "speech-02-hd", + "speech-02-turbo", + "speech-2.5-turbo-preview" + ], + "example": "speech-02-turbo", + "default": "speech-02-turbo" }, - "name": { + "emotion": { "type": "string", - "description": "This is the name of the customer. This is just for your own reference.\n\nFor SIP inbound calls, this is extracted from the `From` SIP header with format `\"Display Name\" `.", - "maxLength": 40 + "description": "The emotion to use for the voice. If not provided, will use auto-detect mode.\nOptions include: 'happy', 'sad', 'angry', 'fearful', 'surprised', 'disgusted', 'neutral'", + "example": "happy" }, - "email": { + "subtitleType": { "type": "string", - "description": "This is the email of the customer.", - "maxLength": 40 + "description": "Controls the granularity of subtitle/timing data returned by Minimax\nduring synthesis. Set to 'word' to receive per-word timestamps in\nassistant.speechStarted events for karaoke-style caption rendering.\n\n@default \"sentence\"", + "enum": [ + "word", + "sentence" + ], + "default": "sentence" }, - "externalId": { - "type": "string", - "description": "This is the external ID of the customer.", - "maxLength": 40 - } - } - }, - "SchedulePlan": { - "type": "object", - "properties": { - "earliestAt": { - "format": "date-time", - "type": "string", - "description": "This is the ISO 8601 date-time string of the earliest time the call can be scheduled." + "pitch": { + "type": "number", + "description": "Voice pitch adjustment. Range from -12 to 12 semitones.\n@default 0", + "minimum": -12, + "maximum": 12, + "example": 0, + "default": 0 }, - "latestAt": { - "format": "date-time", + "speed": { + "type": "number", + "description": "Voice speed adjustment. Range from 0.5 to 2.0.\n@default 1.0", + "minimum": 0.5, + "maximum": 2, + "example": 1, + "default": 1 + }, + "volume": { + "type": "number", + "description": "Voice volume adjustment. Range from 0.5 to 2.0.\n@default 1.0", + "minimum": 0.5, + "maximum": 2, + "example": 1, + "default": 1 + }, + "region": { "type": "string", - "description": "This is the ISO 8601 date-time string of the latest time the call can be scheduled." - } - }, - "required": [ - "earliestAt" - ] - }, - "Call": { - "type": "object", - "properties": { - "type": { + "description": "The region for Minimax API. Defaults to \"worldwide\".", + "enum": [ + "worldwide", + "china" + ], + "default": "worldwide" + }, + "languageBoost": { "type": "string", - "description": "This is the type of call.", + "description": "Language hint for MiniMax T2A. Example: yue (Cantonese), zh (Chinese), en (English).", "enum": [ - "inboundPhoneCall", - "outboundPhoneCall", - "webCall", - "vapi.websocketCall" + "Chinese", + "Chinese,Yue", + "English", + "Arabic", + "Russian", + "Spanish", + "French", + "Portuguese", + "German", + "Turkish", + "Dutch", + "Ukrainian", + "Vietnamese", + "Indonesian", + "Japanese", + "Italian", + "Korean", + "Thai", + "Polish", + "Romanian", + "Greek", + "Czech", + "Finnish", + "Hindi", + "Bulgarian", + "Danish", + "Hebrew", + "Malay", + "Persian", + "Slovak", + "Swedish", + "Croatian", + "Filipino", + "Hungarian", + "Norwegian", + "Slovenian", + "Catalan", + "Nynorsk", + "Tamil", + "Afrikaans", + "auto" ] }, - "costs": { - "type": "array", - "description": "These are the costs of individual components of the call in USD.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/TransportCost", - "title": "TransportCost" - }, - { - "$ref": "#/components/schemas/TranscriberCost", - "title": "TranscriberCost" - }, - { - "$ref": "#/components/schemas/ModelCost", - "title": "ModelCost" - }, - { - "$ref": "#/components/schemas/VoiceCost", - "title": "VoiceCost" - }, - { - "$ref": "#/components/schemas/VapiCost", - "title": "VapiCost" - }, - { - "$ref": "#/components/schemas/VoicemailDetectionCost", - "title": "VoicemailDetectionCost" - }, - { - "$ref": "#/components/schemas/AnalysisCost", - "title": "AnalysisCost" - }, - { - "$ref": "#/components/schemas/KnowledgeBaseCost", - "title": "KnowledgeBaseCost" - } - ] - } + "textNormalizationEnabled": { + "type": "boolean", + "description": "Enable MiniMax text normalization to improve number reading and formatting.", + "default": true }, - "messages": { + "chunkPlan": { + "description": "This is the plan for chunking the model output before it is sent to the voice provider.", + "allOf": [ + { + "$ref": "#/components/schemas/ChunkPlan" + } + ] + } + }, + "required": [ + "provider", + "voiceId" + ] + }, + "FallbackWellSaidVoice": { + "type": "object", + "properties": { + "cachingEnabled": { + "type": "boolean", + "description": "This is the flag to toggle voice caching for the assistant.", + "example": true, + "default": true + }, + "provider": { + "type": "string", + "description": "This is the voice provider that will be used.", + "enum": [ + "wellsaid" + ] + }, + "voiceId": { + "type": "string", + "description": "The WellSaid speaker ID to synthesize." + }, + "model": { + "type": "string", + "description": "This is the model that will be used.", + "enum": [ + "caruso", + "legacy" + ] + }, + "enableSsml": { + "type": "boolean", + "description": "Enables limited SSML translation for input text." + }, + "libraryIds": { + "description": "Array of library IDs to use for voice synthesis.", "type": "array", "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/UserMessage", - "title": "UserMessage" - }, - { - "$ref": "#/components/schemas/SystemMessage", - "title": "SystemMessage" - }, - { - "$ref": "#/components/schemas/BotMessage", - "title": "BotMessage" - }, - { - "$ref": "#/components/schemas/ToolCallMessage", - "title": "ToolCallMessage" - }, - { - "$ref": "#/components/schemas/ToolCallResultMessage", - "title": "ToolCallResultMessage" - } - ] + "type": "string" } }, - "phoneCallProvider": { + "chunkPlan": { + "description": "This is the plan for chunking the model output before it is sent to the voice provider.", + "allOf": [ + { + "$ref": "#/components/schemas/ChunkPlan" + } + ] + } + }, + "required": [ + "provider", + "voiceId" + ] + }, + "XaiVoice": { + "type": "object", + "properties": { + "cachingEnabled": { + "type": "boolean", + "description": "This is the flag to toggle voice caching for the assistant.", + "example": true, + "default": true + }, + "provider": { "type": "string", - "description": "This is the provider of the call.\n\nOnly relevant for `outboundPhoneCall` and `inboundPhoneCall` type.", - "deprecated": true, + "description": "This is the voice provider that will be used.", "enum": [ - "twilio", - "vonage", - "vapi", - "telnyx" + "xai" ] }, - "phoneCallTransport": { + "voiceId": { "type": "string", - "description": "This is the transport of the phone call.\n\nOnly relevant for `outboundPhoneCall` and `inboundPhoneCall` type.", + "description": "Built-in voices: eve, ara, rex, sal, leo. Cloned voice IDs are also accepted.", + "maxLength": 120, + "title": "xAI Voice ID", "enum": [ - "sip", - "pstn" + "eve", + "ara", + "rex", + "sal", + "leo" + ], + "example": "eve" + }, + "language": { + "type": "string", + "description": "BCP-47 language code for xAI TTS synthesis.", + "enum": [ + "auto", + "en", + "ar-EG", + "ar-SA", + "ar-AE", + "bn", + "zh", + "fr", + "de", + "hi", + "id", + "it", + "ja", + "ko", + "pt-BR", + "pt-PT", + "ru", + "es-MX", + "es-ES", + "tr", + "vi" + ], + "default": "en" + }, + "speed": { + "type": "number", + "description": "Speed multiplier for xAI TTS synthesis.", + "minimum": 0.7, + "maximum": 1.5, + "default": 1.1 + }, + "chunkPlan": { + "description": "This is the plan for chunking the model output before it is sent to the voice provider.", + "allOf": [ + { + "$ref": "#/components/schemas/ChunkPlan" + } ] }, - "status": { + "fallbackPlan": { + "description": "This is the plan for voice provider fallbacks in the event that the primary voice provider fails.", + "allOf": [ + { + "$ref": "#/components/schemas/FallbackPlan" + } + ] + } + }, + "required": [ + "provider", + "voiceId" + ] + }, + "MicrosoftVoice": { + "type": "object", + "properties": { + "cachingEnabled": { + "type": "boolean", + "description": "This is the flag to toggle voice caching for the assistant.", + "example": true, + "default": true + }, + "provider": { "type": "string", - "description": "This is the status of the call.", + "description": "This is the voice provider that will be used.", "enum": [ - "scheduled", - "queued", - "ringing", - "in-progress", - "forwarding", - "ended" + "microsoft" ] }, - "endedReason": { + "voiceId": { "type": "string", - "description": "This is the explanation for how the call ended.", + "description": "MAI-Voice-2 voice ID. Built-in voices listed in enum.", + "enum": [ + "de-DE-Klaus:MAI-Voice-2", + "de-DE-Mia:MAI-Voice-2", + "en-AU-Lisa:MAI-Voice-2", + "en-US-Ethan:MAI-Voice-2", + "en-US-Grant:MAI-Voice-2", + "en-US-Harper:MAI-Voice-2", + "en-US-Iris:MAI-Voice-2", + "en-US-Jasper:MAI-Voice-2", + "en-US-Olivia:MAI-Voice-2", + "es-ES-Marta:MAI-Voice-2", + "es-MX-Alejo:MAI-Voice-2", + "es-MX-Valeria:MAI-Voice-2", + "fr-FR-Marc:MAI-Voice-2", + "fr-FR-Soleil:MAI-Voice-2", + "hi-IN-Arjun:MAI-Voice-2", + "hi-IN-Dhruv:MAI-Voice-2", + "hi-IN-Kavya:MAI-Voice-2", + "hi-IN-Priya:MAI-Voice-2", + "hu-HU-Bence:MAI-Voice-2", + "hu-HU-Levente:MAI-Voice-2", + "hu-HU-Lilla:MAI-Voice-2", + "hu-HU-Réka:MAI-Voice-2", + "it-IT-Luca:MAI-Voice-2", + "it-IT-Rosa:MAI-Voice-2", + "ko-KR-Hana:MAI-Voice-2", + "ko-KR-Junho:MAI-Voice-2", + "nl-NL-Fleur:MAI-Voice-2", + "nl-NL-Sander:MAI-Voice-2", + "pt-BR-Caio:MAI-Voice-2", + "pt-BR-Luana:MAI-Voice-2", + "pt-BR-Pedro:MAI-Voice-2", + "pt-BR-Rafael:MAI-Voice-2", + "pt-PT-Rui:MAI-Voice-2", + "ro-RO-Andrei:MAI-Voice-2", + "ro-RO-Elena:MAI-Voice-2", + "ro-RO-Ioana:MAI-Voice-2", + "ro-RO-Radu:MAI-Voice-2", + "ru-RU-Lev:MAI-Voice-2", + "ru-RU-Masha:MAI-Voice-2", + "th-TH-Krit:MAI-Voice-2", + "th-TH-Nattapong:MAI-Voice-2", + "tr-TR-Aydin:MAI-Voice-2", + "tr-TR-Elif:MAI-Voice-2", + "zh-CN-Bo:MAI-Voice-2", + "zh-CN-Lan:MAI-Voice-2", + "zh-CN-Mei:MAI-Voice-2" + ], + "example": "en-US-Ethan:MAI-Voice-2" + }, + "style": { + "type": "string", + "description": "Speaking style applied via mstts:express-as on every request. Unknown styles are ignored by Azure and fall back to neutral.", + "enum": [ + "adventurous", + "angry", + "caring", + "cheerful", + "confused", + "curious", + "determined", + "disappointed", + "disgusted", + "embarrassed", + "empathy", + "encouraging", + "excited", + "fearful", + "friendly", + "happy", + "hopeful", + "jealous", + "joyful", + "nostalgic", + "reflective", + "regretful", + "relieved", + "sad", + "serious", + "shouting", + "softvoice", + "surprised", + "whispering" + ], + "example": "happy" + }, + "styleDegree": { + "type": "number", + "description": "Style intensity (0.01–2). Default 1 = the predefined style strength. Only applies when `style` is set.", + "minimum": 0.01, + "maximum": 2, + "default": 1 + }, + "role": { + "type": "string", + "description": "Role-play (age/gender imitation). Requires `style` to be set; ignored otherwise.", "enum": [ - "call-start-error-neither-assistant-nor-server-set", - "assistant-request-failed", - "assistant-request-returned-error", - "assistant-request-returned-unspeakable-error", - "assistant-request-returned-invalid-assistant", - "assistant-request-returned-no-assistant", - "assistant-request-returned-forwarding-phone-number", - "scheduled-call-deleted", - "call.start.error-vapifault-get-org", - "call.start.error-vapifault-get-subscription", - "call.start.error-get-assistant", - "call.start.error-get-phone-number", - "call.start.error-get-customer", - "call.start.error-get-resources-validation", - "call.start.error-vapi-number-international", - "call.start.error-vapi-number-outbound-daily-limit", - "call.start.error-get-transport", - "call.start.error-subscription-wallet-does-not-exist", - "call.start.error-subscription-frozen", - "call.start.error-subscription-insufficient-credits", - "call.start.error-subscription-upgrade-failed", - "call.start.error-subscription-concurrency-limit-reached", - "assistant-not-valid", - "database-error", - "assistant-not-found", - "pipeline-error-openai-voice-failed", - "pipeline-error-cartesia-voice-failed", - "pipeline-error-deepgram-voice-failed", - "pipeline-error-eleven-labs-voice-failed", - "pipeline-error-playht-voice-failed", - "pipeline-error-lmnt-voice-failed", - "pipeline-error-azure-voice-failed", - "pipeline-error-rime-ai-voice-failed", - "pipeline-error-smallest-ai-voice-failed", - "pipeline-error-neuphonic-voice-failed", - "pipeline-error-hume-voice-failed", - "pipeline-error-sesame-voice-failed", - "pipeline-error-inworld-voice-failed", - "pipeline-error-minimax-voice-failed", - "pipeline-error-tavus-video-failed", - "call.in-progress.error-vapifault-openai-voice-failed", - "call.in-progress.error-vapifault-cartesia-voice-failed", - "call.in-progress.error-vapifault-deepgram-voice-failed", - "call.in-progress.error-vapifault-eleven-labs-voice-failed", - "call.in-progress.error-vapifault-playht-voice-failed", - "call.in-progress.error-vapifault-lmnt-voice-failed", - "call.in-progress.error-vapifault-azure-voice-failed", - "call.in-progress.error-vapifault-rime-ai-voice-failed", - "call.in-progress.error-vapifault-smallest-ai-voice-failed", - "call.in-progress.error-vapifault-neuphonic-voice-failed", - "call.in-progress.error-vapifault-hume-voice-failed", - "call.in-progress.error-vapifault-sesame-voice-failed", - "call.in-progress.error-vapifault-inworld-voice-failed", - "call.in-progress.error-vapifault-minimax-voice-failed", - "call.in-progress.error-vapifault-tavus-video-failed", - "pipeline-error-vapi-llm-failed", - "pipeline-error-vapi-400-bad-request-validation-failed", - "pipeline-error-vapi-401-unauthorized", - "pipeline-error-vapi-403-model-access-denied", - "pipeline-error-vapi-429-exceeded-quota", - "pipeline-error-vapi-500-server-error", - "pipeline-error-vapi-503-server-overloaded-error", - "call.in-progress.error-vapifault-vapi-llm-failed", - "call.in-progress.error-vapifault-vapi-400-bad-request-validation-failed", - "call.in-progress.error-vapifault-vapi-401-unauthorized", - "call.in-progress.error-vapifault-vapi-403-model-access-denied", - "call.in-progress.error-vapifault-vapi-429-exceeded-quota", - "call.in-progress.error-providerfault-vapi-500-server-error", - "call.in-progress.error-providerfault-vapi-503-server-overloaded-error", - "pipeline-error-deepgram-transcriber-failed", - "call.in-progress.error-vapifault-deepgram-transcriber-failed", - "pipeline-error-gladia-transcriber-failed", - "call.in-progress.error-vapifault-gladia-transcriber-failed", - "pipeline-error-speechmatics-transcriber-failed", - "call.in-progress.error-vapifault-speechmatics-transcriber-failed", - "pipeline-error-assembly-ai-transcriber-failed", - "pipeline-error-assembly-ai-returning-400-insufficent-funds", - "pipeline-error-assembly-ai-returning-400-paid-only-feature", - "pipeline-error-assembly-ai-returning-401-invalid-credentials", - "pipeline-error-assembly-ai-returning-500-invalid-schema", - "pipeline-error-assembly-ai-returning-500-word-boost-parsing-failed", - "call.in-progress.error-vapifault-assembly-ai-transcriber-failed", - "call.in-progress.error-vapifault-assembly-ai-returning-400-insufficent-funds", - "call.in-progress.error-vapifault-assembly-ai-returning-400-paid-only-feature", - "call.in-progress.error-vapifault-assembly-ai-returning-401-invalid-credentials", - "call.in-progress.error-vapifault-assembly-ai-returning-500-invalid-schema", - "call.in-progress.error-vapifault-assembly-ai-returning-500-word-boost-parsing-failed", - "pipeline-error-talkscriber-transcriber-failed", - "call.in-progress.error-vapifault-talkscriber-transcriber-failed", - "pipeline-error-azure-speech-transcriber-failed", - "call.in-progress.error-vapifault-azure-speech-transcriber-failed", - "call.in-progress.error-pipeline-no-available-llm-model", - "worker-shutdown", - "vonage-disconnected", - "vonage-failed-to-connect-call", - "vonage-completed", - "phone-call-provider-bypass-enabled-but-no-call-received", - "call.in-progress.error-providerfault-transport-never-connected", - "call.in-progress.error-vapifault-worker-not-available", - "call.in-progress.error-vapifault-transport-never-connected", - "call.in-progress.error-vapifault-transport-connected-but-call-not-active", - "call.in-progress.error-vapifault-call-started-but-connection-to-transport-missing", - "call.in-progress.error-vapifault-worker-died", - "call.in-progress.twilio-completed-call", - "call.in-progress.sip-completed-call", - "call.in-progress.error-vapifault-openai-llm-failed", - "call.in-progress.error-vapifault-azure-openai-llm-failed", - "call.in-progress.error-vapifault-groq-llm-failed", - "call.in-progress.error-vapifault-google-llm-failed", - "call.in-progress.error-vapifault-xai-llm-failed", - "call.in-progress.error-vapifault-mistral-llm-failed", - "call.in-progress.error-vapifault-inflection-ai-llm-failed", - "call.in-progress.error-vapifault-cerebras-llm-failed", - "call.in-progress.error-vapifault-deep-seek-llm-failed", - "call.in-progress.error-vapifault-chat-pipeline-failed-to-start", - "pipeline-error-openai-400-bad-request-validation-failed", - "pipeline-error-openai-401-unauthorized", - "pipeline-error-openai-401-incorrect-api-key", - "pipeline-error-openai-401-account-not-in-organization", - "pipeline-error-openai-403-model-access-denied", - "pipeline-error-openai-429-exceeded-quota", - "pipeline-error-openai-429-rate-limit-reached", - "pipeline-error-openai-500-server-error", - "pipeline-error-openai-503-server-overloaded-error", - "pipeline-error-openai-llm-failed", - "call.in-progress.error-vapifault-openai-400-bad-request-validation-failed", - "call.in-progress.error-vapifault-openai-401-unauthorized", - "call.in-progress.error-vapifault-openai-401-incorrect-api-key", - "call.in-progress.error-vapifault-openai-401-account-not-in-organization", - "call.in-progress.error-vapifault-openai-403-model-access-denied", - "call.in-progress.error-vapifault-openai-429-exceeded-quota", - "call.in-progress.error-vapifault-openai-429-rate-limit-reached", - "call.in-progress.error-providerfault-openai-500-server-error", - "call.in-progress.error-providerfault-openai-503-server-overloaded-error", - "pipeline-error-azure-openai-400-bad-request-validation-failed", - "pipeline-error-azure-openai-401-unauthorized", - "pipeline-error-azure-openai-403-model-access-denied", - "pipeline-error-azure-openai-429-exceeded-quota", - "pipeline-error-azure-openai-500-server-error", - "pipeline-error-azure-openai-503-server-overloaded-error", - "pipeline-error-azure-openai-llm-failed", - "call.in-progress.error-vapifault-azure-openai-400-bad-request-validation-failed", - "call.in-progress.error-vapifault-azure-openai-401-unauthorized", - "call.in-progress.error-vapifault-azure-openai-403-model-access-denied", - "call.in-progress.error-vapifault-azure-openai-429-exceeded-quota", - "call.in-progress.error-providerfault-azure-openai-500-server-error", - "call.in-progress.error-providerfault-azure-openai-503-server-overloaded-error", - "pipeline-error-google-400-bad-request-validation-failed", - "pipeline-error-google-401-unauthorized", - "pipeline-error-google-403-model-access-denied", - "pipeline-error-google-429-exceeded-quota", - "pipeline-error-google-500-server-error", - "pipeline-error-google-503-server-overloaded-error", - "pipeline-error-google-llm-failed", - "call.in-progress.error-vapifault-google-400-bad-request-validation-failed", - "call.in-progress.error-vapifault-google-401-unauthorized", - "call.in-progress.error-vapifault-google-403-model-access-denied", - "call.in-progress.error-vapifault-google-429-exceeded-quota", - "call.in-progress.error-providerfault-google-500-server-error", - "call.in-progress.error-providerfault-google-503-server-overloaded-error", - "pipeline-error-xai-400-bad-request-validation-failed", - "pipeline-error-xai-401-unauthorized", - "pipeline-error-xai-403-model-access-denied", - "pipeline-error-xai-429-exceeded-quota", - "pipeline-error-xai-500-server-error", - "pipeline-error-xai-503-server-overloaded-error", - "pipeline-error-xai-llm-failed", - "call.in-progress.error-vapifault-xai-400-bad-request-validation-failed", - "call.in-progress.error-vapifault-xai-401-unauthorized", - "call.in-progress.error-vapifault-xai-403-model-access-denied", - "call.in-progress.error-vapifault-xai-429-exceeded-quota", - "call.in-progress.error-providerfault-xai-500-server-error", - "call.in-progress.error-providerfault-xai-503-server-overloaded-error", - "pipeline-error-mistral-400-bad-request-validation-failed", - "pipeline-error-mistral-401-unauthorized", - "pipeline-error-mistral-403-model-access-denied", - "pipeline-error-mistral-429-exceeded-quota", - "pipeline-error-mistral-500-server-error", - "pipeline-error-mistral-503-server-overloaded-error", - "pipeline-error-mistral-llm-failed", - "call.in-progress.error-vapifault-mistral-400-bad-request-validation-failed", - "call.in-progress.error-vapifault-mistral-401-unauthorized", - "call.in-progress.error-vapifault-mistral-403-model-access-denied", - "call.in-progress.error-vapifault-mistral-429-exceeded-quota", - "call.in-progress.error-providerfault-mistral-500-server-error", - "call.in-progress.error-providerfault-mistral-503-server-overloaded-error", - "pipeline-error-inflection-ai-400-bad-request-validation-failed", - "pipeline-error-inflection-ai-401-unauthorized", - "pipeline-error-inflection-ai-403-model-access-denied", - "pipeline-error-inflection-ai-429-exceeded-quota", - "pipeline-error-inflection-ai-500-server-error", - "pipeline-error-inflection-ai-503-server-overloaded-error", - "pipeline-error-inflection-ai-llm-failed", - "call.in-progress.error-vapifault-inflection-ai-400-bad-request-validation-failed", - "call.in-progress.error-vapifault-inflection-ai-401-unauthorized", - "call.in-progress.error-vapifault-inflection-ai-403-model-access-denied", - "call.in-progress.error-vapifault-inflection-ai-429-exceeded-quota", - "call.in-progress.error-providerfault-inflection-ai-500-server-error", - "call.in-progress.error-providerfault-inflection-ai-503-server-overloaded-error", - "pipeline-error-deep-seek-400-bad-request-validation-failed", - "pipeline-error-deep-seek-401-unauthorized", - "pipeline-error-deep-seek-403-model-access-denied", - "pipeline-error-deep-seek-429-exceeded-quota", - "pipeline-error-deep-seek-500-server-error", - "pipeline-error-deep-seek-503-server-overloaded-error", - "pipeline-error-deep-seek-llm-failed", - "call.in-progress.error-vapifault-deep-seek-400-bad-request-validation-failed", - "call.in-progress.error-vapifault-deep-seek-401-unauthorized", - "call.in-progress.error-vapifault-deep-seek-403-model-access-denied", - "call.in-progress.error-vapifault-deep-seek-429-exceeded-quota", - "call.in-progress.error-providerfault-deep-seek-500-server-error", - "call.in-progress.error-providerfault-deep-seek-503-server-overloaded-error", - "pipeline-error-groq-400-bad-request-validation-failed", - "pipeline-error-groq-401-unauthorized", - "pipeline-error-groq-403-model-access-denied", - "pipeline-error-groq-429-exceeded-quota", - "pipeline-error-groq-500-server-error", - "pipeline-error-groq-503-server-overloaded-error", - "pipeline-error-groq-llm-failed", - "call.in-progress.error-vapifault-groq-400-bad-request-validation-failed", - "call.in-progress.error-vapifault-groq-401-unauthorized", - "call.in-progress.error-vapifault-groq-403-model-access-denied", - "call.in-progress.error-vapifault-groq-429-exceeded-quota", - "call.in-progress.error-providerfault-groq-500-server-error", - "call.in-progress.error-providerfault-groq-503-server-overloaded-error", - "pipeline-error-cerebras-400-bad-request-validation-failed", - "pipeline-error-cerebras-401-unauthorized", - "pipeline-error-cerebras-403-model-access-denied", - "pipeline-error-cerebras-429-exceeded-quota", - "pipeline-error-cerebras-500-server-error", - "pipeline-error-cerebras-503-server-overloaded-error", - "pipeline-error-cerebras-llm-failed", - "call.in-progress.error-vapifault-cerebras-400-bad-request-validation-failed", - "call.in-progress.error-vapifault-cerebras-401-unauthorized", - "call.in-progress.error-vapifault-cerebras-403-model-access-denied", - "call.in-progress.error-vapifault-cerebras-429-exceeded-quota", - "call.in-progress.error-providerfault-cerebras-500-server-error", - "call.in-progress.error-providerfault-cerebras-503-server-overloaded-error", - "pipeline-error-anthropic-400-bad-request-validation-failed", - "pipeline-error-anthropic-401-unauthorized", - "pipeline-error-anthropic-403-model-access-denied", - "pipeline-error-anthropic-429-exceeded-quota", - "pipeline-error-anthropic-500-server-error", - "pipeline-error-anthropic-503-server-overloaded-error", - "pipeline-error-anthropic-llm-failed", - "call.in-progress.error-vapifault-anthropic-llm-failed", - "call.in-progress.error-vapifault-anthropic-400-bad-request-validation-failed", - "call.in-progress.error-vapifault-anthropic-401-unauthorized", - "call.in-progress.error-vapifault-anthropic-403-model-access-denied", - "call.in-progress.error-vapifault-anthropic-429-exceeded-quota", - "call.in-progress.error-providerfault-anthropic-500-server-error", - "call.in-progress.error-providerfault-anthropic-503-server-overloaded-error", - "pipeline-error-anthropic-bedrock-400-bad-request-validation-failed", - "pipeline-error-anthropic-bedrock-401-unauthorized", - "pipeline-error-anthropic-bedrock-403-model-access-denied", - "pipeline-error-anthropic-bedrock-429-exceeded-quota", - "pipeline-error-anthropic-bedrock-500-server-error", - "pipeline-error-anthropic-bedrock-503-server-overloaded-error", - "pipeline-error-anthropic-bedrock-llm-failed", - "call.in-progress.error-vapifault-anthropic-bedrock-llm-failed", - "call.in-progress.error-vapifault-anthropic-bedrock-400-bad-request-validation-failed", - "call.in-progress.error-vapifault-anthropic-bedrock-401-unauthorized", + "Girl", + "Boy", + "YoungAdultFemale", + "YoungAdultMale", + "OlderAdultFemale", + "OlderAdultMale", + "SeniorFemale", + "SeniorMale" + ], + "example": "YoungAdultFemale" + }, + "chunkPlan": { + "description": "This is the plan for chunking the model output before it is sent to the voice provider.", + "allOf": [ + { + "$ref": "#/components/schemas/ChunkPlan" + } + ] + }, + "speed": { + "type": "number", + "description": "This is the speed multiplier that will be used.", + "minimum": 0.5, + "maximum": 2 + }, + "fallbackPlan": { + "description": "This is the plan for voice provider fallbacks in the event that the primary voice provider fails.", + "allOf": [ + { + "$ref": "#/components/schemas/FallbackPlan" + } + ] + } + }, + "required": [ + "provider", + "voiceId" + ] + }, + "FallbackAzureVoice": { + "type": "object", + "properties": { + "cachingEnabled": { + "type": "boolean", + "description": "This is the flag to toggle voice caching for the assistant.", + "example": true, + "default": true + }, + "provider": { + "type": "string", + "description": "This is the voice provider that will be used.", + "enum": [ + "azure" + ] + }, + "voiceId": { + "description": "This is the provider-specific ID that will be used.", + "oneOf": [ + { + "type": "string", + "enum": [ + "andrew", + "brian", + "emma" + ], + "title": "Preset Voice Options" + }, + { + "type": "string", + "title": "Azure Voice ID" + } + ] + }, + "speed": { + "type": "number", + "description": "This is the speed multiplier that will be used.", + "minimum": 0.5, + "maximum": 2 + }, + "chunkPlan": { + "description": "This is the plan for chunking the model output before it is sent to the voice provider.", + "allOf": [ + { + "$ref": "#/components/schemas/ChunkPlan" + } + ] + } + }, + "required": [ + "provider", + "voiceId" + ] + }, + "FallbackCartesiaVoice": { + "type": "object", + "properties": { + "cachingEnabled": { + "type": "boolean", + "description": "This is the flag to toggle voice caching for the assistant.", + "example": true, + "default": true + }, + "provider": { + "type": "string", + "description": "This is the voice provider that will be used.", + "enum": [ + "cartesia" + ] + }, + "voiceId": { + "type": "string", + "description": "The ID of the particular voice you want to use." + }, + "model": { + "type": "string", + "description": "This is the model that will be used. This is optional and will default to the correct model for the voiceId.", + "enum": [ + "sonic-3.5", + "sonic-3.5-2026-05-04", + "sonic-3", + "sonic-3-2026-01-12", + "sonic-3-2025-10-27", + "sonic-2", + "sonic-2-2025-06-11", + "sonic-english", + "sonic-multilingual", + "sonic-preview", + "sonic" + ], + "example": "sonic-english" + }, + "language": { + "type": "string", + "description": "This is the language that will be used. This is optional and will default to the correct language for the voiceId.", + "enum": [ + "ar", + "bg", + "bn", + "cs", + "da", + "de", + "el", + "en", + "es", + "fi", + "fr", + "gu", + "he", + "hi", + "hr", + "hu", + "id", + "it", + "ja", + "ka", + "kn", + "ko", + "ml", + "mr", + "ms", + "nl", + "no", + "pa", + "pl", + "pt", + "ro", + "ru", + "sk", + "sv", + "ta", + "te", + "th", + "tl", + "tr", + "uk", + "vi", + "zh" + ], + "example": "en" + }, + "experimentalControls": { + "description": "Experimental controls for Cartesia voice generation", + "allOf": [ + { + "$ref": "#/components/schemas/CartesiaExperimentalControls" + } + ] + }, + "generationConfig": { + "description": "Generation config for fine-grained control of sonic-3 voice output (speed, volume, and experimental controls). Only available for sonic-3 model.", + "allOf": [ + { + "$ref": "#/components/schemas/CartesiaGenerationConfig" + } + ] + }, + "pronunciationDictId": { + "type": "string", + "description": "Pronunciation dictionary ID for sonic-3. Allows custom pronunciations for specific words. Only available for sonic-3 model.", + "example": "dict_abc123" + }, + "chunkPlan": { + "description": "This is the plan for chunking the model output before it is sent to the voice provider.", + "allOf": [ + { + "$ref": "#/components/schemas/ChunkPlan" + } + ] + } + }, + "required": [ + "provider", + "voiceId" + ] + }, + "FallbackCustomVoice": { + "type": "object", + "properties": { + "cachingEnabled": { + "type": "boolean", + "description": "This is the flag to toggle voice caching for the assistant.", + "example": true, + "default": true + }, + "provider": { + "type": "string", + "description": "This is the voice provider that will be used. Use `custom-voice` for providers that are not natively supported.", + "enum": [ + "custom-voice" + ] + }, + "voiceId": { + "type": "string", + "description": "This is the provider-specific ID that will be used. This is passed in the voice request payload to identify the voice to use." + }, + "server": { + "description": "This is where the voice request will be sent.\n\nRequest Example:\n\nPOST https://{server.url}\nContent-Type: application/json\n\n{\n \"message\": {\n \"type\": \"voice-request\",\n \"text\": \"Hello, world!\",\n \"sampleRate\": 24000,\n ...other metadata about the call...\n }\n}\n\nResponse Expected: 1-channel 16-bit raw PCM audio at the sample rate specified in the request. Here is how the response will be piped to the transport:\n```\nresponse.on('data', (chunk: Buffer) => {\n outputStream.write(chunk);\n});\n```", + "allOf": [ + { + "$ref": "#/components/schemas/Server" + } + ] + }, + "chunkPlan": { + "description": "This is the plan for chunking the model output before it is sent to the voice provider.", + "allOf": [ + { + "$ref": "#/components/schemas/ChunkPlan" + } + ] + } + }, + "required": [ + "provider", + "server" + ] + }, + "FallbackDeepgramVoice": { + "type": "object", + "properties": { + "cachingEnabled": { + "type": "boolean", + "description": "This is the flag to toggle voice caching for the assistant.", + "example": true, + "default": true + }, + "provider": { + "type": "string", + "description": "This is the voice provider that will be used.", + "enum": [ + "deepgram" + ] + }, + "voiceId": { + "type": "string", + "description": "This is the provider-specific ID that will be used.", + "enum": [ + "asteria", + "luna", + "stella", + "athena", + "hera", + "orion", + "arcas", + "perseus", + "angus", + "orpheus", + "helios", + "zeus", + "thalia", + "andromeda", + "helena", + "apollo", + "arcas", + "aries", + "amalthea", + "asteria", + "athena", + "atlas", + "aurora", + "callista", + "cora", + "cordelia", + "delia", + "draco", + "electra", + "harmonia", + "hera", + "hermes", + "hyperion", + "iris", + "janus", + "juno", + "jupiter", + "luna", + "mars", + "minerva", + "neptune", + "odysseus", + "ophelia", + "orion", + "orpheus", + "pandora", + "phoebe", + "pluto", + "saturn", + "selene", + "theia", + "vesta", + "zeus", + "celeste", + "estrella", + "nestor", + "sirio", + "carina", + "alvaro", + "diana", + "aquila", + "selena", + "javier", + "viktoria", + "kara", + "fabian", + "julius", + "lara", + "elara", + "aurelia" + ], + "title": "This is the Deepgram Voice ID" + }, + "model": { + "type": "string", + "description": "This is the model that will be used. Defaults to 'aura-2' when not specified.", + "enum": [ + "aura", + "aura-2" + ], + "example": "aura-2" + }, + "mipOptOut": { + "type": "boolean", + "description": "If set to true, this will add mip_opt_out=true as a query parameter of all API requests. See https://developers.deepgram.com/docs/the-deepgram-model-improvement-partnership-program#want-to-opt-out\n\nThis will only be used if you are using your own Deepgram API key.\n\n@default false", + "example": false, + "default": false + }, + "chunkPlan": { + "description": "This is the plan for chunking the model output before it is sent to the voice provider.", + "allOf": [ + { + "$ref": "#/components/schemas/ChunkPlan" + } + ] + } + }, + "required": [ + "provider", + "voiceId" + ] + }, + "FallbackElevenLabsVoice": { + "type": "object", + "properties": { + "cachingEnabled": { + "type": "boolean", + "description": "This is the flag to toggle voice caching for the assistant.", + "example": true, + "default": true + }, + "provider": { + "type": "string", + "description": "This is the voice provider that will be used.", + "enum": [ + "11labs" + ] + }, + "voiceId": { + "description": "This is the provider-specific ID that will be used. Ensure the Voice is present in your 11Labs Voice Library.", + "oneOf": [ + { + "type": "string", + "enum": [ + "burt", + "marissa", + "andrea", + "sarah", + "phillip", + "steve", + "joseph", + "myra", + "paula", + "ryan", + "drew", + "paul", + "mrb", + "matilda", + "mark" + ], + "title": "Preset Voice Options" + }, + { + "type": "string", + "title": "11Labs Voice ID" + } + ] + }, + "stability": { + "type": "number", + "description": "Defines the stability for voice settings.", + "minimum": 0, + "maximum": 1, + "example": 0.5 + }, + "similarityBoost": { + "type": "number", + "description": "Defines the similarity boost for voice settings.", + "minimum": 0, + "maximum": 1, + "example": 0.75 + }, + "style": { + "type": "number", + "description": "Defines the style for voice settings.", + "minimum": 0, + "maximum": 1, + "example": 0 + }, + "useSpeakerBoost": { + "type": "boolean", + "description": "Defines the use speaker boost for voice settings.", + "example": false + }, + "speed": { + "type": "number", + "description": "Defines the speed for voice settings.", + "minimum": 0.7, + "maximum": 1.2, + "example": 0.9 + }, + "optimizeStreamingLatency": { + "type": "number", + "description": "Defines the optimize streaming latency for voice settings. Defaults to 3.", + "minimum": 0, + "maximum": 4, + "example": 3 + }, + "enableSsmlParsing": { + "type": "boolean", + "description": "This enables the use of https://elevenlabs.io/docs/speech-synthesis/prompting#pronunciation. Defaults to false to save latency.\n\n@default false", + "example": false + }, + "autoMode": { + "type": "boolean", + "description": "Defines the auto mode for voice settings. Defaults to false.", + "example": false + }, + "model": { + "type": "string", + "description": "This is the model that will be used. Defaults to 'eleven_turbo_v2' if not specified.", + "enum": [ + "eleven_multilingual_v2", + "eleven_turbo_v2", + "eleven_turbo_v2_5", + "eleven_flash_v2", + "eleven_flash_v2_5", + "eleven_monolingual_v1", + "eleven_v3" + ], + "example": "eleven_turbo_v2_5" + }, + "language": { + "type": "string", + "description": "This is the language (ISO 639-1) that is enforced for the model. Currently only Turbo v2.5 supports language enforcement. For other models, an error will be returned if language code is provided." + }, + "pronunciationDictionaryLocators": { + "description": "This is the pronunciation dictionary locators to use.", + "type": "array", + "items": { + "$ref": "#/components/schemas/ElevenLabsPronunciationDictionaryLocator" + } + }, + "chunkPlan": { + "description": "This is the plan for chunking the model output before it is sent to the voice provider.", + "allOf": [ + { + "$ref": "#/components/schemas/ChunkPlan" + } + ] + } + }, + "required": [ + "provider", + "voiceId" + ] + }, + "FallbackHumeVoice": { + "type": "object", + "properties": { + "cachingEnabled": { + "type": "boolean", + "description": "This is the flag to toggle voice caching for the assistant.", + "example": true, + "default": true + }, + "provider": { + "type": "string", + "description": "This is the voice provider that will be used.", + "enum": [ + "hume" + ] + }, + "model": { + "type": "string", + "description": "This is the model that will be used.", + "enum": [ + "octave", + "octave2" + ], + "example": "octave2" + }, + "voiceId": { + "type": "string", + "description": "The ID of the particular voice you want to use." + }, + "isCustomHumeVoice": { + "type": "boolean", + "description": "Indicates whether the chosen voice is a preset Hume AI voice or a custom voice.", + "example": false + }, + "description": { + "type": "string", + "description": "Natural language instructions describing how the synthesized speech should sound, including but not limited to tone, intonation, pacing, and accent (e.g., 'a soft, gentle voice with a strong British accent').\n\nIf a Voice is specified in the request, this description serves as acting instructions.\nIf no Voice is specified, a new voice is generated based on this description." + }, + "chunkPlan": { + "description": "This is the plan for chunking the model output before it is sent to the voice provider.", + "allOf": [ + { + "$ref": "#/components/schemas/ChunkPlan" + } + ] + } + }, + "required": [ + "provider", + "voiceId" + ] + }, + "FallbackLMNTVoice": { + "type": "object", + "properties": { + "cachingEnabled": { + "type": "boolean", + "description": "This is the flag to toggle voice caching for the assistant.", + "example": true, + "default": true + }, + "provider": { + "type": "string", + "description": "This is the voice provider that will be used.", + "enum": [ + "lmnt" + ] + }, + "voiceId": { + "description": "This is the provider-specific ID that will be used.", + "oneOf": [ + { + "type": "string", + "enum": [ + "amy", + "ansel", + "autumn", + "ava", + "brandon", + "caleb", + "cassian", + "chloe", + "dalton", + "daniel", + "dustin", + "elowen", + "evander", + "huxley", + "james", + "juniper", + "kennedy", + "lauren", + "leah", + "lily", + "lucas", + "magnus", + "miles", + "morgan", + "natalie", + "nathan", + "noah", + "nyssa", + "oliver", + "paige", + "ryan", + "sadie", + "sophie", + "stella", + "terrence", + "tyler", + "vesper", + "violet", + "warrick", + "zain", + "zeke", + "zoe" + ], + "title": "Preset Voice Options" + }, + { + "type": "string", + "title": "LMNT Voice ID" + } + ] + }, + "speed": { + "type": "number", + "description": "This is the speed multiplier that will be used.", + "minimum": 0.25, + "maximum": 2, + "example": null + }, + "language": { + "description": "Two letter ISO 639-1 language code. Use \"auto\" for auto-detection.", + "enum": [ + "aa", + "ab", + "ae", + "af", + "ak", + "am", + "an", + "ar", + "as", + "av", + "ay", + "az", + "ba", + "be", + "bg", + "bh", + "bi", + "bm", + "bn", + "bo", + "br", + "bs", + "ca", + "ce", + "ch", + "co", + "cr", + "cs", + "cu", + "cv", + "cy", + "da", + "de", + "dv", + "dz", + "ee", + "el", + "en", + "eo", + "es", + "et", + "eu", + "fa", + "ff", + "fi", + "fj", + "fo", + "fr", + "fy", + "ga", + "gd", + "gl", + "gn", + "gu", + "gv", + "ha", + "he", + "hi", + "ho", + "hr", + "ht", + "hu", + "hy", + "hz", + "ia", + "id", + "ie", + "ig", + "ii", + "ik", + "io", + "is", + "it", + "iu", + "ja", + "jv", + "ka", + "kg", + "ki", + "kj", + "kk", + "kl", + "km", + "kn", + "ko", + "kr", + "ks", + "ku", + "kv", + "kw", + "ky", + "la", + "lb", + "lg", + "li", + "ln", + "lo", + "lt", + "lu", + "lv", + "mg", + "mh", + "mi", + "mk", + "ml", + "mn", + "mr", + "ms", + "mt", + "my", + "na", + "nb", + "nd", + "ne", + "ng", + "nl", + "nn", + "no", + "nr", + "nv", + "ny", + "oc", + "oj", + "om", + "or", + "os", + "pa", + "pi", + "pl", + "ps", + "pt", + "qu", + "rm", + "rn", + "ro", + "ru", + "rw", + "sa", + "sc", + "sd", + "se", + "sg", + "si", + "sk", + "sl", + "sm", + "sn", + "so", + "sq", + "sr", + "ss", + "st", + "su", + "sv", + "sw", + "ta", + "te", + "tg", + "th", + "ti", + "tk", + "tl", + "tn", + "to", + "tr", + "ts", + "tt", + "tw", + "ty", + "ug", + "uk", + "ur", + "uz", + "ve", + "vi", + "vo", + "wa", + "wo", + "xh", + "yi", + "yue", + "yo", + "za", + "zh", + "zu", + "auto" + ], + "example": "en", + "oneOf": [ + { + "type": "string", + "enum": [ + "aa", + "ab", + "ae", + "af", + "ak", + "am", + "an", + "ar", + "as", + "av", + "ay", + "az", + "ba", + "be", + "bg", + "bh", + "bi", + "bm", + "bn", + "bo", + "br", + "bs", + "ca", + "ce", + "ch", + "co", + "cr", + "cs", + "cu", + "cv", + "cy", + "da", + "de", + "dv", + "dz", + "ee", + "el", + "en", + "eo", + "es", + "et", + "eu", + "fa", + "ff", + "fi", + "fj", + "fo", + "fr", + "fy", + "ga", + "gd", + "gl", + "gn", + "gu", + "gv", + "ha", + "he", + "hi", + "ho", + "hr", + "ht", + "hu", + "hy", + "hz", + "ia", + "id", + "ie", + "ig", + "ii", + "ik", + "io", + "is", + "it", + "iu", + "ja", + "jv", + "ka", + "kg", + "ki", + "kj", + "kk", + "kl", + "km", + "kn", + "ko", + "kr", + "ks", + "ku", + "kv", + "kw", + "ky", + "la", + "lb", + "lg", + "li", + "ln", + "lo", + "lt", + "lu", + "lv", + "mg", + "mh", + "mi", + "mk", + "ml", + "mn", + "mr", + "ms", + "mt", + "my", + "na", + "nb", + "nd", + "ne", + "ng", + "nl", + "nn", + "no", + "nr", + "nv", + "ny", + "oc", + "oj", + "om", + "or", + "os", + "pa", + "pi", + "pl", + "ps", + "pt", + "qu", + "rm", + "rn", + "ro", + "ru", + "rw", + "sa", + "sc", + "sd", + "se", + "sg", + "si", + "sk", + "sl", + "sm", + "sn", + "so", + "sq", + "sr", + "ss", + "st", + "su", + "sv", + "sw", + "ta", + "te", + "tg", + "th", + "ti", + "tk", + "tl", + "tn", + "to", + "tr", + "ts", + "tt", + "tw", + "ty", + "ug", + "uk", + "ur", + "uz", + "ve", + "vi", + "vo", + "wa", + "wo", + "xh", + "yi", + "yue", + "yo", + "za", + "zh", + "zu" + ], + "title": "ISO 639-1 Language Code" + }, + { + "type": "string", + "enum": [ + "auto" + ], + "title": "Auto-detect" + } + ] + }, + "chunkPlan": { + "description": "This is the plan for chunking the model output before it is sent to the voice provider.", + "allOf": [ + { + "$ref": "#/components/schemas/ChunkPlan" + } + ] + } + }, + "required": [ + "provider", + "voiceId" + ] + }, + "FallbackNeuphonicVoice": { + "type": "object", + "properties": { + "cachingEnabled": { + "type": "boolean", + "description": "This is the flag to toggle voice caching for the assistant.", + "example": true, + "default": true + }, + "provider": { + "type": "string", + "description": "This is the voice provider that will be used.", + "enum": [ + "neuphonic" + ] + }, + "voiceId": { + "description": "This is the provider-specific ID that will be used.", + "oneOf": [ + { + "type": "string", + "enum": [], + "title": "Preset Voice Options" + }, + { + "type": "string", + "title": "Neuphonic Voice ID" + } + ] + }, + "model": { + "type": "string", + "description": "This is the model that will be used. Defaults to 'neu_fast' if not specified.", + "enum": [ + "neu_hq", + "neu_fast" + ], + "example": "neu_fast" + }, + "language": { + "type": "object", + "description": "This is the language (ISO 639-1) that is enforced for the model.", + "example": "en" + }, + "speed": { + "type": "number", + "description": "This is the speed multiplier that will be used.", + "minimum": 0.25, + "maximum": 2, + "example": null + }, + "chunkPlan": { + "description": "This is the plan for chunking the model output before it is sent to the voice provider.", + "allOf": [ + { + "$ref": "#/components/schemas/ChunkPlan" + } + ] + } + }, + "required": [ + "provider", + "voiceId", + "language" + ] + }, + "FallbackOpenAIVoice": { + "type": "object", + "properties": { + "cachingEnabled": { + "type": "boolean", + "description": "This is the flag to toggle voice caching for the assistant.", + "example": true, + "default": true + }, + "provider": { + "type": "string", + "description": "This is the voice provider that will be used.", + "enum": [ + "openai" + ] + }, + "voiceId": { + "description": "This is the provider-specific ID that will be used.\nPlease note that ash, ballad, coral, sage, and verse may only be used with realtime models.", + "oneOf": [ + { + "type": "string", + "enum": [ + "alloy", + "echo", + "fable", + "onyx", + "nova", + "shimmer", + "marin", + "cedar" + ], + "title": "Preset Voice Options" + }, + { + "type": "string", + "title": "OpenAI Voice ID" + } + ] + }, + "model": { + "type": "string", + "description": "This is the model that will be used for text-to-speech.", + "enum": [ + "tts-1", + "tts-1-hd", + "gpt-4o-mini-tts" + ] + }, + "instructions": { + "type": "string", + "description": "This is a prompt that allows you to control the voice of your generated audio.\nDoes not work with 'tts-1' or 'tts-1-hd' models.", + "maxLength": 10000 + }, + "speed": { + "type": "number", + "description": "This is the speed multiplier that will be used.", + "minimum": 0.25, + "maximum": 4, + "example": null + }, + "chunkPlan": { + "description": "This is the plan for chunking the model output before it is sent to the voice provider.", + "allOf": [ + { + "$ref": "#/components/schemas/ChunkPlan" + } + ] + } + }, + "required": [ + "provider", + "voiceId" + ] + }, + "FallbackPlayHTVoice": { + "type": "object", + "properties": { + "cachingEnabled": { + "type": "boolean", + "description": "This is the flag to toggle voice caching for the assistant.", + "example": true, + "default": true + }, + "provider": { + "type": "string", + "description": "This is the voice provider that will be used.", + "enum": [ + "playht" + ] + }, + "voiceId": { + "description": "This is the provider-specific ID that will be used.", + "oneOf": [ + { + "type": "string", + "enum": [ + "jennifer", + "melissa", + "will", + "chris", + "matt", + "jack", + "ruby", + "davis", + "donna", + "michael" + ], + "title": "Preset Voice Options" + }, + { + "type": "string", + "title": "PlayHT Voice ID" + } + ] + }, + "speed": { + "type": "number", + "description": "This is the speed multiplier that will be used.", + "minimum": 0.1, + "maximum": 5, + "example": null + }, + "temperature": { + "type": "number", + "description": "A floating point number between 0, exclusive, and 2, inclusive. If equal to null or not provided, the model's default temperature will be used. The temperature parameter controls variance. Lower temperatures result in more predictable results, higher temperatures allow each run to vary more, so the voice may sound less like the baseline voice.", + "minimum": 0.1, + "maximum": 2, + "example": null + }, + "emotion": { + "type": "string", + "description": "An emotion to be applied to the speech.", + "enum": [ + "female_happy", + "female_sad", + "female_angry", + "female_fearful", + "female_disgust", + "female_surprised", + "male_happy", + "male_sad", + "male_angry", + "male_fearful", + "male_disgust", + "male_surprised" + ], + "example": null + }, + "voiceGuidance": { + "type": "number", + "description": "A number between 1 and 6. Use lower numbers to reduce how unique your chosen voice will be compared to other voices.", + "minimum": 1, + "maximum": 6, + "example": null + }, + "styleGuidance": { + "type": "number", + "description": "A number between 1 and 30. Use lower numbers to to reduce how strong your chosen emotion will be. Higher numbers will create a very emotional performance.", + "minimum": 1, + "maximum": 30, + "example": null + }, + "textGuidance": { + "type": "number", + "description": "A number between 1 and 2. This number influences how closely the generated speech adheres to the input text. Use lower values to create more fluid speech, but with a higher chance of deviating from the input text. Higher numbers will make the generated speech more accurate to the input text, ensuring that the words spoken align closely with the provided text.", + "minimum": 1, + "maximum": 2, + "example": null + }, + "model": { + "type": "string", + "description": "Playht voice model/engine to use.", + "enum": [ + "PlayHT2.0", + "PlayHT2.0-turbo", + "Play3.0-mini", + "PlayDialog" + ] + }, + "language": { + "type": "string", + "description": "The language to use for the speech.", + "enum": [ + "afrikaans", + "albanian", + "amharic", + "arabic", + "bengali", + "bulgarian", + "catalan", + "croatian", + "czech", + "danish", + "dutch", + "english", + "french", + "galician", + "german", + "greek", + "hebrew", + "hindi", + "hungarian", + "indonesian", + "italian", + "japanese", + "korean", + "malay", + "mandarin", + "polish", + "portuguese", + "russian", + "serbian", + "spanish", + "swedish", + "tagalog", + "thai", + "turkish", + "ukrainian", + "urdu", + "xhosa" + ] + }, + "chunkPlan": { + "description": "This is the plan for chunking the model output before it is sent to the voice provider.", + "allOf": [ + { + "$ref": "#/components/schemas/ChunkPlan" + } + ] + } + }, + "required": [ + "provider", + "voiceId" + ] + }, + "FallbackRimeAIVoice": { + "type": "object", + "properties": { + "cachingEnabled": { + "type": "boolean", + "description": "This is the flag to toggle voice caching for the assistant.", + "example": true, + "default": true + }, + "provider": { + "type": "string", + "description": "This is the voice provider that will be used.", + "enum": [ + "rime-ai" + ] + }, + "voiceId": { + "description": "This is the provider-specific ID that will be used.", + "oneOf": [ + { + "type": "string", + "enum": [ + "cove", + "moon", + "wildflower", + "eva", + "amber", + "maya", + "lagoon", + "breeze", + "helen", + "joy", + "marsh", + "creek", + "cedar", + "alpine", + "summit", + "nicholas", + "tyler", + "colin", + "hank", + "thunder", + "astra", + "eucalyptus", + "moraine", + "peak", + "tundra", + "mesa_extra", + "talon", + "marlu", + "glacier", + "falcon", + "luna", + "celeste", + "estelle", + "andromeda", + "esther", + "lyra", + "lintel", + "oculus", + "vespera", + "transom", + "bond", + "arcade", + "atrium", + "cupola", + "fern", + "sirius", + "orion", + "masonry", + "albion", + "parapet" + ], + "title": "Suggested Voice Options", + "description": "Popular Rime AI voices across mist, mistv2, and arcana models. Any valid Rime AI voice ID is accepted, not just these suggestions." + }, + { + "type": "string", + "title": "Any Rime AI Voice ID", + "description": "Any valid Rime AI voice ID. See https://docs.rime.ai/docs/voices for the full catalog." + } + ] + }, + "model": { + "type": "string", + "description": "This is the model that will be used. Defaults to 'arcana' when not specified.", + "enum": [ + "arcana", + "mistv2", + "mist" + ], + "example": "arcana" + }, + "speed": { + "type": "number", + "description": "This is the speed multiplier that will be used.", + "minimum": 0.1, + "example": null + }, + "pauseBetweenBrackets": { + "type": "boolean", + "description": "This is a flag that controls whether to add slight pauses using angle brackets. Example: \"Hi. <200> I'd love to have a conversation with you.\" adds a 200ms pause between the first and second sentences.", + "example": false + }, + "phonemizeBetweenBrackets": { + "type": "boolean", + "description": "This is a flag that controls whether text inside brackets should be phonemized (converted to phonetic pronunciation) - Example: \"{h'El.o} World\" will pronounce \"Hello\" as expected.", + "example": false + }, + "reduceLatency": { + "type": "boolean", + "description": "This is a flag that controls whether to optimize for reduced latency in streaming. https://docs.rime.ai/api-reference/endpoint/websockets#param-reduce-latency", + "example": false + }, + "inlineSpeedAlpha": { + "type": "string", + "description": "This is a string that allows inline speed control using alpha notation. https://docs.rime.ai/api-reference/endpoint/websockets#param-inline-speed-alpha", + "example": null + }, + "language": { + "type": "string", + "description": "Language for speech synthesis. Uses ISO 639 codes. Supported: en, es, de, fr, ar, hi, ja, he, pt, ta, si.", + "enum": [ + "en", + "es", + "de", + "fr", + "ar", + "hi", + "ja", + "he", + "pt", + "ta", + "si" + ], + "example": "en" + }, + "chunkPlan": { + "description": "This is the plan for chunking the model output before it is sent to the voice provider.", + "allOf": [ + { + "$ref": "#/components/schemas/ChunkPlan" + } + ] + } + }, + "required": [ + "provider", + "voiceId" + ] + }, + "FallbackSesameVoice": { + "type": "object", + "properties": { + "cachingEnabled": { + "type": "boolean", + "description": "This is the flag to toggle voice caching for the assistant.", + "example": true, + "default": true + }, + "provider": { + "type": "string", + "description": "This is the voice provider that will be used.", + "enum": [ + "sesame" + ] + }, + "voiceId": { + "type": "string", + "description": "This is the provider-specific ID that will be used.", + "title": "Sesame Voice ID. This should be either a name (a built-in voice) or a UUID (a custom voice)." + }, + "model": { + "type": "string", + "description": "This is the model that will be used.", + "enum": [ + "csm-1b" + ] + }, + "chunkPlan": { + "description": "This is the plan for chunking the model output before it is sent to the voice provider.", + "allOf": [ + { + "$ref": "#/components/schemas/ChunkPlan" + } + ] + } + }, + "required": [ + "provider", + "voiceId", + "model" + ] + }, + "FallbackSmallestAIVoice": { + "type": "object", + "properties": { + "cachingEnabled": { + "type": "boolean", + "description": "This is the flag to toggle voice caching for the assistant.", + "example": true, + "default": true + }, + "provider": { + "type": "string", + "description": "This is the voice provider that will be used.", + "enum": [ + "smallest-ai" + ] + }, + "voiceId": { + "description": "This is the provider-specific ID that will be used.", + "oneOf": [ + { + "type": "string", + "enum": [ + "emily", + "jasmine", + "arman", + "james", + "mithali", + "aravind", + "raj", + "diya", + "raman", + "ananya", + "isha", + "william", + "aarav", + "monika", + "niharika", + "deepika", + "raghav", + "kajal", + "radhika", + "mansi", + "nisha", + "saurabh", + "pooja", + "saina", + "sanya" + ], + "title": "Preset Voice Options" + }, + { + "type": "string", + "title": "Smallest AI Voice ID" + } + ] + }, + "model": { + "type": "string", + "description": "Smallest AI voice model to use. Defaults to 'lightning' when not specified.", + "enum": [ + "lightning" + ] + }, + "speed": { + "type": "number", + "description": "This is the speed multiplier that will be used.", + "example": null + }, + "chunkPlan": { + "description": "This is the plan for chunking the model output before it is sent to the voice provider.", + "allOf": [ + { + "$ref": "#/components/schemas/ChunkPlan" + } + ] + } + }, + "required": [ + "provider", + "voiceId" + ] + }, + "FallbackTavusVoice": { + "type": "object", + "properties": { + "cachingEnabled": { + "type": "boolean", + "description": "This is the flag to toggle voice caching for the assistant.", + "example": true, + "default": true + }, + "provider": { + "type": "string", + "description": "This is the voice provider that will be used.", + "enum": [ + "tavus" + ] + }, + "voiceId": { + "description": "This is the provider-specific ID that will be used.", + "oneOf": [ + { + "type": "string", + "enum": [ + "r52da2535a" + ], + "title": "Preset Voice Options" + }, + { + "type": "string", + "title": "Tavus Voice ID" + } + ] + }, + "personaId": { + "type": "string", + "description": "This is the unique identifier for the persona that the replica will use in the conversation." + }, + "callbackUrl": { + "type": "string", + "description": "This is the url that will receive webhooks with updates regarding the conversation state." + }, + "conversationName": { + "type": "string", + "description": "This is the name for the conversation." + }, + "conversationalContext": { + "type": "string", + "description": "This is the context that will be appended to any context provided in the persona, if one is provided." + }, + "customGreeting": { + "type": "string", + "description": "This is the custom greeting that the replica will give once a participant joines the conversation." + }, + "properties": { + "description": "These are optional properties used to customize the conversation.", + "allOf": [ + { + "$ref": "#/components/schemas/TavusConversationProperties" + } + ] + }, + "chunkPlan": { + "description": "This is the plan for chunking the model output before it is sent to the voice provider.", + "allOf": [ + { + "$ref": "#/components/schemas/ChunkPlan" + } + ] + } + }, + "required": [ + "provider", + "voiceId" + ] + }, + "FallbackVapiVoice": { + "type": "object", + "properties": { + "cachingEnabled": { + "type": "boolean", + "description": "This is the flag to toggle voice caching for the assistant.", + "example": true, + "default": true + }, + "provider": { + "type": "string", + "description": "This is the voice provider that will be used.", + "enum": [ + "vapi" + ] + }, + "voiceId": { + "type": "string", + "description": "The voice to use: a built-in Vapi voice name, or a cloned voice id (used with version 2).", + "example": "Clara" + }, + "version": { + "description": "The Vapi voice routing generation. `latest` auto-updates to the newest generation; version 1 uses legacy mappings; version 2 can use xAI-backed voices when available. When omitted, Version 1 is used. Accepts the string channel ('latest', '1', '2'); legacy numeric values (1, 2) are also accepted and coerced to their string form.", + "enum": [ + "1", + "2", + "latest" + ], + "oneOf": [ + { + "type": "string", + "enum": [ + "1", + "2", + "latest" + ] + }, + { + "type": "number", + "enum": [ + 1, + 2 + ] + } + ] + }, + "speed": { + "type": "number", + "description": "This is the speed multiplier that will be used.\n\n@default 1", + "minimum": 0.25, + "maximum": 2, + "default": 1 + }, + "language": { + "type": "string", + "description": "Language for Vapi voice synthesis. For Version 2, omit this field or set `auto` for automatic language detection. Version 1 supports legacy Vapi language values.", + "enum": [ + "en-US", + "en-GB", + "en-AU", + "en-CA", + "ja", + "zh", + "de", + "hi", + "fr-FR", + "fr-CA", + "ko", + "pt-BR", + "pt-PT", + "it", + "es-ES", + "es-MX", + "id", + "nl", + "tr", + "fil", + "pl", + "sv", + "bg", + "ro", + "ar-SA", + "ar-AE", + "cs", + "el", + "fi", + "hr", + "ms", + "sk", + "da", + "ta", + "uk", + "ru", + "hu", + "no", + "vi", + "auto", + "en", + "ar", + "ar-EG", + "bn", + "es", + "fr", + "gu", + "he", + "ka", + "kn", + "ml", + "mr", + "pa", + "pt", + "te", + "th", + "tl" + ] + }, + "pronunciationDictionary": { + "description": "List of pronunciation dictionary locators for custom word pronunciations.", + "type": "array", + "items": { + "$ref": "#/components/schemas/VapiPronunciationDictionaryLocator" + } + }, + "chunkPlan": { + "description": "This is the plan for chunking the model output before it is sent to the voice provider.", + "allOf": [ + { + "$ref": "#/components/schemas/ChunkPlan" + } + ] + } + }, + "required": [ + "provider", + "voiceId" + ] + }, + "FallbackInworldVoice": { + "type": "object", + "properties": { + "cachingEnabled": { + "type": "boolean", + "description": "This is the flag to toggle voice caching for the assistant.", + "example": true, + "default": true + }, + "provider": { + "type": "string", + "description": "This is the voice provider that will be used.", + "enum": [ + "inworld" + ] + }, + "voiceId": { + "type": "string", + "description": "Available voices by language:\n• en: Alex, Ashley, Craig, Deborah, Dennis, Edward, Elizabeth, Hades, Julia, Pixie, Mark, Olivia, Priya, Ronald, Sarah, Shaun, Theodore, Timothy, Wendy, Dominus, Hana, Clive, Carter, Blake, Luna\n• zh: Yichen, Xiaoyin, Xinyi, Jing\n• nl: Erik, Katrien, Lennart, Lore\n• fr: Alain, Hélène, Mathieu, Étienne\n• de: Johanna, Josef\n• it: Gianni, Orietta\n• ja: Asuka, Satoshi\n• ko: Hyunwoo, Minji, Seojun, Yoona\n• pl: Szymon, Wojciech\n• pt: Heitor, Maitê\n• es: Diego, Lupita, Miguel, Rafael\n• ru: Svetlana, Elena, Dmitry, Nikolai\n• hi: Riya, Manoj\n• he: Yael, Oren\n• ar: Nour, Omar", + "maxLength": 120, + "title": "Inworld Voice ID", + "enum": [ + "Alex", + "Ashley", + "Craig", + "Deborah", + "Dennis", + "Edward", + "Elizabeth", + "Hades", + "Julia", + "Pixie", + "Mark", + "Olivia", + "Priya", + "Ronald", + "Sarah", + "Shaun", + "Theodore", + "Timothy", + "Wendy", + "Dominus", + "Hana", + "Clive", + "Carter", + "Blake", + "Luna", + "Yichen", + "Xiaoyin", + "Xinyi", + "Jing", + "Erik", + "Katrien", + "Lennart", + "Lore", + "Alain", + "Hélène", + "Mathieu", + "Étienne", + "Johanna", + "Josef", + "Gianni", + "Orietta", + "Asuka", + "Satoshi", + "Hyunwoo", + "Minji", + "Seojun", + "Yoona", + "Szymon", + "Wojciech", + "Heitor", + "Maitê", + "Diego", + "Lupita", + "Miguel", + "Rafael", + "Svetlana", + "Elena", + "Dmitry", + "Nikolai", + "Riya", + "Manoj", + "Yael", + "Oren", + "Nour", + "Omar" + ], + "example": "Alex" + }, + "model": { + "type": "string", + "description": "This is the model that will be used.", + "enum": [ + "inworld-tts-1" + ], + "default": "inworld-tts-1" + }, + "languageCode": { + "type": "string", + "description": "Language code for Inworld TTS synthesis", + "default": "en", + "enum": [ + "en", + "zh", + "ko", + "nl", + "fr", + "es", + "ja", + "de", + "it", + "pl", + "pt", + "ru", + "hi", + "he", + "ar" + ] + }, + "temperature": { + "type": "number", + "description": "A floating point number between 0, exclusive, and 2, inclusive. If equal to null or not provided, the model's default temperature of 1.1 will be used. The temperature parameter controls variance.\nHigher values will make the output more random and can lead to more expressive results. Lower values will make it more deterministic.\nSee https://docs.inworld.ai/docs/tts/capabilities/generating-audio#additional-configurations for more details.", + "minimum": 0.1, + "maximum": 2, + "default": 1.1, + "example": null + }, + "speakingRate": { + "type": "number", + "description": "A floating point number between 0.5, inclusive, and 1.5, inclusive. If equal to null or not provided, the model's default speaking speed of 1.0 will be used.\nValues above 0.8 are recommended for higher quality.\nSee https://docs.inworld.ai/docs/tts/capabilities/generating-audio#additional-configurations for more details.", + "minimum": 0.5, + "maximum": 1.5, + "default": 1, + "example": null + }, + "chunkPlan": { + "description": "This is the plan for chunking the model output before it is sent to the voice provider.", + "allOf": [ + { + "$ref": "#/components/schemas/ChunkPlan" + } + ] + } + }, + "required": [ + "provider", + "voiceId" + ] + }, + "FallbackXaiVoice": { + "type": "object", + "properties": { + "cachingEnabled": { + "type": "boolean", + "description": "This is the flag to toggle voice caching for the assistant.", + "example": true, + "default": true + }, + "provider": { + "type": "string", + "description": "This is the voice provider that will be used.", + "enum": [ + "xai" + ] + }, + "voiceId": { + "type": "string", + "description": "Built-in voices: eve, ara, rex, sal, leo. Cloned voice IDs are also accepted.", + "maxLength": 120, + "title": "xAI Voice ID", + "enum": [ + "eve", + "ara", + "rex", + "sal", + "leo" + ], + "example": "eve" + }, + "language": { + "type": "string", + "description": "BCP-47 language code for xAI TTS synthesis.", + "enum": [ + "auto", + "en", + "ar-EG", + "ar-SA", + "ar-AE", + "bn", + "zh", + "fr", + "de", + "hi", + "id", + "it", + "ja", + "ko", + "pt-BR", + "pt-PT", + "ru", + "es-MX", + "es-ES", + "tr", + "vi" + ], + "default": "en" + }, + "speed": { + "type": "number", + "description": "Speed multiplier for xAI TTS synthesis.", + "minimum": 0.7, + "maximum": 1.5, + "default": 1.1 + }, + "chunkPlan": { + "description": "This is the plan for chunking the model output before it is sent to the voice provider.", + "allOf": [ + { + "$ref": "#/components/schemas/ChunkPlan" + } + ] + } + }, + "required": [ + "provider", + "voiceId" + ] + }, + "FallbackMicrosoftVoice": { + "type": "object", + "properties": { + "cachingEnabled": { + "type": "boolean", + "description": "This is the flag to toggle voice caching for the assistant.", + "example": true, + "default": true + }, + "provider": { + "type": "string", + "description": "This is the voice provider that will be used.", + "enum": [ + "microsoft" + ] + }, + "voiceId": { + "type": "string", + "description": "MAI-Voice-2 voice ID. Built-in voices listed in enum.", + "enum": [ + "de-DE-Klaus:MAI-Voice-2", + "de-DE-Mia:MAI-Voice-2", + "en-AU-Lisa:MAI-Voice-2", + "en-US-Ethan:MAI-Voice-2", + "en-US-Grant:MAI-Voice-2", + "en-US-Harper:MAI-Voice-2", + "en-US-Iris:MAI-Voice-2", + "en-US-Jasper:MAI-Voice-2", + "en-US-Olivia:MAI-Voice-2", + "es-ES-Marta:MAI-Voice-2", + "es-MX-Alejo:MAI-Voice-2", + "es-MX-Valeria:MAI-Voice-2", + "fr-FR-Marc:MAI-Voice-2", + "fr-FR-Soleil:MAI-Voice-2", + "hi-IN-Arjun:MAI-Voice-2", + "hi-IN-Dhruv:MAI-Voice-2", + "hi-IN-Kavya:MAI-Voice-2", + "hi-IN-Priya:MAI-Voice-2", + "hu-HU-Bence:MAI-Voice-2", + "hu-HU-Levente:MAI-Voice-2", + "hu-HU-Lilla:MAI-Voice-2", + "hu-HU-Réka:MAI-Voice-2", + "it-IT-Luca:MAI-Voice-2", + "it-IT-Rosa:MAI-Voice-2", + "ko-KR-Hana:MAI-Voice-2", + "ko-KR-Junho:MAI-Voice-2", + "nl-NL-Fleur:MAI-Voice-2", + "nl-NL-Sander:MAI-Voice-2", + "pt-BR-Caio:MAI-Voice-2", + "pt-BR-Luana:MAI-Voice-2", + "pt-BR-Pedro:MAI-Voice-2", + "pt-BR-Rafael:MAI-Voice-2", + "pt-PT-Rui:MAI-Voice-2", + "ro-RO-Andrei:MAI-Voice-2", + "ro-RO-Elena:MAI-Voice-2", + "ro-RO-Ioana:MAI-Voice-2", + "ro-RO-Radu:MAI-Voice-2", + "ru-RU-Lev:MAI-Voice-2", + "ru-RU-Masha:MAI-Voice-2", + "th-TH-Krit:MAI-Voice-2", + "th-TH-Nattapong:MAI-Voice-2", + "tr-TR-Aydin:MAI-Voice-2", + "tr-TR-Elif:MAI-Voice-2", + "zh-CN-Bo:MAI-Voice-2", + "zh-CN-Lan:MAI-Voice-2", + "zh-CN-Mei:MAI-Voice-2" + ], + "example": "en-US-Ethan:MAI-Voice-2" + }, + "style": { + "type": "string", + "description": "Speaking style applied via mstts:express-as on every request. Unknown styles are ignored by Azure and fall back to neutral.", + "enum": [ + "adventurous", + "angry", + "caring", + "cheerful", + "confused", + "curious", + "determined", + "disappointed", + "disgusted", + "embarrassed", + "empathy", + "encouraging", + "excited", + "fearful", + "friendly", + "happy", + "hopeful", + "jealous", + "joyful", + "nostalgic", + "reflective", + "regretful", + "relieved", + "sad", + "serious", + "shouting", + "softvoice", + "surprised", + "whispering" + ], + "example": "happy" + }, + "styleDegree": { + "type": "number", + "description": "Style intensity (0.01–2). Default 1 = the predefined style strength. Only applies when `style` is set.", + "minimum": 0.01, + "maximum": 2, + "default": 1 + }, + "role": { + "type": "string", + "description": "Role-play (age/gender imitation). Requires `style` to be set; ignored otherwise.", + "enum": [ + "Girl", + "Boy", + "YoungAdultFemale", + "YoungAdultMale", + "OlderAdultFemale", + "OlderAdultMale", + "SeniorFemale", + "SeniorMale" + ], + "example": "YoungAdultFemale" + }, + "speed": { + "type": "number", + "description": "This is the speed multiplier that will be used.", + "minimum": 0.5, + "maximum": 2 + }, + "chunkPlan": { + "description": "This is the plan for chunking the model output before it is sent to the voice provider.", + "allOf": [ + { + "$ref": "#/components/schemas/ChunkPlan" + } + ] + } + }, + "required": [ + "provider", + "voiceId" + ] + }, + "TransportConfigurationTwilio": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "twilio" + ] + }, + "timeout": { + "type": "number", + "description": "The integer number of seconds that we should allow the phone to ring before assuming there is no answer.\nThe default is `60` seconds and the maximum is `600` seconds.\nFor some call flows, we will add a 5-second buffer to the timeout value you provide.\nFor this reason, a timeout value of 10 seconds could result in an actual timeout closer to 15 seconds.\nYou can set this to a short time, such as `15` seconds, to hang up before reaching an answering machine or voicemail.\n\n@default 60", + "minimum": 1, + "maximum": 600, + "example": 60 + }, + "record": { + "type": "boolean", + "description": "Whether to record the call.\nCan be `true` to record the phone call, or `false` to not.\nThe default is `false`.\n\n@default false", + "example": false + }, + "recordingChannels": { + "type": "string", + "description": "The number of channels in the final recording.\nCan be: `mono` or `dual`.\nThe default is `mono`.\n`mono` records both legs of the call in a single channel of the recording file.\n`dual` records each leg to a separate channel of the recording file.\nThe first channel of a dual-channel recording contains the parent call and the second channel contains the child call.\n\n@default 'mono'", + "enum": [ + "mono", + "dual" + ], + "example": "mono" + } + }, + "required": [ + "provider" + ] + }, + "CreateAnthropicCredentialDTO": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "anthropic" + ] + }, + "apiKey": { + "type": "string", + "maxLength": 10000, + "description": "This is not returned in the API." + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + }, + "required": [ + "provider", + "apiKey" + ] + }, + "CreateAnthropicBedrockCredentialDTO": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "anthropic-bedrock" + ] + }, + "region": { + "type": "string", + "description": "AWS region where Bedrock is configured.", + "enum": [ + "us-east-1", + "us-west-2", + "eu-central-1", + "eu-west-1", + "eu-west-3", + "ap-northeast-1", + "ap-southeast-2" + ] + }, + "authenticationPlan": { + "description": "Authentication method - either direct IAM credentials or cross-account role assumption.", + "oneOf": [ + { + "$ref": "#/components/schemas/AWSIAMCredentialsAuthenticationPlan" + }, + { + "$ref": "#/components/schemas/AWSStsAuthenticationPlan" + } + ] + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + }, + "required": [ + "provider", + "region", + "authenticationPlan" + ] + }, + "CreateAnyscaleCredentialDTO": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "anyscale" + ] + }, + "apiKey": { + "type": "string", + "maxLength": 10000, + "description": "This is not returned in the API." + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + }, + "required": [ + "provider", + "apiKey" + ] + }, + "CreateAssemblyAICredentialDTO": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "assembly-ai" + ] + }, + "apiKey": { + "type": "string", + "description": "This is not returned in the API." + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + }, + "required": [ + "provider", + "apiKey" + ] + }, + "AzureBlobStorageBucketPlan": { + "type": "object", + "properties": { + "connectionString": { + "type": "string", + "description": "This is the blob storage connection string for the Azure resource." + }, + "containerName": { + "type": "string", + "description": "This is the container name for the Azure blob storage." + }, + "path": { + "type": "string", + "description": "This is the path where call artifacts will be stored.\n\nUsage:\n- To store call artifacts in a specific folder, set this to the full path. Eg. \"/folder-name1/folder-name2\".\n- To store call artifacts in the root of the bucket, leave this blank.\n\n@default \"/\"" + } + }, + "required": [ + "connectionString", + "containerName" + ] + }, + "CreateAzureCredentialDTO": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "azure" + ] + }, + "service": { + "type": "string", + "description": "This is the service being used in Azure.", + "enum": [ + "speech", + "blob_storage" + ], + "default": "speech" + }, + "region": { + "type": "string", + "description": "This is the region of the Azure resource.", + "enum": [ + "australiaeast", + "canadaeast", + "canadacentral", + "centralus", + "eastus2", + "eastus", + "france", + "germanywestcentral", + "india", + "japaneast", + "japanwest", + "northcentralus", + "norway", + "polandcentral", + "southcentralus", + "spaincentral", + "swedencentral", + "switzerland", + "switzerlandnorth", + "switzerlandwest", + "uaenorth", + "uk", + "westeurope", + "westus", + "westus3" + ] + }, + "apiKey": { + "type": "string", + "description": "This is not returned in the API.", + "maxLength": 10000 + }, + "fallbackIndex": { + "type": "number", + "minimum": 1, + "description": "This is the order in which this storage provider is tried during upload retries. Lower numbers are tried first in increasing order." + }, + "bucketPlan": { + "description": "This is the bucket plan that can be provided to store call artifacts in Azure Blob Storage.", + "allOf": [ + { + "$ref": "#/components/schemas/AzureBlobStorageBucketPlan" + } + ] + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + }, + "required": [ + "provider", + "service" + ] + }, + "CreateAzureOpenAICredentialDTO": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "azure-openai" + ] + }, + "region": { + "type": "string", + "enum": [ + "australiaeast", + "canadaeast", + "canadacentral", + "centralus", + "eastus2", + "eastus", + "france", + "germanywestcentral", + "india", + "japaneast", + "japanwest", + "northcentralus", + "norway", + "polandcentral", + "southcentralus", + "spaincentral", + "swedencentral", + "switzerland", + "switzerlandnorth", + "switzerlandwest", + "uaenorth", + "uk", + "westeurope", + "westus", + "westus3" + ] + }, + "models": { + "type": "array", + "enum": [ + "gpt-5.6-luna-2026-07-09", + "gpt-5.6-terra-2026-07-09", + "gpt-5.6-sol-2026-07-09", + "gpt-5.4", + "gpt-5.4-mini", + "gpt-5.4-nano", + "gpt-5.2", + "gpt-5.2-chat", + "gpt-5.1", + "gpt-5.1-chat", + "gpt-5", + "gpt-5-mini", + "gpt-5-nano", + "gpt-4.1-2025-04-14", + "gpt-4.1-mini-2025-04-14", + "gpt-4.1-nano-2025-04-14", + "gpt-4o-2024-11-20", + "gpt-4o-2024-08-06", + "gpt-4o-2024-05-13", + "gpt-4o-mini-2024-07-18", + "gpt-4-turbo-2024-04-09", + "gpt-4-0125-preview", + "gpt-4-1106-preview", + "gpt-4-0613", + "gpt-35-turbo-0125", + "gpt-35-turbo-1106", + "gpt-4o", + "gpt-4.1", + "gpt-5.4-mini-2026-03-17" + ], + "example": [ + "gpt-4-0125-preview", + "gpt-4-0613" + ], + "items": { + "type": "string", + "enum": [ + "gpt-5.6-luna-2026-07-09", + "gpt-5.6-terra-2026-07-09", + "gpt-5.6-sol-2026-07-09", + "gpt-5.4", + "gpt-5.4-mini", + "gpt-5.4-nano", + "gpt-5.2", + "gpt-5.2-chat", + "gpt-5.1", + "gpt-5.1-chat", + "gpt-5", + "gpt-5-mini", + "gpt-5-nano", + "gpt-4.1-2025-04-14", + "gpt-4.1-mini-2025-04-14", + "gpt-4.1-nano-2025-04-14", + "gpt-4o-2024-11-20", + "gpt-4o-2024-08-06", + "gpt-4o-2024-05-13", + "gpt-4o-mini-2024-07-18", + "gpt-4-turbo-2024-04-09", + "gpt-4-0125-preview", + "gpt-4-1106-preview", + "gpt-4-0613", + "gpt-35-turbo-0125", + "gpt-35-turbo-1106", + "gpt-4o", + "gpt-4.1", + "gpt-5.4-mini-2026-03-17" + ] + } + }, + "openAIKey": { + "type": "string", + "maxLength": 10000, + "description": "This is not returned in the API." + }, + "ocpApimSubscriptionKey": { + "type": "string", + "description": "This is not returned in the API." + }, + "openAIEndpoint": { + "type": "string", + "maxLength": 10000 + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + }, + "required": [ + "provider", + "region", + "models", + "openAIKey", + "openAIEndpoint" + ] + }, + "SipTrunkGateway": { + "type": "object", + "properties": { + "ip": { + "type": "string", + "description": "This is the address of the gateway. Inbound gateways require an IPv4 address like 1.1.1.1. Outbound-only gateways can also use a fully qualified domain name like my-sip-trunk.pstn.twilio.com." + }, + "port": { + "type": "number", + "description": "This is the port number of the gateway. Default is 5060.\n\n@default 5060", + "minimum": 1, + "maximum": 65535 + }, + "netmask": { + "type": "number", + "description": "This is the netmask of the gateway. Defaults to 32.\n\n@default 32", + "minimum": 24, + "maximum": 32 + }, + "inboundEnabled": { + "type": "boolean", + "description": "This is whether inbound calls are allowed from this gateway. Default is true.\n\n@default true" + }, + "outboundEnabled": { + "type": "boolean", + "description": "This is whether outbound calls should be sent to this gateway. Default is true.\n\nNote, if netmask is less than 32, it doesn't affect the outbound IPs that are tried. 1 attempt is made to `ip:port`.\n\n@default true" + }, + "outboundProtocol": { + "type": "string", + "description": "This is the protocol to use for SIP signaling outbound calls. Default is udp.\n\n@default udp", + "enum": [ + "tls/srtp", + "tcp", + "tls", + "udp" + ] + }, + "optionsPingEnabled": { + "type": "boolean", + "description": "This is whether to send options ping to the gateway. This can be used to check if the gateway is reachable. Default is false.\n\nThis is useful for high availability setups where you want to check if the gateway is reachable before routing calls to it. Note, if no gateway for a trunk is reachable, outbound calls will be rejected.\n\n@default false" + } + }, + "required": [ + "ip" + ] + }, + "SipTrunkOutboundSipRegisterPlan": { + "type": "object", + "properties": { + "domain": { + "type": "string" + }, + "username": { + "type": "string" + }, + "realm": { + "type": "string" + } + } + }, + "SipTrunkOutboundAuthenticationPlan": { + "type": "object", + "properties": { + "authPassword": { + "type": "string", + "description": "This is not returned in the API." + }, + "authUsername": { + "type": "string" + }, + "sipRegisterPlan": { + "description": "This can be used to configure if SIP register is required by the SIP trunk. If not provided, no SIP registration will be attempted.", + "allOf": [ + { + "$ref": "#/components/schemas/SipTrunkOutboundSipRegisterPlan" + } + ] + } + } + }, + "CreateByoSipTrunkCredentialDTO": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "description": "This can be used to bring your own SIP trunks or to connect to a Carrier.", + "enum": [ + "byo-sip-trunk" + ] + }, + "gateways": { + "description": "This is the list of SIP trunk's gateways.", + "type": "array", + "items": { + "$ref": "#/components/schemas/SipTrunkGateway" + } + }, + "outboundAuthenticationPlan": { + "description": "This can be used to configure the outbound authentication if required by the SIP trunk.", + "allOf": [ + { + "$ref": "#/components/schemas/SipTrunkOutboundAuthenticationPlan" + } + ] + }, + "outboundLeadingPlusEnabled": { + "type": "boolean", + "description": "This ensures the outbound origination attempts have a leading plus. Defaults to false to match conventional telecom behavior.\n\nUsage:\n- Vonage/Twilio requires leading plus for all outbound calls. Set this to true.\n\n@default false" + }, + "techPrefix": { + "type": "string", + "description": "This can be used to configure the tech prefix on outbound calls. This is an advanced property.", + "maxLength": 10000 + }, + "sipDiversionHeader": { + "type": "string", + "description": "This can be used to enable the SIP diversion header for authenticating the calling number if the SIP trunk supports it. This is an advanced property.", + "maxLength": 10000 + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + }, + "required": [ + "gateways" + ] + }, + "CreateCartesiaCredentialDTO": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "cartesia" + ] + }, + "apiKey": { + "type": "string", + "description": "This is not returned in the API." + }, + "apiUrl": { + "type": "string", + "description": "This can be used to point to an onprem Cartesia instance. Defaults to api.cartesia.ai." + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + }, + "required": [ + "provider", + "apiKey" + ] + }, + "CloudflareR2BucketPlan": { + "type": "object", + "properties": { + "accessKeyId": { + "type": "string", + "description": "Cloudflare R2 Access key ID." + }, + "secretAccessKey": { + "type": "string", + "description": "Cloudflare R2 access key secret. This is not returned in the API." + }, + "url": { + "type": "string", + "description": "Cloudflare R2 base url." + }, + "name": { + "type": "string", + "description": "This is the name of the bucket." + }, + "path": { + "type": "string", + "description": "This is the path where call artifacts will be stored.\n\nUsage:\n- To store call artifacts in a specific folder, set this to the full path. Eg. \"/folder-name1/folder-name2\".\n- To store call artifacts in the root of the bucket, leave this blank.\n\n@default \"/\"" + } + }, + "required": [ + "name" + ] + }, + "CreateCloudflareCredentialDTO": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "cloudflare" + ], + "description": "Credential provider. Only allowed value is cloudflare" + }, + "accountId": { + "type": "string", + "description": "Cloudflare Account Id." + }, + "apiKey": { + "type": "string", + "description": "Cloudflare API Key / Token." + }, + "accountEmail": { + "type": "string", + "description": "Cloudflare Account Email." + }, + "fallbackIndex": { + "type": "number", + "description": "This is the order in which this storage provider is tried during upload retries. Lower numbers are tried first in increasing order.", + "minimum": 1 + }, + "bucketPlan": { + "description": "This is the bucket plan that can be provided to store call artifacts in R2", + "allOf": [ + { + "$ref": "#/components/schemas/CloudflareR2BucketPlan" + } + ] + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + }, + "required": [ + "provider" + ] + }, + "OAuth2AuthenticationPlan": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "oauth2" + ] + }, + "url": { + "type": "string", + "description": "This is the OAuth2 URL." + }, + "clientId": { + "type": "string", + "description": "This is the OAuth2 client ID." + }, + "clientSecret": { + "type": "string", + "description": "This is the OAuth2 client secret." + }, + "scope": { + "type": "string", + "description": "This is the scope of the OAuth2 token.", + "maxLength": 1000 + } + }, + "required": [ + "type", + "url", + "clientId", + "clientSecret" + ] + }, + "CreateCustomLLMCredentialDTO": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "custom-llm" + ] + }, + "apiKey": { + "type": "string", + "maxLength": 10000, + "description": "This is not returned in the API." + }, + "authenticationPlan": { + "description": "This is the authentication plan. Currently supports OAuth2 RFC 6749. To use Bearer authentication, use apiKey", + "allOf": [ + { + "$ref": "#/components/schemas/OAuth2AuthenticationPlan" + } + ] + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + }, + "required": [ + "provider", + "apiKey" + ] + }, + "CreateDeepgramCredentialDTO": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "deepgram" + ] + }, + "apiKey": { + "type": "string", + "description": "This is not returned in the API." + }, + "apiUrl": { + "type": "string", + "description": "This can be used to point to an onprem Deepgram instance. Defaults to api.deepgram.com." + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + }, + "required": [ + "provider", + "apiKey" + ] + }, + "CreateDeepInfraCredentialDTO": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "deepinfra" + ] + }, + "apiKey": { + "type": "string", + "description": "This is not returned in the API." + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + }, + "required": [ + "provider", + "apiKey" + ] + }, + "CreateDeepSeekCredentialDTO": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "deep-seek" + ] + }, + "apiKey": { + "type": "string", + "description": "This is not returned in the API." + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + }, + "required": [ + "provider", + "apiKey" + ] + }, + "CreateElevenLabsCredentialDTO": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "11labs" + ] + }, + "apiKey": { + "type": "string", + "maxLength": 10000, + "description": "This is not returned in the API." + }, + "apiUrl": { + "type": "string", + "enum": [ + "https://api.elevenlabs.io", + "https://api.eu.residency.elevenlabs.io" + ], + "description": "ElevenLabs-only API environment for this key: the global endpoint or the EU data residency endpoint. In EU deployments, new credentials must explicitly use the EU data residency endpoint; existing credentials may omit this field on update to retain their saved endpoint. Outside EU deployments, Vapi detects an omitted endpoint automatically and null on update clears and re-detects the endpoint.", + "nullable": true + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + }, + "required": [ + "provider", + "apiKey" + ] + }, + "GcpKey": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "This is the type of the key. Most likely, this is \"service_account\"." + }, + "projectId": { + "type": "string", + "description": "This is the ID of the Google Cloud project associated with this key." + }, + "privateKeyId": { + "type": "string", + "description": "This is the unique identifier for the private key." + }, + "privateKey": { + "type": "string", + "description": "This is the private key in PEM format.\n\nNote: This is not returned in the API." + }, + "clientEmail": { + "type": "string", + "description": "This is the email address associated with the service account." + }, + "clientId": { + "type": "string", + "description": "This is the unique identifier for the client." + }, + "authUri": { + "type": "string", + "description": "This is the URI for the auth provider's authorization endpoint." + }, + "tokenUri": { + "type": "string", + "description": "This is the URI for the auth provider's token endpoint." + }, + "authProviderX509CertUrl": { + "type": "string", + "description": "This is the URL of the public x509 certificate for the auth provider." + }, + "clientX509CertUrl": { + "type": "string", + "description": "This is the URL of the public x509 certificate for the client." + }, + "universeDomain": { + "type": "string", + "description": "This is the domain associated with the universe this service account belongs to." + } + }, + "required": [ + "type", + "projectId", + "privateKeyId", + "privateKey", + "clientEmail", + "clientId", + "authUri", + "tokenUri", + "authProviderX509CertUrl", + "clientX509CertUrl", + "universeDomain" + ] + }, + "BucketPlan": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "This is the name of the bucket." + }, + "region": { + "type": "string", + "description": "This is the region of the bucket.\n\nUsage:\n- If `credential.type` is `aws`, then this is required.\n- If `credential.type` is `gcp`, then this is optional since GCP allows buckets to be accessed without a region but region is required for data residency requirements. Read here: https://cloud.google.com/storage/docs/request-endpoints\n\nThis overrides the `credential.region` field if it is provided." + }, + "path": { + "type": "string", + "description": "This is the path where call artifacts will be stored.\n\nUsage:\n- To store call artifacts in a specific folder, set this to the full path. Eg. \"/folder-name1/folder-name2\".\n- To store call artifacts in the root of the bucket, leave this blank.\n\n@default \"/\"" + }, + "hmacAccessKey": { + "type": "string", + "description": "This is the HMAC access key offered by GCP for interoperability with S3 clients. Here is the guide on how to create: https://cloud.google.com/storage/docs/authentication/managing-hmackeys#console\n\nUsage:\n- If `credential.type` is `gcp`, then this is required.\n- If `credential.type` is `aws`, then this is not required since credential.awsAccessKeyId is used instead." + }, + "hmacSecret": { + "type": "string", + "description": "This is the secret for the HMAC access key. Here is the guide on how to create: https://cloud.google.com/storage/docs/authentication/managing-hmackeys#console\n\nUsage:\n- If `credential.type` is `gcp`, then this is required.\n- If `credential.type` is `aws`, then this is not required since credential.awsSecretAccessKey is used instead.\n\nNote: This is not returned in the API." + } + }, + "required": [ + "name" + ] + }, + "CreateGcpCredentialDTO": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "gcp" + ] + }, + "fallbackIndex": { + "type": "number", + "description": "This is the order in which this storage provider is tried during upload retries. Lower numbers are tried first in increasing order.", + "minimum": 1 + }, + "gcpKey": { + "description": "This is the GCP key. This is the JSON that can be generated in the Google Cloud Console at https://console.cloud.google.com/iam-admin/serviceaccounts/details//keys.\n\nThe schema is identical to the JSON that GCP outputs.", + "allOf": [ + { + "$ref": "#/components/schemas/GcpKey" + } + ] + }, + "region": { + "type": "string", + "description": "This is the region of the GCP resource.", + "maxLength": 40 + }, + "bucketPlan": { + "$ref": "#/components/schemas/BucketPlan" + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + }, + "required": [ + "provider", + "gcpKey" + ] + }, + "CreateGladiaCredentialDTO": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "gladia" + ] + }, + "apiKey": { + "type": "string", + "description": "This is not returned in the API." + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + }, + "required": [ + "provider", + "apiKey" + ] + }, + "CreateGoHighLevelCredentialDTO": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "gohighlevel" + ] + }, + "apiKey": { + "type": "string", + "description": "This is not returned in the API." + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + }, + "required": [ + "provider", + "apiKey" + ] + }, + "CreateGroqCredentialDTO": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "groq" + ] + }, + "apiKey": { + "type": "string", + "description": "This is not returned in the API." + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + }, + "required": [ + "provider", + "apiKey" + ] + }, + "CreateLangfuseCredentialDTO": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "langfuse" + ] + }, + "publicKey": { + "type": "string", + "description": "The public key for Langfuse project. Eg: pk-lf-..." + }, + "apiKey": { + "type": "string", + "description": "The secret key for Langfuse project. Eg: sk-lf-... .This is not returned in the API." + }, + "apiUrl": { + "type": "string", + "description": "The host URL for Langfuse project. Eg: https://cloud.langfuse.com" + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + }, + "required": [ + "provider", + "publicKey", + "apiKey", + "apiUrl" + ] + }, + "CreateLmntCredentialDTO": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "lmnt" + ] + }, + "apiKey": { + "type": "string", + "description": "This is not returned in the API." + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + }, + "required": [ + "provider", + "apiKey" + ] + }, + "CreateMakeCredentialDTO": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "make" + ] + }, + "teamId": { + "type": "string", + "description": "Team ID" + }, + "region": { + "type": "string", + "description": "Region of your application. For example: eu1, eu2, us1, us2" + }, + "apiKey": { + "type": "string", + "description": "This is not returned in the API." + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + }, + "required": [ + "provider", + "teamId", + "region", + "apiKey" + ] + }, + "CreateOpenAICredentialDTO": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "openai" + ] + }, + "apiKey": { + "type": "string", + "description": "This is not returned in the API." + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + }, + "required": [ + "provider", + "apiKey" + ] + }, + "CreateOpenRouterCredentialDTO": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "openrouter" + ] + }, + "apiKey": { + "type": "string", + "description": "This is not returned in the API." + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + }, + "required": [ + "provider", + "apiKey" + ] + }, + "CreatePerplexityAICredentialDTO": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "perplexity-ai" + ] + }, + "apiKey": { + "type": "string", + "description": "This is not returned in the API." + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + }, + "required": [ + "provider", + "apiKey" + ] + }, + "CreatePlayHTCredentialDTO": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "playht" + ] + }, + "apiKey": { + "type": "string", + "description": "This is not returned in the API." + }, + "userId": { + "type": "string" + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + }, + "required": [ + "provider", + "apiKey", + "userId" + ] + }, + "CreateRimeAICredentialDTO": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "rime-ai" + ] + }, + "apiKey": { + "type": "string", + "description": "This is not returned in the API." + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + }, + "required": [ + "provider", + "apiKey" + ] + }, + "CreateRunpodCredentialDTO": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "runpod" + ] + }, + "apiKey": { + "type": "string", + "description": "This is not returned in the API." + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + }, + "required": [ + "provider", + "apiKey" + ] + }, + "CreateS3CredentialDTO": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "s3" + ], + "description": "Credential provider. Only allowed value is s3" + }, + "awsAccessKeyId": { + "type": "string", + "description": "AWS access key ID." + }, + "awsSecretAccessKey": { + "type": "string", + "description": "AWS access key secret. This is not returned in the API." + }, + "region": { + "type": "string", + "description": "AWS region in which the S3 bucket is located." + }, + "s3BucketName": { + "type": "string", + "description": "AWS S3 bucket name." + }, + "s3PathPrefix": { + "type": "string", + "description": "The path prefix for the uploaded recording. Ex. \"recordings/\"" + }, + "fallbackIndex": { + "type": "number", + "minimum": 1, + "description": "This is the order in which this storage provider is tried during upload retries. Lower numbers are tried first in increasing order." + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + }, + "required": [ + "provider", + "awsAccessKeyId", + "awsSecretAccessKey", + "region", + "s3BucketName", + "s3PathPrefix" + ] + }, + "SupabaseBucketPlan": { + "type": "object", + "properties": { + "region": { + "type": "string", + "description": "This is the S3 Region. It should look like us-east-1\nIt should be one of the supabase regions defined in the SUPABASE_REGION enum\nCheck https://supabase.com/docs/guides/platform/regions for up to date regions", + "enum": [ + "us-west-1", + "us-east-1", + "us-east-2", + "ca-central-1", + "eu-west-1", + "eu-west-2", + "eu-west-3", + "eu-central-1", + "eu-central-2", + "eu-north-1", + "ap-south-1", + "ap-southeast-1", + "ap-northeast-1", + "ap-northeast-2", + "ap-southeast-2", + "sa-east-1" + ] + }, + "url": { + "type": "string", + "description": "This is the S3 compatible URL for Supabase S3\nThis should look like https://.supabase.co/storage/v1/s3" + }, + "accessKeyId": { + "type": "string", + "description": "This is the Supabase S3 Access Key ID.\nThe user creates this in the Supabase project Storage settings" + }, + "secretAccessKey": { + "type": "string", + "description": "This is the Supabase S3 Secret Access Key.\nThe user creates this in the Supabase project Storage settings along with the access key id" + }, + "name": { + "type": "string", + "description": "This is the Supabase S3 Bucket Name.\nThe user must create this in Supabase under Storage > Buckets\nA bucket that does not exist will not be checked now, but file uploads will fail" + }, + "path": { + "type": "string", + "description": "This is the Supabase S3 Bucket Folder Path.\nThe user can create this in Supabase under Storage > Buckets\nA path that does not exist will not be checked now, but file uploads will fail\nA Path is like a folder in the bucket\nEg. If the bucket is called \"my-bucket\" and the path is \"my-folder\", the full path is \"my-bucket/my-folder\"" + } + }, + "required": [ + "region", + "url", + "accessKeyId", + "secretAccessKey", + "name" + ] + }, + "CreateSupabaseCredentialDTO": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "supabase" + ], + "description": "This is for supabase storage." + }, + "fallbackIndex": { + "type": "number", + "minimum": 1, + "description": "This is the order in which this storage provider is tried during upload retries. Lower numbers are tried first in increasing order." + }, + "bucketPlan": { + "$ref": "#/components/schemas/SupabaseBucketPlan" + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + }, + "required": [ + "provider" + ] + }, + "CreateSmallestAICredentialDTO": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "smallest-ai" + ] + }, + "apiKey": { + "type": "string", + "description": "This is not returned in the API." + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + }, + "required": [ + "provider", + "apiKey" + ] + }, + "CreateTavusCredentialDTO": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "tavus" + ] + }, + "apiKey": { + "type": "string", + "description": "This is not returned in the API." + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + }, + "required": [ + "provider", + "apiKey" + ] + }, + "CreateTogetherAICredentialDTO": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "together-ai" + ] + }, + "apiKey": { + "type": "string", + "description": "This is not returned in the API." + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + }, + "required": [ + "provider", + "apiKey" + ] + }, + "CreateTwilioCredentialDTO": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "twilio" + ] + }, + "authToken": { + "type": "string", + "description": "This is not returned in the API." + }, + "apiKey": { + "type": "string", + "description": "This is not returned in the API." + }, + "apiSecret": { + "type": "string", + "description": "This is not returned in the API." + }, + "accountSid": { + "type": "string" + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + }, + "required": [ + "provider", + "accountSid" + ] + }, + "CreateVonageCredentialDTO": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "vonage" + ] + }, + "apiSecret": { + "type": "string", + "description": "This is not returned in the API." + }, + "apiKey": { + "type": "string" + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + }, + "required": [ + "provider", + "apiSecret", + "apiKey" + ] + }, + "CreateWebhookCredentialDTO": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "webhook" + ] + }, + "authenticationPlan": { + "description": "This is the authentication plan. Supports OAuth2 RFC 6749, HMAC signing, and Bearer authentication.", + "oneOf": [ + { + "$ref": "#/components/schemas/OAuth2AuthenticationPlan" + }, + { + "$ref": "#/components/schemas/HMACAuthenticationPlan" + }, + { + "$ref": "#/components/schemas/BearerAuthenticationPlan" + } + ], + "discriminator": { + "propertyName": "type", + "mapping": { + "oauth2": "#/components/schemas/OAuth2AuthenticationPlan", + "hmac": "#/components/schemas/HMACAuthenticationPlan", + "bearer": "#/components/schemas/BearerAuthenticationPlan" + } + } + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + }, + "required": [ + "provider", + "authenticationPlan" + ] + }, + "CreateXAiCredentialDTO": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "description": "This is the api key for Grok in XAi's console. Get it from here: https://console.x.ai", + "enum": [ + "xai" + ] + }, + "apiKey": { + "type": "string", + "maxLength": 10000, + "description": "This is not returned in the API." + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + }, + "required": [ + "provider", + "apiKey" + ] + }, + "CreateGoogleCalendarOAuth2ClientCredentialDTO": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "google.calendar.oauth2-client" + ] + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + }, + "required": [ + "provider" + ] + }, + "CreateGoogleCalendarOAuth2AuthorizationCredentialDTO": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "google.calendar.oauth2-authorization" + ] + }, + "authorizationId": { + "type": "string", + "description": "The authorization ID for the OAuth2 authorization" + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + }, + "required": [ + "provider", + "authorizationId" + ] + }, + "CreateGoogleSheetsOAuth2AuthorizationCredentialDTO": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "google.sheets.oauth2-authorization" + ] + }, + "authorizationId": { + "type": "string", + "description": "The authorization ID for the OAuth2 authorization" + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + }, + "required": [ + "provider", + "authorizationId" + ] + }, + "CreateSlackOAuth2AuthorizationCredentialDTO": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "slack.oauth2-authorization" + ] + }, + "authorizationId": { + "type": "string", + "description": "The authorization ID for the OAuth2 authorization" + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + }, + "required": [ + "provider", + "authorizationId" + ] + }, + "CreateMinimaxCredentialDTO": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "minimax" + ] + }, + "apiKey": { + "type": "string", + "description": "This is not returned in the API." + }, + "groupId": { + "type": "string", + "description": "This is the Minimax Group ID." + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + }, + "required": [ + "provider", + "apiKey", + "groupId" + ] + }, + "EndpointedSpeechLowConfidenceOptions": { + "type": "object", + "properties": { + "confidenceMin": { + "type": "number", + "description": "This is the minimum confidence threshold.\nTranscripts with confidence below this value will be discarded.\n\n@default confidenceMax - 0.2", + "minimum": 0, + "maximum": 1 + }, + "confidenceMax": { + "type": "number", + "description": "This is the maximum confidence threshold.\nTranscripts with confidence at or above this value will be processed normally.\n\n@default transcriber's confidenceThreshold", + "minimum": 0, + "maximum": 1 + } + } + }, + "CallHookTranscriberEndpointedSpeechLowConfidence": { + "type": "object", + "properties": { + "do": { + "type": "array", + "description": "This is the set of actions to perform when the hook triggers", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/SayHookAction", + "title": "SayHookAction" + }, + { + "$ref": "#/components/schemas/ToolCallHookAction", + "title": "ToolCallHookAction" + }, + { + "$ref": "#/components/schemas/MessageAddHookAction", + "title": "MessageAddHookAction" + } + ] + } + }, + "on": { + "type": "string", + "description": "This is the event that triggers this hook", + "maxLength": 1000 + }, + "options": { + "description": "This is the options for the hook including confidence thresholds", + "allOf": [ + { + "$ref": "#/components/schemas/EndpointedSpeechLowConfidenceOptions" + } + ] + } + }, + "required": [ + "do", + "on" + ] + }, + "SessionCreatedHook": { + "type": "object", + "properties": { + "on": { + "type": "string", + "description": "This is the event that triggers this hook", + "enum": [ + "session.created" + ], + "maxLength": 1000 + }, + "do": { + "type": "array", + "description": "This is the set of actions to perform when the hook triggers.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/ToolCallHookAction", + "title": "ToolCallHookAction" + } + ] + } + }, + "name": { + "type": "string", + "description": "Optional name for this hook instance.\nIf no name is provided, the hook will be auto generated as UUID.\n\n@default UUID", + "maxLength": 1000 + } + }, + "required": [ + "on", + "do" + ] + }, + "SQLInjectionSecurityFilter": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The type of security threat to filter.", + "enum": [ + "sql-injection" + ] + } + }, + "required": [ + "type" + ] + }, + "XSSSecurityFilter": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The type of security threat to filter.", + "enum": [ + "xss" + ] + } + }, + "required": [ + "type" + ] + }, + "SSRFSecurityFilter": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The type of security threat to filter.", + "enum": [ + "ssrf" + ] + } + }, + "required": [ + "type" + ] + }, + "RCESecurityFilter": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The type of security threat to filter.", + "enum": [ + "rce" + ] + } + }, + "required": [ + "type" + ] + }, + "PromptInjectionSecurityFilter": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The type of security threat to filter.", + "enum": [ + "prompt-injection" + ] + } + }, + "required": [ + "type" + ] + }, + "RegexSecurityFilter": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The type of security threat to filter.", + "enum": [ + "regex" + ] + }, + "regex": { + "type": "string", + "description": "The regex pattern to filter.", + "example": "badword1|badword2" + } + }, + "required": [ + "type", + "regex" + ] + }, + "AssistantOverrides": { + "type": "object", + "properties": { + "transcriber": { + "description": "These are the options for the assistant's transcriber.", + "oneOf": [ + { + "$ref": "#/components/schemas/AssemblyAITranscriber", + "title": "AssemblyAITranscriber" + }, + { + "$ref": "#/components/schemas/AzureSpeechTranscriber", + "title": "AzureSpeechTranscriber" + }, + { + "$ref": "#/components/schemas/CustomTranscriber", + "title": "CustomTranscriber" + }, + { + "$ref": "#/components/schemas/DeepgramTranscriber", + "title": "DeepgramTranscriber" + }, + { + "$ref": "#/components/schemas/ElevenLabsTranscriber", + "title": "ElevenLabsTranscriber" + }, + { + "$ref": "#/components/schemas/GladiaTranscriber", + "title": "GladiaTranscriber" + }, + { + "$ref": "#/components/schemas/GoogleTranscriber", + "title": "GoogleTranscriber" + }, + { + "$ref": "#/components/schemas/SpeechmaticsTranscriber", + "title": "SpeechmaticsTranscriber" + }, + { + "$ref": "#/components/schemas/TalkscriberTranscriber", + "title": "TalkscriberTranscriber" + }, + { + "$ref": "#/components/schemas/OpenAITranscriber", + "title": "OpenAITranscriber" + }, + { + "$ref": "#/components/schemas/CartesiaTranscriber", + "title": "CartesiaTranscriber" + }, + { + "$ref": "#/components/schemas/SonioxTranscriber", + "title": "SonioxTranscriber" + }, + { + "$ref": "#/components/schemas/XaiTranscriber", + "title": "XaiTranscriber" + }, + { + "$ref": "#/components/schemas/VapiTranscriber", + "title": "VapiTranscriber" + } + ] + }, + "model": { + "description": "These are the options for the assistant's LLM.", + "oneOf": [ + { + "$ref": "#/components/schemas/AnthropicModel", + "title": "Anthropic" + }, + { + "$ref": "#/components/schemas/AnthropicBedrockModel", + "title": "AnthropicBedrock" + }, + { + "$ref": "#/components/schemas/AnyscaleModel", + "title": "Anyscale" + }, + { + "$ref": "#/components/schemas/CerebrasModel", + "title": "Cerebras" + }, + { + "$ref": "#/components/schemas/CustomLLMModel", + "title": "CustomLLM" + }, + { + "$ref": "#/components/schemas/DeepInfraModel", + "title": "DeepInfra" + }, + { + "$ref": "#/components/schemas/DeepSeekModel", + "title": "DeepSeek" + }, + { + "$ref": "#/components/schemas/GoogleModel", + "title": "Google" + }, + { + "$ref": "#/components/schemas/GroqModel", + "title": "Groq" + }, + { + "$ref": "#/components/schemas/InflectionAIModel", + "title": "InflectionAI" + }, + { + "$ref": "#/components/schemas/MinimaxLLMModel", + "title": "MiniMaxLLM" + }, + { + "$ref": "#/components/schemas/OpenAIModel", + "title": "OpenAI" + }, + { + "$ref": "#/components/schemas/OpenRouterModel", + "title": "OpenRouter" + }, + { + "$ref": "#/components/schemas/PerplexityAIModel", + "title": "PerplexityAI" + }, + { + "$ref": "#/components/schemas/TogetherAIModel", + "title": "Together" + }, + { + "$ref": "#/components/schemas/XaiModel", + "title": "XAI" + }, + { + "$ref": "#/components/schemas/VapiModel", + "title": "Vapi" + } + ] + }, + "voice": { + "description": "These are the options for the assistant's voice.", + "oneOf": [ + { + "$ref": "#/components/schemas/AzureVoice", + "title": "AzureVoice" + }, + { + "$ref": "#/components/schemas/CartesiaVoice", + "title": "CartesiaVoice" + }, + { + "$ref": "#/components/schemas/CustomVoice", + "title": "CustomVoice" + }, + { + "$ref": "#/components/schemas/DeepgramVoice", + "title": "DeepgramVoice" + }, + { + "$ref": "#/components/schemas/ElevenLabsVoice", + "title": "ElevenLabsVoice" + }, + { + "$ref": "#/components/schemas/HumeVoice", + "title": "HumeVoice" + }, + { + "$ref": "#/components/schemas/LMNTVoice", + "title": "LMNTVoice" + }, + { + "$ref": "#/components/schemas/NeuphonicVoice", + "title": "NeuphonicVoice" + }, + { + "$ref": "#/components/schemas/OpenAIVoice", + "title": "OpenAIVoice" + }, + { + "$ref": "#/components/schemas/PlayHTVoice", + "title": "PlayHTVoice" + }, + { + "$ref": "#/components/schemas/WellSaidVoice", + "title": "WellSaidVoice" + }, + { + "$ref": "#/components/schemas/RimeAIVoice", + "title": "RimeAIVoice" + }, + { + "$ref": "#/components/schemas/SmallestAIVoice", + "title": "SmallestAIVoice" + }, + { + "$ref": "#/components/schemas/TavusVoice", + "title": "TavusVoice" + }, + { + "$ref": "#/components/schemas/VapiVoice", + "title": "VapiVoice" + }, + { + "$ref": "#/components/schemas/SesameVoice", + "title": "SesameVoice" + }, + { + "$ref": "#/components/schemas/InworldVoice", + "title": "InworldVoice" + }, + { + "$ref": "#/components/schemas/MinimaxVoice", + "title": "MinimaxVoice" + }, + { + "$ref": "#/components/schemas/XaiVoice", + "title": "XaiVoice" + }, + { + "$ref": "#/components/schemas/MicrosoftVoice", + "title": "MicrosoftVoice" + } + ] + }, + "firstMessage": { + "type": "string", + "description": "This is the first message that the assistant will say. This can also be a URL to a containerized audio file (mp3, wav, etc.).\n\nIf unspecified, assistant will wait for user to speak and use the model to respond once they speak.", + "example": "Hello! How can I help you today?" + }, + "firstMessageInterruptionsEnabled": { + "type": "boolean", + "default": false + }, + "firstMessageMode": { + "type": "string", + "description": "This is the mode for the first message. Default is 'assistant-speaks-first'.\n\nUse:\n- 'assistant-speaks-first' to have the assistant speak first.\n- 'assistant-waits-for-user' to have the assistant wait for the user to speak first.\n- 'assistant-speaks-first-with-model-generated-message' to have the assistant speak first with a message generated by the model based on the conversation state. (`assistant.model.messages` at call start, `call.messages` at squad transfer points).\n\n@default 'assistant-speaks-first'", + "enum": [ + "assistant-speaks-first", + "assistant-speaks-first-with-model-generated-message", + "assistant-waits-for-user" + ], + "example": "assistant-speaks-first" + }, + "voicemailDetection": { + "description": "These are the settings to configure or disable voicemail detection. Alternatively, voicemail detection can be configured using the model.tools=[VoicemailTool].\nBy default, voicemail detection is disabled.", + "oneOf": [ + { + "type": "string", + "enum": [ + "off" + ] + }, + { + "$ref": "#/components/schemas/GoogleVoicemailDetectionPlan", + "title": "Google" + }, + { + "$ref": "#/components/schemas/OpenAIVoicemailDetectionPlan", + "title": "OpenAI" + }, + { + "$ref": "#/components/schemas/TwilioVoicemailDetectionPlan", + "title": "Twilio" + }, + { + "$ref": "#/components/schemas/VapiVoicemailDetectionPlan", + "title": "Vapi" + } + ] + }, + "clientMessages": { + "type": "array", + "enum": [ + "conversation-update", + "assistant.speechStarted", + "function-call", + "function-call-result", + "hang", + "language-changed", + "metadata", + "model-output", + "speech-update", + "status-update", + "transcript", + "tool-calls", + "tool-calls-result", + "tool.completed", + "transfer-update", + "user-interrupted", + "voice-input", + "workflow.node.started", + "assistant.started" + ], + "example": [ + "conversation-update", + "function-call", + "hang", + "model-output", + "speech-update", + "status-update", + "transfer-update", + "transcript", + "tool-calls", + "user-interrupted", + "voice-input", + "workflow.node.started", + "assistant.started" + ], + "description": "These are the messages that will be sent to your Client SDKs. Default is conversation-update,function-call,hang,model-output,speech-update,status-update,transfer-update,transcript,tool-calls,user-interrupted,voice-input,workflow.node.started,assistant.started. You can check the shape of the messages in ClientMessage schema.", + "items": { + "type": "string", + "enum": [ + "conversation-update", + "assistant.speechStarted", + "function-call", + "function-call-result", + "hang", + "language-changed", + "metadata", + "model-output", + "speech-update", + "status-update", + "transcript", + "tool-calls", + "tool-calls-result", + "tool.completed", + "transfer-update", + "user-interrupted", + "voice-input", + "workflow.node.started", + "assistant.started" + ] + } + }, + "serverMessages": { + "type": "array", + "enum": [ + "assistant.started", + "assistant.speechStarted", + "conversation-update", + "end-of-call-report", + "function-call", + "hang", + "language-changed", + "language-change-detected", + "model-output", + "phone-call-control", + "speech-update", + "status-update", + "transcript", + "transcript[transcriptType=\"final\"]", + "tool-calls", + "transfer-destination-request", + "handoff-destination-request", + "transfer-update", + "user-interrupted", + "voice-input", + "chat.created", + "chat.deleted", + "session.created", + "session.updated", + "session.deleted", + "call.deleted", + "call.delete.failed", + "call.artifact.upload" + ], + "example": [ + "conversation-update", + "end-of-call-report", + "function-call", + "hang", + "speech-update", + "status-update", + "tool-calls", + "transfer-destination-request", + "handoff-destination-request", + "user-interrupted", + "assistant.started" + ], + "description": "These are the messages that will be sent to your Server URL. Default is conversation-update,end-of-call-report,function-call,hang,speech-update,status-update,tool-calls,transfer-destination-request,handoff-destination-request,user-interrupted,assistant.started. You can check the shape of the messages in ServerMessage schema.", + "items": { + "type": "string", + "enum": [ + "assistant.started", + "assistant.speechStarted", + "conversation-update", + "end-of-call-report", + "function-call", + "hang", + "language-changed", + "language-change-detected", + "model-output", + "phone-call-control", + "speech-update", + "status-update", + "transcript", + "transcript[transcriptType=\"final\"]", + "tool-calls", + "transfer-destination-request", + "handoff-destination-request", + "transfer-update", + "user-interrupted", + "voice-input", + "chat.created", + "chat.deleted", + "session.created", + "session.updated", + "session.deleted", + "call.deleted", + "call.delete.failed", + "call.artifact.upload" + ] + } + }, + "maxDurationSeconds": { + "type": "number", + "description": "This is the maximum number of seconds that the call will last. When the call reaches this duration, it will be ended.\n\n@default 600 (10 minutes)", + "minimum": 10, + "maximum": 43200, + "example": 600 + }, + "backgroundSound": { + "description": "This is the background sound in the call. Default for phone calls is 'office' and default for web calls is 'off'.\nYou can also provide a custom sound by providing a URL to an audio file.", + "oneOf": [ + { + "type": "string", + "enum": [ + "off", + "office" + ], + "example": "office" + }, + { + "type": "string", + "format": "uri", + "example": "https://www.soundjay.com/ambient/sounds/people-in-lounge-1.mp3" + } + ] + }, + "modelOutputInMessagesEnabled": { + "type": "boolean", + "description": "This determines whether the model's output is used in conversation history rather than the transcription of assistant's speech.\n\n@default false", + "example": false + }, + "transportConfigurations": { + "type": "array", + "description": "These are the configurations to be passed to the transport providers of assistant's calls, like Twilio. You can store multiple configurations for different transport providers. For a call, only the configuration matching the call transport provider is used.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/TransportConfigurationTwilio", + "title": "Twilio" + } + ] + } + }, + "observabilityPlan": { + "description": "This is the plan for observability of assistant's calls.\n\nCurrently, only Langfuse is supported.", + "oneOf": [ + { + "$ref": "#/components/schemas/LangfuseObservabilityPlan", + "title": "Langfuse" + } + ], + "allOf": [ + { + "$ref": "#/components/schemas/LangfuseObservabilityPlan" + } + ] + }, + "credentials": { + "type": "array", + "description": "These are dynamic credentials that will be used for the assistant calls. By default, all the credentials are available for use in the call but you can supplement an additional credentials using this. Dynamic credentials override existing credentials.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/CreateAnthropicCredentialDTO", + "title": "AnthropicCredential" + }, + { + "$ref": "#/components/schemas/CreateAnthropicBedrockCredentialDTO", + "title": "AnthropicBedrockCredential" + }, + { + "$ref": "#/components/schemas/CreateAnyscaleCredentialDTO", + "title": "AnyscaleCredential" + }, + { + "$ref": "#/components/schemas/CreateAssemblyAICredentialDTO", + "title": "AssemblyAICredential" + }, + { + "$ref": "#/components/schemas/CreateAzureCredentialDTO", + "title": "AzureCredential" + }, + { + "$ref": "#/components/schemas/CreateAzureOpenAICredentialDTO", + "title": "AzureOpenAICredential" + }, + { + "$ref": "#/components/schemas/CreateByoSipTrunkCredentialDTO", + "title": "ByoSipTrunkCredential" + }, + { + "$ref": "#/components/schemas/CreateCartesiaCredentialDTO", + "title": "CartesiaCredential" + }, + { + "$ref": "#/components/schemas/CreateCerebrasCredentialDTO", + "title": "CerebrasCredential" + }, + { + "$ref": "#/components/schemas/CreateCloudflareCredentialDTO", + "title": "CloudflareCredential" + }, + { + "$ref": "#/components/schemas/CreateCustomLLMCredentialDTO", + "title": "CustomLLMCredential" + }, + { + "$ref": "#/components/schemas/CreateDeepgramCredentialDTO", + "title": "DeepgramCredential" + }, + { + "$ref": "#/components/schemas/CreateDeepInfraCredentialDTO", + "title": "DeepInfraCredential" + }, + { + "$ref": "#/components/schemas/CreateDeepSeekCredentialDTO", + "title": "DeepSeekCredential" + }, + { + "$ref": "#/components/schemas/CreateElevenLabsCredentialDTO", + "title": "ElevenLabsCredential" + }, + { + "$ref": "#/components/schemas/CreateGcpCredentialDTO", + "title": "GcpCredential" + }, + { + "$ref": "#/components/schemas/CreateGladiaCredentialDTO", + "title": "GladiaCredential" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelCredentialDTO", + "title": "GhlCredential" + }, + { + "$ref": "#/components/schemas/CreateGoogleCredentialDTO", + "title": "GoogleCredential" + }, + { + "$ref": "#/components/schemas/CreateGroqCredentialDTO", + "title": "GroqCredential" + }, + { + "$ref": "#/components/schemas/CreateHumeCredentialDTO", + "title": "HumeCredential" + }, + { + "$ref": "#/components/schemas/CreateInflectionAICredentialDTO", + "title": "InflectionAICredential" + }, + { + "$ref": "#/components/schemas/CreateLangfuseCredentialDTO", + "title": "LangfuseCredential" + }, + { + "$ref": "#/components/schemas/CreateLmntCredentialDTO", + "title": "LmntCredential" + }, + { + "$ref": "#/components/schemas/CreateMakeCredentialDTO", + "title": "MakeCredential" + }, + { + "$ref": "#/components/schemas/CreateMistralCredentialDTO", + "title": "MistralCredential" + }, + { + "$ref": "#/components/schemas/CreateNeuphonicCredentialDTO", + "title": "NeuphonicCredential" + }, + { + "$ref": "#/components/schemas/CreateOpenAICredentialDTO", + "title": "OpenAICredential" + }, + { + "$ref": "#/components/schemas/CreateOpenRouterCredentialDTO", + "title": "OpenRouterCredential" + }, + { + "$ref": "#/components/schemas/CreatePerplexityAICredentialDTO", + "title": "PerplexityAICredential" + }, + { + "$ref": "#/components/schemas/CreatePlayHTCredentialDTO", + "title": "PlayHTCredential" + }, + { + "$ref": "#/components/schemas/CreateRimeAICredentialDTO", + "title": "RimeAICredential" + }, + { + "$ref": "#/components/schemas/CreateRunpodCredentialDTO", + "title": "RunpodCredential" + }, + { + "$ref": "#/components/schemas/CreateS3CredentialDTO", + "title": "S3Credential" + }, + { + "$ref": "#/components/schemas/CreateS3CompatibleCredentialDTO", + "title": "S3CompatibleStorageCredential" + }, + { + "$ref": "#/components/schemas/CreateSmallestAICredentialDTO", + "title": "SmallestAICredential" + }, + { + "$ref": "#/components/schemas/CreateSpeechmaticsCredentialDTO", + "title": "SpeechmaticsCredential" + }, + { + "$ref": "#/components/schemas/CreateSonioxCredentialDTO", + "title": "SonioxCredential" + }, + { + "$ref": "#/components/schemas/CreateSupabaseCredentialDTO", + "title": "SupabaseCredential" + }, + { + "$ref": "#/components/schemas/CreateTavusCredentialDTO", + "title": "TavusCredential" + }, + { + "$ref": "#/components/schemas/CreateTogetherAICredentialDTO", + "title": "TogetherAICredential" + }, + { + "$ref": "#/components/schemas/CreateTwilioCredentialDTO", + "title": "TwilioCredential" + }, + { + "$ref": "#/components/schemas/CreateVonageCredentialDTO", + "title": "VonageCredential" + }, + { + "$ref": "#/components/schemas/CreateWebhookCredentialDTO", + "title": "WebhookCredential" + }, + { + "$ref": "#/components/schemas/CreateCustomCredentialDTO", + "title": "CustomCredential" + }, + { + "$ref": "#/components/schemas/CreateXAiCredentialDTO", + "title": "XAiCredential" + }, + { + "$ref": "#/components/schemas/CreateMicrosoftCredentialDTO", + "title": "MicrosoftCredential" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarOAuth2ClientCredentialDTO", + "title": "GoogleCalendarOAuth2ClientCredential" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarOAuth2AuthorizationCredentialDTO", + "title": "GoogleCalendarOAuth2AuthorizationCredential" + }, + { + "$ref": "#/components/schemas/CreateGoogleSheetsOAuth2AuthorizationCredentialDTO", + "title": "GoogleSheetsOAuth2AuthorizationCredential" + }, + { + "$ref": "#/components/schemas/CreateSlackOAuth2AuthorizationCredentialDTO", + "title": "SlackOAuth2AuthorizationCredential" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelMCPCredentialDTO", + "title": "GoHighLevelMCPCredential" + }, + { + "$ref": "#/components/schemas/CreateInworldCredentialDTO", + "title": "InworldCredential" + }, + { + "$ref": "#/components/schemas/CreateMinimaxCredentialDTO", + "title": "MinimaxCredential" + }, + { + "$ref": "#/components/schemas/CreateWellSaidCredentialDTO", + "title": "WellSaidCredential" + }, + { + "$ref": "#/components/schemas/CreateEmailCredentialDTO", + "title": "EmailCredential" + }, + { + "$ref": "#/components/schemas/CreateSlackWebhookCredentialDTO", + "title": "SlackWebhookCredential" + } + ], + "discriminator": { + "propertyName": "provider", + "mapping": { + "11labs": "#/components/schemas/CreateElevenLabsCredentialDTO", + "anthropic": "#/components/schemas/CreateAnthropicCredentialDTO", + "anthropic-bedrock": "#/components/schemas/CreateAnthropicBedrockCredentialDTO", + "anyscale": "#/components/schemas/CreateAnyscaleCredentialDTO", + "assembly-ai": "#/components/schemas/CreateAssemblyAICredentialDTO", + "azure-openai": "#/components/schemas/CreateAzureOpenAICredentialDTO", + "azure": "#/components/schemas/CreateAzureCredentialDTO", + "byo-sip-trunk": "#/components/schemas/CreateByoSipTrunkCredentialDTO", + "cartesia": "#/components/schemas/CreateCartesiaCredentialDTO", + "cerebras": "#/components/schemas/CreateCerebrasCredentialDTO", + "cloudflare": "#/components/schemas/CreateCloudflareCredentialDTO", + "custom-llm": "#/components/schemas/CreateCustomLLMCredentialDTO", + "deepgram": "#/components/schemas/CreateDeepgramCredentialDTO", + "deepinfra": "#/components/schemas/CreateDeepInfraCredentialDTO", + "deep-seek": "#/components/schemas/CreateDeepSeekCredentialDTO", + "gcp": "#/components/schemas/CreateGcpCredentialDTO", + "gladia": "#/components/schemas/CreateGladiaCredentialDTO", + "gohighlevel": "#/components/schemas/CreateGoHighLevelCredentialDTO", + "google": "#/components/schemas/CreateGoogleCredentialDTO", + "groq": "#/components/schemas/CreateGroqCredentialDTO", + "inflection-ai": "#/components/schemas/CreateInflectionAICredentialDTO", + "langfuse": "#/components/schemas/CreateLangfuseCredentialDTO", + "lmnt": "#/components/schemas/CreateLmntCredentialDTO", + "make": "#/components/schemas/CreateMakeCredentialDTO", + "openai": "#/components/schemas/CreateOpenAICredentialDTO", + "openrouter": "#/components/schemas/CreateOpenRouterCredentialDTO", + "perplexity-ai": "#/components/schemas/CreatePerplexityAICredentialDTO", + "playht": "#/components/schemas/CreatePlayHTCredentialDTO", + "rime-ai": "#/components/schemas/CreateRimeAICredentialDTO", + "runpod": "#/components/schemas/CreateRunpodCredentialDTO", + "s3": "#/components/schemas/CreateS3CredentialDTO", + "s3-compatible": "#/components/schemas/CreateS3CompatibleCredentialDTO", + "supabase": "#/components/schemas/CreateSupabaseCredentialDTO", + "smallest-ai": "#/components/schemas/CreateSmallestAICredentialDTO", + "tavus": "#/components/schemas/CreateTavusCredentialDTO", + "together-ai": "#/components/schemas/CreateTogetherAICredentialDTO", + "twilio": "#/components/schemas/CreateTwilioCredentialDTO", + "vonage": "#/components/schemas/CreateVonageCredentialDTO", + "webhook": "#/components/schemas/CreateWebhookCredentialDTO", + "custom-credential": "#/components/schemas/CreateCustomCredentialDTO", + "xai": "#/components/schemas/CreateXAiCredentialDTO", + "microsoft": "#/components/schemas/CreateMicrosoftCredentialDTO", + "neuphonic": "#/components/schemas/CreateNeuphonicCredentialDTO", + "hume": "#/components/schemas/CreateHumeCredentialDTO", + "mistral": "#/components/schemas/CreateMistralCredentialDTO", + "speechmatics": "#/components/schemas/CreateSpeechmaticsCredentialDTO", + "soniox": "#/components/schemas/CreateSonioxCredentialDTO", + "google.calendar.oauth2-client": "#/components/schemas/CreateGoogleCalendarOAuth2ClientCredentialDTO", + "google.calendar.oauth2-authorization": "#/components/schemas/CreateGoogleCalendarOAuth2AuthorizationCredentialDTO", + "google.sheets.oauth2-authorization": "#/components/schemas/CreateGoogleSheetsOAuth2AuthorizationCredentialDTO", + "slack.oauth2-authorization": "#/components/schemas/CreateSlackOAuth2AuthorizationCredentialDTO", + "ghl.oauth2-authorization": "#/components/schemas/CreateGoHighLevelMCPCredentialDTO", + "inworld": "#/components/schemas/CreateInworldCredentialDTO", + "minimax": "#/components/schemas/CreateMinimaxCredentialDTO", + "wellsaid": "#/components/schemas/CreateWellSaidCredentialDTO", + "email": "#/components/schemas/CreateEmailCredentialDTO", + "slack-webhook": "#/components/schemas/CreateSlackWebhookCredentialDTO" + } + } + } + }, + "hooks": { + "type": "array", + "description": "This is a set of actions that will be performed on certain events.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/CallHookCallEnding", + "title": "CallHookCallEnding" + }, + { + "$ref": "#/components/schemas/CallHookAssistantSpeechInterrupted", + "title": "CallHookAssistantSpeechInterrupted" + }, + { + "$ref": "#/components/schemas/CallHookCustomerSpeechInterrupted", + "title": "CallHookCustomerSpeechInterrupted" + }, + { + "$ref": "#/components/schemas/CallHookCustomerSpeechTimeout", + "title": "CallHookCustomerSpeechTimeout" + }, + { + "$ref": "#/components/schemas/SessionCreatedHook", + "title": "SessionCreatedHook" + } + ] + } + }, + "tools:append": { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/CreateApiRequestToolDTO", + "title": "ApiRequestTool" + }, + { + "$ref": "#/components/schemas/CreateBashToolDTO", + "title": "BashTool" + }, + { + "$ref": "#/components/schemas/CreateCodeToolDTO", + "title": "CodeTool" + }, + { + "$ref": "#/components/schemas/CreateComputerToolDTO", + "title": "ComputerTool" + }, + { + "$ref": "#/components/schemas/CreateDtmfToolDTO", + "title": "DtmfTool" + }, + { + "$ref": "#/components/schemas/CreateEndCallToolDTO", + "title": "EndCallTool" + }, + { + "$ref": "#/components/schemas/CreateFunctionToolDTO", + "title": "FunctionTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelCalendarAvailabilityToolDTO", + "title": "GoHighLevelCalendarAvailabilityTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelCalendarEventCreateToolDTO", + "title": "GoHighLevelCalendarEventCreateTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelContactCreateToolDTO", + "title": "GoHighLevelContactCreateTool" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelContactGetToolDTO", + "title": "GoHighLevelContactGetTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarCheckAvailabilityToolDTO", + "title": "GoogleCalendarCheckAvailabilityTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarCreateEventToolDTO", + "title": "GoogleCalendarCreateEventTool" + }, + { + "$ref": "#/components/schemas/CreateGoogleSheetsRowAppendToolDTO", + "title": "GoogleSheetsRowAppendTool" + }, + { + "$ref": "#/components/schemas/CreateHandoffToolDTO", + "title": "HandoffTool" + }, + { + "$ref": "#/components/schemas/CreateMcpToolDTO", + "title": "McpTool" + }, + { + "$ref": "#/components/schemas/CreateQueryToolDTO", + "title": "QueryTool" + }, + { + "$ref": "#/components/schemas/CreateSlackSendMessageToolDTO", + "title": "SlackSendMessageTool" + }, + { + "$ref": "#/components/schemas/CreateSmsToolDTO", + "title": "SmsTool" + }, + { + "$ref": "#/components/schemas/CreateTextEditorToolDTO", + "title": "TextEditorTool" + }, + { + "$ref": "#/components/schemas/CreateTransferCallToolDTO", + "title": "TransferCallTool" + }, + { + "$ref": "#/components/schemas/CreateSipRequestToolDTO", + "title": "SipRequestTool" + }, + { + "$ref": "#/components/schemas/CreateVoicemailToolDTO", + "title": "VoicemailTool" + } + ] + } + }, + "variableValues": { + "type": "object", + "description": "These are values that will be used to replace the template variables in the assistant messages and other text-based fields.\nThis uses LiquidJS syntax. https://liquidjs.com/tutorials/intro-to-liquid.html\n\nSo for example, `{{ name }}` will be replaced with the value of `name` in `variableValues`.\n`{{\"now\" | date: \"%b %d, %Y, %I:%M %p\", \"America/New_York\"}}` will be replaced with the current date and time in New York.\n Some VAPI reserved defaults:\n - *customer* - the customer object" + }, + "name": { + "type": "string", + "description": "This is the name of the assistant.\n\nThis is required when you want to transfer between assistants in a call.", + "maxLength": 40 + }, + "voicemailMessage": { + "type": "string", + "description": "This is the message that the assistant will say if the call is forwarded to voicemail.\n\nIf unspecified, it will hang up.", + "maxLength": 1000 + }, + "endCallMessage": { + "type": "string", + "description": "This is the message that the assistant will say if it ends the call.\n\nIf unspecified, it will hang up without saying anything.", + "maxLength": 1000 + }, + "endCallPhrases": { + "description": "This list contains phrases that, if spoken by the assistant, will trigger the call to be hung up. Case insensitive.", + "type": "array", + "items": { + "type": "string", + "maxLength": 140, + "minLength": 2 + } + }, + "compliancePlan": { + "$ref": "#/components/schemas/CompliancePlan" + }, + "metadata": { + "type": "object", + "description": "This is for metadata you want to store on the assistant." + }, + "backgroundSpeechDenoisingPlan": { + "description": "This enables filtering of noise and background speech while the user is talking.\n\nFeatures:\n- Smart denoising using Krisp\n- Fourier denoising\n\nSmart denoising can be combined with or used independently of Fourier denoising.\n\nOrder of precedence:\n- Smart denoising\n- Fourier denoising", + "allOf": [ + { + "$ref": "#/components/schemas/BackgroundSpeechDenoisingPlan" + } + ] + }, + "analysisPlan": { + "description": "This is the plan for analysis of assistant's calls. Stored in `call.analysis`.", + "deprecated": true, + "allOf": [ + { + "$ref": "#/components/schemas/AnalysisPlan" + } + ] + }, + "artifactPlan": { + "description": "This is the plan for artifacts generated during assistant's calls. Stored in `call.artifact`.", + "allOf": [ + { + "$ref": "#/components/schemas/ArtifactPlan" + } + ] + }, + "startSpeakingPlan": { + "description": "This is the plan for when the assistant should start talking.\n\nYou should configure this if you're running into these issues:\n- The assistant is too slow to start talking after the customer is done speaking.\n- The assistant is too fast to start talking after the customer is done speaking.\n- The assistant is so fast that it's actually interrupting the customer.", + "allOf": [ + { + "$ref": "#/components/schemas/StartSpeakingPlan" + } + ] + }, + "stopSpeakingPlan": { + "description": "This is the plan for when assistant should stop talking on customer interruption.\n\nYou should configure this if you're running into these issues:\n- The assistant is too slow to recognize customer's interruption.\n- The assistant is too fast to recognize customer's interruption.\n- The assistant is getting interrupted by phrases that are just acknowledgments.\n- The assistant is getting interrupted by background noises.\n- The assistant is not properly stopping -- it starts talking right after getting interrupted.", + "allOf": [ + { + "$ref": "#/components/schemas/StopSpeakingPlan" + } + ] + }, + "monitorPlan": { + "description": "This is the plan for real-time monitoring of the assistant's calls.\n\nUsage:\n- To enable live listening of the assistant's calls, set `monitorPlan.listenEnabled` to `true`.\n- To enable live control of the assistant's calls, set `monitorPlan.controlEnabled` to `true`.\n- To attach monitors to the assistant, set `monitorPlan.monitorIds` to the set of monitor ids.", + "allOf": [ + { + "$ref": "#/components/schemas/MonitorPlan" + } + ] + }, + "credentialIds": { + "description": "These are the credentials that will be used for the assistant calls. By default, all the credentials are available for use in the call but you can provide a subset using this.", + "type": "array", + "items": { + "type": "string" + } + }, + "server": { + "description": "This is where Vapi will send webhooks. You can find all webhooks available along with their shape in ServerMessage schema.\n\nThe order of precedence is:\n\n1. assistant.server.url\n2. phoneNumber.serverUrl\n3. org.serverUrl", + "allOf": [ + { + "$ref": "#/components/schemas/Server" + } + ] + }, + "keypadInputPlan": { + "$ref": "#/components/schemas/KeypadInputPlan" + } + } + }, + "CreateAssistantDTO": { + "type": "object", + "properties": { + "transcriber": { + "description": "These are the options for the assistant's transcriber.", + "oneOf": [ + { + "$ref": "#/components/schemas/AssemblyAITranscriber", + "title": "AssemblyAITranscriber" + }, + { + "$ref": "#/components/schemas/AzureSpeechTranscriber", + "title": "AzureSpeechTranscriber" + }, + { + "$ref": "#/components/schemas/CustomTranscriber", + "title": "CustomTranscriber" + }, + { + "$ref": "#/components/schemas/DeepgramTranscriber", + "title": "DeepgramTranscriber" + }, + { + "$ref": "#/components/schemas/ElevenLabsTranscriber", + "title": "ElevenLabsTranscriber" + }, + { + "$ref": "#/components/schemas/GladiaTranscriber", + "title": "GladiaTranscriber" + }, + { + "$ref": "#/components/schemas/GoogleTranscriber", + "title": "GoogleTranscriber" + }, + { + "$ref": "#/components/schemas/SpeechmaticsTranscriber", + "title": "SpeechmaticsTranscriber" + }, + { + "$ref": "#/components/schemas/TalkscriberTranscriber", + "title": "TalkscriberTranscriber" + }, + { + "$ref": "#/components/schemas/OpenAITranscriber", + "title": "OpenAITranscriber" + }, + { + "$ref": "#/components/schemas/CartesiaTranscriber", + "title": "CartesiaTranscriber" + }, + { + "$ref": "#/components/schemas/SonioxTranscriber", + "title": "SonioxTranscriber" + }, + { + "$ref": "#/components/schemas/XaiTranscriber", + "title": "XaiTranscriber" + }, + { + "$ref": "#/components/schemas/VapiTranscriber", + "title": "VapiTranscriber" + } + ] + }, + "model": { + "description": "These are the options for the assistant's LLM.", + "oneOf": [ + { + "$ref": "#/components/schemas/AnthropicModel", + "title": "Anthropic" + }, + { + "$ref": "#/components/schemas/AnthropicBedrockModel", + "title": "AnthropicBedrock" + }, + { + "$ref": "#/components/schemas/AnyscaleModel", + "title": "Anyscale" + }, + { + "$ref": "#/components/schemas/CerebrasModel", + "title": "Cerebras" + }, + { + "$ref": "#/components/schemas/CustomLLMModel", + "title": "CustomLLM" + }, + { + "$ref": "#/components/schemas/DeepInfraModel", + "title": "DeepInfra" + }, + { + "$ref": "#/components/schemas/DeepSeekModel", + "title": "DeepSeek" + }, + { + "$ref": "#/components/schemas/GoogleModel", + "title": "Google" + }, + { + "$ref": "#/components/schemas/GroqModel", + "title": "Groq" + }, + { + "$ref": "#/components/schemas/InflectionAIModel", + "title": "InflectionAI" + }, + { + "$ref": "#/components/schemas/MinimaxLLMModel", + "title": "MiniMaxLLM" + }, + { + "$ref": "#/components/schemas/OpenAIModel", + "title": "OpenAI" + }, + { + "$ref": "#/components/schemas/OpenRouterModel", + "title": "OpenRouter" + }, + { + "$ref": "#/components/schemas/PerplexityAIModel", + "title": "PerplexityAI" + }, + { + "$ref": "#/components/schemas/TogetherAIModel", + "title": "Together" + }, + { + "$ref": "#/components/schemas/XaiModel", + "title": "XAI" + }, + { + "$ref": "#/components/schemas/VapiModel", + "title": "Vapi" + } + ] + }, + "voice": { + "description": "These are the options for the assistant's voice.", + "oneOf": [ + { + "$ref": "#/components/schemas/AzureVoice", + "title": "AzureVoice" + }, + { + "$ref": "#/components/schemas/CartesiaVoice", + "title": "CartesiaVoice" + }, + { + "$ref": "#/components/schemas/CustomVoice", + "title": "CustomVoice" + }, + { + "$ref": "#/components/schemas/DeepgramVoice", + "title": "DeepgramVoice" + }, + { + "$ref": "#/components/schemas/ElevenLabsVoice", + "title": "ElevenLabsVoice" + }, + { + "$ref": "#/components/schemas/HumeVoice", + "title": "HumeVoice" + }, + { + "$ref": "#/components/schemas/LMNTVoice", + "title": "LMNTVoice" + }, + { + "$ref": "#/components/schemas/NeuphonicVoice", + "title": "NeuphonicVoice" + }, + { + "$ref": "#/components/schemas/OpenAIVoice", + "title": "OpenAIVoice" + }, + { + "$ref": "#/components/schemas/PlayHTVoice", + "title": "PlayHTVoice" + }, + { + "$ref": "#/components/schemas/WellSaidVoice", + "title": "WellSaidVoice" + }, + { + "$ref": "#/components/schemas/RimeAIVoice", + "title": "RimeAIVoice" + }, + { + "$ref": "#/components/schemas/SmallestAIVoice", + "title": "SmallestAIVoice" + }, + { + "$ref": "#/components/schemas/TavusVoice", + "title": "TavusVoice" + }, + { + "$ref": "#/components/schemas/VapiVoice", + "title": "VapiVoice" + }, + { + "$ref": "#/components/schemas/SesameVoice", + "title": "SesameVoice" + }, + { + "$ref": "#/components/schemas/InworldVoice", + "title": "InworldVoice" + }, + { + "$ref": "#/components/schemas/MinimaxVoice", + "title": "MinimaxVoice" + }, + { + "$ref": "#/components/schemas/XaiVoice", + "title": "XaiVoice" + }, + { + "$ref": "#/components/schemas/MicrosoftVoice", + "title": "MicrosoftVoice" + } + ] + }, + "firstMessage": { + "type": "string", + "description": "This is the first message that the assistant will say. This can also be a URL to a containerized audio file (mp3, wav, etc.).\n\nIf unspecified, assistant will wait for user to speak and use the model to respond once they speak.", + "example": "Hello! How can I help you today?" + }, + "firstMessageInterruptionsEnabled": { + "type": "boolean", + "default": false + }, + "firstMessageMode": { + "type": "string", + "description": "This is the mode for the first message. Default is 'assistant-speaks-first'.\n\nUse:\n- 'assistant-speaks-first' to have the assistant speak first.\n- 'assistant-waits-for-user' to have the assistant wait for the user to speak first.\n- 'assistant-speaks-first-with-model-generated-message' to have the assistant speak first with a message generated by the model based on the conversation state. (`assistant.model.messages` at call start, `call.messages` at squad transfer points).\n\n@default 'assistant-speaks-first'", + "enum": [ + "assistant-speaks-first", + "assistant-speaks-first-with-model-generated-message", + "assistant-waits-for-user" + ], + "example": "assistant-speaks-first" + }, + "voicemailDetection": { + "description": "These are the settings to configure or disable voicemail detection. Alternatively, voicemail detection can be configured using the model.tools=[VoicemailTool].\nBy default, voicemail detection is disabled.", + "oneOf": [ + { + "type": "string", + "enum": [ + "off" + ] + }, + { + "$ref": "#/components/schemas/GoogleVoicemailDetectionPlan", + "title": "Google" + }, + { + "$ref": "#/components/schemas/OpenAIVoicemailDetectionPlan", + "title": "OpenAI" + }, + { + "$ref": "#/components/schemas/TwilioVoicemailDetectionPlan", + "title": "Twilio" + }, + { + "$ref": "#/components/schemas/VapiVoicemailDetectionPlan", + "title": "Vapi" + } + ] + }, + "clientMessages": { + "type": "array", + "enum": [ + "conversation-update", + "assistant.speechStarted", + "function-call", + "function-call-result", + "hang", + "language-changed", + "metadata", + "model-output", + "speech-update", + "status-update", + "transcript", + "tool-calls", + "tool-calls-result", + "tool.completed", + "transfer-update", + "user-interrupted", + "voice-input", + "workflow.node.started", + "assistant.started" + ], + "example": [ + "conversation-update", + "function-call", + "hang", + "model-output", + "speech-update", + "status-update", + "transfer-update", + "transcript", + "tool-calls", + "user-interrupted", + "voice-input", + "workflow.node.started", + "assistant.started" + ], + "description": "These are the messages that will be sent to your Client SDKs. Default is conversation-update,function-call,hang,model-output,speech-update,status-update,transfer-update,transcript,tool-calls,user-interrupted,voice-input,workflow.node.started,assistant.started. You can check the shape of the messages in ClientMessage schema.", + "items": { + "type": "string", + "enum": [ + "conversation-update", + "assistant.speechStarted", + "function-call", + "function-call-result", + "hang", + "language-changed", + "metadata", + "model-output", + "speech-update", + "status-update", + "transcript", + "tool-calls", + "tool-calls-result", + "tool.completed", + "transfer-update", + "user-interrupted", + "voice-input", + "workflow.node.started", + "assistant.started" + ] + } + }, + "serverMessages": { + "type": "array", + "enum": [ + "assistant.started", + "assistant.speechStarted", + "conversation-update", + "end-of-call-report", + "function-call", + "hang", + "language-changed", + "language-change-detected", + "model-output", + "phone-call-control", + "speech-update", + "status-update", + "transcript", + "transcript[transcriptType=\"final\"]", + "tool-calls", + "transfer-destination-request", + "handoff-destination-request", + "transfer-update", + "user-interrupted", + "voice-input", + "chat.created", + "chat.deleted", + "session.created", + "session.updated", + "session.deleted", + "call.deleted", + "call.delete.failed", + "call.artifact.upload" + ], + "example": [ + "conversation-update", + "end-of-call-report", + "function-call", + "hang", + "speech-update", + "status-update", + "tool-calls", + "transfer-destination-request", + "handoff-destination-request", + "user-interrupted", + "assistant.started" + ], + "description": "These are the messages that will be sent to your Server URL. Default is conversation-update,end-of-call-report,function-call,hang,speech-update,status-update,tool-calls,transfer-destination-request,handoff-destination-request,user-interrupted,assistant.started. You can check the shape of the messages in ServerMessage schema.", + "items": { + "type": "string", + "enum": [ + "assistant.started", + "assistant.speechStarted", + "conversation-update", + "end-of-call-report", + "function-call", + "hang", + "language-changed", + "language-change-detected", + "model-output", + "phone-call-control", + "speech-update", + "status-update", + "transcript", + "transcript[transcriptType=\"final\"]", + "tool-calls", + "transfer-destination-request", + "handoff-destination-request", + "transfer-update", + "user-interrupted", + "voice-input", + "chat.created", + "chat.deleted", + "session.created", + "session.updated", + "session.deleted", + "call.deleted", + "call.delete.failed", + "call.artifact.upload" + ] + } + }, + "maxDurationSeconds": { + "type": "number", + "description": "This is the maximum number of seconds that the call will last. When the call reaches this duration, it will be ended.\n\n@default 600 (10 minutes)", + "minimum": 10, + "maximum": 43200, + "example": 600 + }, + "backgroundSound": { + "description": "This is the background sound in the call. Default for phone calls is 'office' and default for web calls is 'off'.\nYou can also provide a custom sound by providing a URL to an audio file.", + "oneOf": [ + { + "type": "string", + "enum": [ + "off", + "office" + ], + "example": "office" + }, + { + "type": "string", + "format": "uri", + "example": "https://www.soundjay.com/ambient/sounds/people-in-lounge-1.mp3" + } + ] + }, + "modelOutputInMessagesEnabled": { + "type": "boolean", + "description": "This determines whether the model's output is used in conversation history rather than the transcription of assistant's speech.\n\n@default false", + "example": false + }, + "transportConfigurations": { + "type": "array", + "description": "These are the configurations to be passed to the transport providers of assistant's calls, like Twilio. You can store multiple configurations for different transport providers. For a call, only the configuration matching the call transport provider is used.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/TransportConfigurationTwilio", + "title": "Twilio" + } + ] + } + }, + "observabilityPlan": { + "description": "This is the plan for observability of assistant's calls.\n\nCurrently, only Langfuse is supported.", + "oneOf": [ + { + "$ref": "#/components/schemas/LangfuseObservabilityPlan", + "title": "Langfuse" + } + ], + "allOf": [ + { + "$ref": "#/components/schemas/LangfuseObservabilityPlan" + } + ] + }, + "credentials": { + "type": "array", + "description": "These are dynamic credentials that will be used for the assistant calls. By default, all the credentials are available for use in the call but you can supplement an additional credentials using this. Dynamic credentials override existing credentials.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/CreateAnthropicCredentialDTO", + "title": "AnthropicCredential" + }, + { + "$ref": "#/components/schemas/CreateAnthropicBedrockCredentialDTO", + "title": "AnthropicBedrockCredential" + }, + { + "$ref": "#/components/schemas/CreateAnyscaleCredentialDTO", + "title": "AnyscaleCredential" + }, + { + "$ref": "#/components/schemas/CreateAssemblyAICredentialDTO", + "title": "AssemblyAICredential" + }, + { + "$ref": "#/components/schemas/CreateAzureCredentialDTO", + "title": "AzureCredential" + }, + { + "$ref": "#/components/schemas/CreateAzureOpenAICredentialDTO", + "title": "AzureOpenAICredential" + }, + { + "$ref": "#/components/schemas/CreateByoSipTrunkCredentialDTO", + "title": "ByoSipTrunkCredential" + }, + { + "$ref": "#/components/schemas/CreateCartesiaCredentialDTO", + "title": "CartesiaCredential" + }, + { + "$ref": "#/components/schemas/CreateCerebrasCredentialDTO", + "title": "CerebrasCredential" + }, + { + "$ref": "#/components/schemas/CreateCloudflareCredentialDTO", + "title": "CloudflareCredential" + }, + { + "$ref": "#/components/schemas/CreateCustomLLMCredentialDTO", + "title": "CustomLLMCredential" + }, + { + "$ref": "#/components/schemas/CreateDeepgramCredentialDTO", + "title": "DeepgramCredential" + }, + { + "$ref": "#/components/schemas/CreateDeepInfraCredentialDTO", + "title": "DeepInfraCredential" + }, + { + "$ref": "#/components/schemas/CreateDeepSeekCredentialDTO", + "title": "DeepSeekCredential" + }, + { + "$ref": "#/components/schemas/CreateElevenLabsCredentialDTO", + "title": "ElevenLabsCredential" + }, + { + "$ref": "#/components/schemas/CreateGcpCredentialDTO", + "title": "GcpCredential" + }, + { + "$ref": "#/components/schemas/CreateGladiaCredentialDTO", + "title": "GladiaCredential" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelCredentialDTO", + "title": "GhlCredential" + }, + { + "$ref": "#/components/schemas/CreateGoogleCredentialDTO", + "title": "GoogleCredential" + }, + { + "$ref": "#/components/schemas/CreateGroqCredentialDTO", + "title": "GroqCredential" + }, + { + "$ref": "#/components/schemas/CreateHumeCredentialDTO", + "title": "HumeCredential" + }, + { + "$ref": "#/components/schemas/CreateInflectionAICredentialDTO", + "title": "InflectionAICredential" + }, + { + "$ref": "#/components/schemas/CreateLangfuseCredentialDTO", + "title": "LangfuseCredential" + }, + { + "$ref": "#/components/schemas/CreateLmntCredentialDTO", + "title": "LmntCredential" + }, + { + "$ref": "#/components/schemas/CreateMakeCredentialDTO", + "title": "MakeCredential" + }, + { + "$ref": "#/components/schemas/CreateMistralCredentialDTO", + "title": "MistralCredential" + }, + { + "$ref": "#/components/schemas/CreateNeuphonicCredentialDTO", + "title": "NeuphonicCredential" + }, + { + "$ref": "#/components/schemas/CreateOpenAICredentialDTO", + "title": "OpenAICredential" + }, + { + "$ref": "#/components/schemas/CreateOpenRouterCredentialDTO", + "title": "OpenRouterCredential" + }, + { + "$ref": "#/components/schemas/CreatePerplexityAICredentialDTO", + "title": "PerplexityAICredential" + }, + { + "$ref": "#/components/schemas/CreatePlayHTCredentialDTO", + "title": "PlayHTCredential" + }, + { + "$ref": "#/components/schemas/CreateRimeAICredentialDTO", + "title": "RimeAICredential" + }, + { + "$ref": "#/components/schemas/CreateRunpodCredentialDTO", + "title": "RunpodCredential" + }, + { + "$ref": "#/components/schemas/CreateS3CredentialDTO", + "title": "S3Credential" + }, + { + "$ref": "#/components/schemas/CreateS3CompatibleCredentialDTO", + "title": "S3CompatibleStorageCredential" + }, + { + "$ref": "#/components/schemas/CreateSmallestAICredentialDTO", + "title": "SmallestAICredential" + }, + { + "$ref": "#/components/schemas/CreateSpeechmaticsCredentialDTO", + "title": "SpeechmaticsCredential" + }, + { + "$ref": "#/components/schemas/CreateSonioxCredentialDTO", + "title": "SonioxCredential" + }, + { + "$ref": "#/components/schemas/CreateSupabaseCredentialDTO", + "title": "SupabaseCredential" + }, + { + "$ref": "#/components/schemas/CreateTavusCredentialDTO", + "title": "TavusCredential" + }, + { + "$ref": "#/components/schemas/CreateTogetherAICredentialDTO", + "title": "TogetherAICredential" + }, + { + "$ref": "#/components/schemas/CreateTwilioCredentialDTO", + "title": "TwilioCredential" + }, + { + "$ref": "#/components/schemas/CreateVonageCredentialDTO", + "title": "VonageCredential" + }, + { + "$ref": "#/components/schemas/CreateWebhookCredentialDTO", + "title": "WebhookCredential" + }, + { + "$ref": "#/components/schemas/CreateCustomCredentialDTO", + "title": "CustomCredential" + }, + { + "$ref": "#/components/schemas/CreateXAiCredentialDTO", + "title": "XAiCredential" + }, + { + "$ref": "#/components/schemas/CreateMicrosoftCredentialDTO", + "title": "MicrosoftCredential" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarOAuth2ClientCredentialDTO", + "title": "GoogleCalendarOAuth2ClientCredential" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarOAuth2AuthorizationCredentialDTO", + "title": "GoogleCalendarOAuth2AuthorizationCredential" + }, + { + "$ref": "#/components/schemas/CreateGoogleSheetsOAuth2AuthorizationCredentialDTO", + "title": "GoogleSheetsOAuth2AuthorizationCredential" + }, + { + "$ref": "#/components/schemas/CreateSlackOAuth2AuthorizationCredentialDTO", + "title": "SlackOAuth2AuthorizationCredential" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelMCPCredentialDTO", + "title": "GoHighLevelMCPCredential" + }, + { + "$ref": "#/components/schemas/CreateInworldCredentialDTO", + "title": "InworldCredential" + }, + { + "$ref": "#/components/schemas/CreateMinimaxCredentialDTO", + "title": "MinimaxCredential" + }, + { + "$ref": "#/components/schemas/CreateWellSaidCredentialDTO", + "title": "WellSaidCredential" + }, + { + "$ref": "#/components/schemas/CreateEmailCredentialDTO", + "title": "EmailCredential" + }, + { + "$ref": "#/components/schemas/CreateSlackWebhookCredentialDTO", + "title": "SlackWebhookCredential" + } + ], + "discriminator": { + "propertyName": "provider", + "mapping": { + "11labs": "#/components/schemas/CreateElevenLabsCredentialDTO", + "anthropic": "#/components/schemas/CreateAnthropicCredentialDTO", + "anthropic-bedrock": "#/components/schemas/CreateAnthropicBedrockCredentialDTO", + "anyscale": "#/components/schemas/CreateAnyscaleCredentialDTO", + "assembly-ai": "#/components/schemas/CreateAssemblyAICredentialDTO", + "azure-openai": "#/components/schemas/CreateAzureOpenAICredentialDTO", + "azure": "#/components/schemas/CreateAzureCredentialDTO", + "byo-sip-trunk": "#/components/schemas/CreateByoSipTrunkCredentialDTO", + "cartesia": "#/components/schemas/CreateCartesiaCredentialDTO", + "cerebras": "#/components/schemas/CreateCerebrasCredentialDTO", + "cloudflare": "#/components/schemas/CreateCloudflareCredentialDTO", + "custom-llm": "#/components/schemas/CreateCustomLLMCredentialDTO", + "deepgram": "#/components/schemas/CreateDeepgramCredentialDTO", + "deepinfra": "#/components/schemas/CreateDeepInfraCredentialDTO", + "deep-seek": "#/components/schemas/CreateDeepSeekCredentialDTO", + "gcp": "#/components/schemas/CreateGcpCredentialDTO", + "gladia": "#/components/schemas/CreateGladiaCredentialDTO", + "gohighlevel": "#/components/schemas/CreateGoHighLevelCredentialDTO", + "google": "#/components/schemas/CreateGoogleCredentialDTO", + "groq": "#/components/schemas/CreateGroqCredentialDTO", + "inflection-ai": "#/components/schemas/CreateInflectionAICredentialDTO", + "langfuse": "#/components/schemas/CreateLangfuseCredentialDTO", + "lmnt": "#/components/schemas/CreateLmntCredentialDTO", + "make": "#/components/schemas/CreateMakeCredentialDTO", + "openai": "#/components/schemas/CreateOpenAICredentialDTO", + "openrouter": "#/components/schemas/CreateOpenRouterCredentialDTO", + "perplexity-ai": "#/components/schemas/CreatePerplexityAICredentialDTO", + "playht": "#/components/schemas/CreatePlayHTCredentialDTO", + "rime-ai": "#/components/schemas/CreateRimeAICredentialDTO", + "runpod": "#/components/schemas/CreateRunpodCredentialDTO", + "s3": "#/components/schemas/CreateS3CredentialDTO", + "s3-compatible": "#/components/schemas/CreateS3CompatibleCredentialDTO", + "supabase": "#/components/schemas/CreateSupabaseCredentialDTO", + "smallest-ai": "#/components/schemas/CreateSmallestAICredentialDTO", + "tavus": "#/components/schemas/CreateTavusCredentialDTO", + "together-ai": "#/components/schemas/CreateTogetherAICredentialDTO", + "twilio": "#/components/schemas/CreateTwilioCredentialDTO", + "vonage": "#/components/schemas/CreateVonageCredentialDTO", + "webhook": "#/components/schemas/CreateWebhookCredentialDTO", + "custom-credential": "#/components/schemas/CreateCustomCredentialDTO", + "xai": "#/components/schemas/CreateXAiCredentialDTO", + "microsoft": "#/components/schemas/CreateMicrosoftCredentialDTO", + "neuphonic": "#/components/schemas/CreateNeuphonicCredentialDTO", + "hume": "#/components/schemas/CreateHumeCredentialDTO", + "mistral": "#/components/schemas/CreateMistralCredentialDTO", + "speechmatics": "#/components/schemas/CreateSpeechmaticsCredentialDTO", + "soniox": "#/components/schemas/CreateSonioxCredentialDTO", + "google.calendar.oauth2-client": "#/components/schemas/CreateGoogleCalendarOAuth2ClientCredentialDTO", + "google.calendar.oauth2-authorization": "#/components/schemas/CreateGoogleCalendarOAuth2AuthorizationCredentialDTO", + "google.sheets.oauth2-authorization": "#/components/schemas/CreateGoogleSheetsOAuth2AuthorizationCredentialDTO", + "slack.oauth2-authorization": "#/components/schemas/CreateSlackOAuth2AuthorizationCredentialDTO", + "ghl.oauth2-authorization": "#/components/schemas/CreateGoHighLevelMCPCredentialDTO", + "inworld": "#/components/schemas/CreateInworldCredentialDTO", + "minimax": "#/components/schemas/CreateMinimaxCredentialDTO", + "wellsaid": "#/components/schemas/CreateWellSaidCredentialDTO", + "email": "#/components/schemas/CreateEmailCredentialDTO", + "slack-webhook": "#/components/schemas/CreateSlackWebhookCredentialDTO" + } + } + } + }, + "hooks": { + "type": "array", + "description": "This is a set of actions that will be performed on certain events.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/CallHookCallEnding", + "title": "CallHookCallEnding" + }, + { + "$ref": "#/components/schemas/CallHookAssistantSpeechInterrupted", + "title": "CallHookAssistantSpeechInterrupted" + }, + { + "$ref": "#/components/schemas/CallHookCustomerSpeechInterrupted", + "title": "CallHookCustomerSpeechInterrupted" + }, + { + "$ref": "#/components/schemas/CallHookCustomerSpeechTimeout", + "title": "CallHookCustomerSpeechTimeout" + }, + { + "$ref": "#/components/schemas/SessionCreatedHook", + "title": "SessionCreatedHook" + } + ] + } + }, + "name": { + "type": "string", + "description": "This is the name of the assistant.\n\nThis is required when you want to transfer between assistants in a call.", + "maxLength": 40 + }, + "voicemailMessage": { + "type": "string", + "description": "This is the message that the assistant will say if the call is forwarded to voicemail.\n\nIf unspecified, it will hang up.", + "maxLength": 1000 + }, + "endCallMessage": { + "type": "string", + "description": "This is the message that the assistant will say if it ends the call.\n\nIf unspecified, it will hang up without saying anything.", + "maxLength": 1000 + }, + "endCallPhrases": { + "description": "This list contains phrases that, if spoken by the assistant, will trigger the call to be hung up. Case insensitive.", + "type": "array", + "items": { + "type": "string", + "maxLength": 140, + "minLength": 2 + } + }, + "compliancePlan": { + "$ref": "#/components/schemas/CompliancePlan" + }, + "metadata": { + "type": "object", + "description": "This is for metadata you want to store on the assistant." + }, + "backgroundSpeechDenoisingPlan": { + "description": "This enables filtering of noise and background speech while the user is talking.\n\nFeatures:\n- Smart denoising using Krisp\n- Fourier denoising\n\nSmart denoising can be combined with or used independently of Fourier denoising.\n\nOrder of precedence:\n- Smart denoising\n- Fourier denoising", + "allOf": [ + { + "$ref": "#/components/schemas/BackgroundSpeechDenoisingPlan" + } + ] + }, + "analysisPlan": { + "description": "This is the plan for analysis of assistant's calls. Stored in `call.analysis`.", + "deprecated": true, + "allOf": [ + { + "$ref": "#/components/schemas/AnalysisPlan" + } + ] + }, + "artifactPlan": { + "description": "This is the plan for artifacts generated during assistant's calls. Stored in `call.artifact`.", + "allOf": [ + { + "$ref": "#/components/schemas/ArtifactPlan" + } + ] + }, + "startSpeakingPlan": { + "description": "This is the plan for when the assistant should start talking.\n\nYou should configure this if you're running into these issues:\n- The assistant is too slow to start talking after the customer is done speaking.\n- The assistant is too fast to start talking after the customer is done speaking.\n- The assistant is so fast that it's actually interrupting the customer.", + "allOf": [ + { + "$ref": "#/components/schemas/StartSpeakingPlan" + } + ] + }, + "stopSpeakingPlan": { + "description": "This is the plan for when assistant should stop talking on customer interruption.\n\nYou should configure this if you're running into these issues:\n- The assistant is too slow to recognize customer's interruption.\n- The assistant is too fast to recognize customer's interruption.\n- The assistant is getting interrupted by phrases that are just acknowledgments.\n- The assistant is getting interrupted by background noises.\n- The assistant is not properly stopping -- it starts talking right after getting interrupted.", + "allOf": [ + { + "$ref": "#/components/schemas/StopSpeakingPlan" + } + ] + }, + "monitorPlan": { + "description": "This is the plan for real-time monitoring of the assistant's calls.\n\nUsage:\n- To enable live listening of the assistant's calls, set `monitorPlan.listenEnabled` to `true`.\n- To enable live control of the assistant's calls, set `monitorPlan.controlEnabled` to `true`.\n- To attach monitors to the assistant, set `monitorPlan.monitorIds` to the set of monitor ids.", + "allOf": [ + { + "$ref": "#/components/schemas/MonitorPlan" + } + ] + }, + "credentialIds": { + "description": "These are the credentials that will be used for the assistant calls. By default, all the credentials are available for use in the call but you can provide a subset using this.", + "type": "array", + "items": { + "type": "string" + } + }, + "server": { + "description": "This is where Vapi will send webhooks. You can find all webhooks available along with their shape in ServerMessage schema.\n\nThe order of precedence is:\n\n1. assistant.server.url\n2. phoneNumber.serverUrl\n3. org.serverUrl", + "allOf": [ + { + "$ref": "#/components/schemas/Server" + } + ] + }, + "keypadInputPlan": { + "$ref": "#/components/schemas/KeypadInputPlan" + } + } + }, + "Assistant": { + "type": "object", + "properties": { + "transcriber": { + "description": "These are the options for the assistant's transcriber.", + "oneOf": [ + { + "$ref": "#/components/schemas/AssemblyAITranscriber", + "title": "AssemblyAITranscriber" + }, + { + "$ref": "#/components/schemas/AzureSpeechTranscriber", + "title": "AzureSpeechTranscriber" + }, + { + "$ref": "#/components/schemas/CustomTranscriber", + "title": "CustomTranscriber" + }, + { + "$ref": "#/components/schemas/DeepgramTranscriber", + "title": "DeepgramTranscriber" + }, + { + "$ref": "#/components/schemas/ElevenLabsTranscriber", + "title": "ElevenLabsTranscriber" + }, + { + "$ref": "#/components/schemas/GladiaTranscriber", + "title": "GladiaTranscriber" + }, + { + "$ref": "#/components/schemas/GoogleTranscriber", + "title": "GoogleTranscriber" + }, + { + "$ref": "#/components/schemas/SpeechmaticsTranscriber", + "title": "SpeechmaticsTranscriber" + }, + { + "$ref": "#/components/schemas/TalkscriberTranscriber", + "title": "TalkscriberTranscriber" + }, + { + "$ref": "#/components/schemas/OpenAITranscriber", + "title": "OpenAITranscriber" + }, + { + "$ref": "#/components/schemas/CartesiaTranscriber", + "title": "CartesiaTranscriber" + }, + { + "$ref": "#/components/schemas/SonioxTranscriber", + "title": "SonioxTranscriber" + }, + { + "$ref": "#/components/schemas/XaiTranscriber", + "title": "XaiTranscriber" + }, + { + "$ref": "#/components/schemas/VapiTranscriber", + "title": "VapiTranscriber" + } + ] + }, + "model": { + "description": "These are the options for the assistant's LLM.", + "oneOf": [ + { + "$ref": "#/components/schemas/AnthropicModel", + "title": "Anthropic" + }, + { + "$ref": "#/components/schemas/AnthropicBedrockModel", + "title": "AnthropicBedrock" + }, + { + "$ref": "#/components/schemas/AnyscaleModel", + "title": "Anyscale" + }, + { + "$ref": "#/components/schemas/CerebrasModel", + "title": "Cerebras" + }, + { + "$ref": "#/components/schemas/CustomLLMModel", + "title": "CustomLLM" + }, + { + "$ref": "#/components/schemas/DeepInfraModel", + "title": "DeepInfra" + }, + { + "$ref": "#/components/schemas/DeepSeekModel", + "title": "DeepSeek" + }, + { + "$ref": "#/components/schemas/GoogleModel", + "title": "Google" + }, + { + "$ref": "#/components/schemas/GroqModel", + "title": "Groq" + }, + { + "$ref": "#/components/schemas/InflectionAIModel", + "title": "InflectionAI" + }, + { + "$ref": "#/components/schemas/MinimaxLLMModel", + "title": "MiniMaxLLM" + }, + { + "$ref": "#/components/schemas/OpenAIModel", + "title": "OpenAI" + }, + { + "$ref": "#/components/schemas/OpenRouterModel", + "title": "OpenRouter" + }, + { + "$ref": "#/components/schemas/PerplexityAIModel", + "title": "PerplexityAI" + }, + { + "$ref": "#/components/schemas/TogetherAIModel", + "title": "Together" + }, + { + "$ref": "#/components/schemas/XaiModel", + "title": "XAI" + }, + { + "$ref": "#/components/schemas/VapiModel", + "title": "Vapi" + } + ] + }, + "voice": { + "description": "These are the options for the assistant's voice.", + "oneOf": [ + { + "$ref": "#/components/schemas/AzureVoice", + "title": "AzureVoice" + }, + { + "$ref": "#/components/schemas/CartesiaVoice", + "title": "CartesiaVoice" + }, + { + "$ref": "#/components/schemas/CustomVoice", + "title": "CustomVoice" + }, + { + "$ref": "#/components/schemas/DeepgramVoice", + "title": "DeepgramVoice" + }, + { + "$ref": "#/components/schemas/ElevenLabsVoice", + "title": "ElevenLabsVoice" + }, + { + "$ref": "#/components/schemas/HumeVoice", + "title": "HumeVoice" + }, + { + "$ref": "#/components/schemas/LMNTVoice", + "title": "LMNTVoice" + }, + { + "$ref": "#/components/schemas/NeuphonicVoice", + "title": "NeuphonicVoice" + }, + { + "$ref": "#/components/schemas/OpenAIVoice", + "title": "OpenAIVoice" + }, + { + "$ref": "#/components/schemas/PlayHTVoice", + "title": "PlayHTVoice" + }, + { + "$ref": "#/components/schemas/WellSaidVoice", + "title": "WellSaidVoice" + }, + { + "$ref": "#/components/schemas/RimeAIVoice", + "title": "RimeAIVoice" + }, + { + "$ref": "#/components/schemas/SmallestAIVoice", + "title": "SmallestAIVoice" + }, + { + "$ref": "#/components/schemas/TavusVoice", + "title": "TavusVoice" + }, + { + "$ref": "#/components/schemas/VapiVoice", + "title": "VapiVoice" + }, + { + "$ref": "#/components/schemas/SesameVoice", + "title": "SesameVoice" + }, + { + "$ref": "#/components/schemas/InworldVoice", + "title": "InworldVoice" + }, + { + "$ref": "#/components/schemas/MinimaxVoice", + "title": "MinimaxVoice" + }, + { + "$ref": "#/components/schemas/XaiVoice", + "title": "XaiVoice" + }, + { + "$ref": "#/components/schemas/MicrosoftVoice", + "title": "MicrosoftVoice" + } + ] + }, + "firstMessage": { + "type": "string", + "description": "This is the first message that the assistant will say. This can also be a URL to a containerized audio file (mp3, wav, etc.).\n\nIf unspecified, assistant will wait for user to speak and use the model to respond once they speak.", + "example": "Hello! How can I help you today?" + }, + "firstMessageInterruptionsEnabled": { + "type": "boolean", + "default": false + }, + "firstMessageMode": { + "type": "string", + "description": "This is the mode for the first message. Default is 'assistant-speaks-first'.\n\nUse:\n- 'assistant-speaks-first' to have the assistant speak first.\n- 'assistant-waits-for-user' to have the assistant wait for the user to speak first.\n- 'assistant-speaks-first-with-model-generated-message' to have the assistant speak first with a message generated by the model based on the conversation state. (`assistant.model.messages` at call start, `call.messages` at squad transfer points).\n\n@default 'assistant-speaks-first'", + "enum": [ + "assistant-speaks-first", + "assistant-speaks-first-with-model-generated-message", + "assistant-waits-for-user" + ], + "example": "assistant-speaks-first" + }, + "voicemailDetection": { + "description": "These are the settings to configure or disable voicemail detection. Alternatively, voicemail detection can be configured using the model.tools=[VoicemailTool].\nBy default, voicemail detection is disabled.", + "oneOf": [ + { + "type": "string", + "enum": [ + "off" + ] + }, + { + "$ref": "#/components/schemas/GoogleVoicemailDetectionPlan", + "title": "Google" + }, + { + "$ref": "#/components/schemas/OpenAIVoicemailDetectionPlan", + "title": "OpenAI" + }, + { + "$ref": "#/components/schemas/TwilioVoicemailDetectionPlan", + "title": "Twilio" + }, + { + "$ref": "#/components/schemas/VapiVoicemailDetectionPlan", + "title": "Vapi" + } + ] + }, + "clientMessages": { + "type": "array", + "enum": [ + "conversation-update", + "assistant.speechStarted", + "function-call", + "function-call-result", + "hang", + "language-changed", + "metadata", + "model-output", + "speech-update", + "status-update", + "transcript", + "tool-calls", + "tool-calls-result", + "tool.completed", + "transfer-update", + "user-interrupted", + "voice-input", + "workflow.node.started", + "assistant.started" + ], + "example": [ + "conversation-update", + "function-call", + "hang", + "model-output", + "speech-update", + "status-update", + "transfer-update", + "transcript", + "tool-calls", + "user-interrupted", + "voice-input", + "workflow.node.started", + "assistant.started" + ], + "description": "These are the messages that will be sent to your Client SDKs. Default is conversation-update,function-call,hang,model-output,speech-update,status-update,transfer-update,transcript,tool-calls,user-interrupted,voice-input,workflow.node.started,assistant.started. You can check the shape of the messages in ClientMessage schema.", + "items": { + "type": "string", + "enum": [ + "conversation-update", + "assistant.speechStarted", + "function-call", + "function-call-result", + "hang", + "language-changed", + "metadata", + "model-output", + "speech-update", + "status-update", + "transcript", + "tool-calls", + "tool-calls-result", + "tool.completed", + "transfer-update", + "user-interrupted", + "voice-input", + "workflow.node.started", + "assistant.started" + ] + } + }, + "serverMessages": { + "type": "array", + "enum": [ + "assistant.started", + "assistant.speechStarted", + "conversation-update", + "end-of-call-report", + "function-call", + "hang", + "language-changed", + "language-change-detected", + "model-output", + "phone-call-control", + "speech-update", + "status-update", + "transcript", + "transcript[transcriptType=\"final\"]", + "tool-calls", + "transfer-destination-request", + "handoff-destination-request", + "transfer-update", + "user-interrupted", + "voice-input", + "chat.created", + "chat.deleted", + "session.created", + "session.updated", + "session.deleted", + "call.deleted", + "call.delete.failed", + "call.artifact.upload" + ], + "example": [ + "conversation-update", + "end-of-call-report", + "function-call", + "hang", + "speech-update", + "status-update", + "tool-calls", + "transfer-destination-request", + "handoff-destination-request", + "user-interrupted", + "assistant.started" + ], + "description": "These are the messages that will be sent to your Server URL. Default is conversation-update,end-of-call-report,function-call,hang,speech-update,status-update,tool-calls,transfer-destination-request,handoff-destination-request,user-interrupted,assistant.started. You can check the shape of the messages in ServerMessage schema.", + "items": { + "type": "string", + "enum": [ + "assistant.started", + "assistant.speechStarted", + "conversation-update", + "end-of-call-report", + "function-call", + "hang", + "language-changed", + "language-change-detected", + "model-output", + "phone-call-control", + "speech-update", + "status-update", + "transcript", + "transcript[transcriptType=\"final\"]", + "tool-calls", + "transfer-destination-request", + "handoff-destination-request", + "transfer-update", + "user-interrupted", + "voice-input", + "chat.created", + "chat.deleted", + "session.created", + "session.updated", + "session.deleted", + "call.deleted", + "call.delete.failed", + "call.artifact.upload" + ] + } + }, + "maxDurationSeconds": { + "type": "number", + "description": "This is the maximum number of seconds that the call will last. When the call reaches this duration, it will be ended.\n\n@default 600 (10 minutes)", + "minimum": 10, + "maximum": 43200, + "example": 600 + }, + "backgroundSound": { + "description": "This is the background sound in the call. Default for phone calls is 'office' and default for web calls is 'off'.\nYou can also provide a custom sound by providing a URL to an audio file.", + "oneOf": [ + { + "type": "string", + "enum": [ + "off", + "office" + ], + "example": "office" + }, + { + "type": "string", + "format": "uri", + "example": "https://www.soundjay.com/ambient/sounds/people-in-lounge-1.mp3" + } + ] + }, + "modelOutputInMessagesEnabled": { + "type": "boolean", + "description": "This determines whether the model's output is used in conversation history rather than the transcription of assistant's speech.\n\n@default false", + "example": false + }, + "transportConfigurations": { + "type": "array", + "description": "These are the configurations to be passed to the transport providers of assistant's calls, like Twilio. You can store multiple configurations for different transport providers. For a call, only the configuration matching the call transport provider is used.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/TransportConfigurationTwilio", + "title": "Twilio" + } + ] + } + }, + "observabilityPlan": { + "description": "This is the plan for observability of assistant's calls.\n\nCurrently, only Langfuse is supported.", + "oneOf": [ + { + "$ref": "#/components/schemas/LangfuseObservabilityPlan", + "title": "Langfuse" + } + ], + "allOf": [ + { + "$ref": "#/components/schemas/LangfuseObservabilityPlan" + } + ] + }, + "credentials": { + "type": "array", + "description": "These are dynamic credentials that will be used for the assistant calls. By default, all the credentials are available for use in the call but you can supplement an additional credentials using this. Dynamic credentials override existing credentials.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/CreateAnthropicCredentialDTO", + "title": "AnthropicCredential" + }, + { + "$ref": "#/components/schemas/CreateAnthropicBedrockCredentialDTO", + "title": "AnthropicBedrockCredential" + }, + { + "$ref": "#/components/schemas/CreateAnyscaleCredentialDTO", + "title": "AnyscaleCredential" + }, + { + "$ref": "#/components/schemas/CreateAssemblyAICredentialDTO", + "title": "AssemblyAICredential" + }, + { + "$ref": "#/components/schemas/CreateAzureCredentialDTO", + "title": "AzureCredential" + }, + { + "$ref": "#/components/schemas/CreateAzureOpenAICredentialDTO", + "title": "AzureOpenAICredential" + }, + { + "$ref": "#/components/schemas/CreateByoSipTrunkCredentialDTO", + "title": "ByoSipTrunkCredential" + }, + { + "$ref": "#/components/schemas/CreateCartesiaCredentialDTO", + "title": "CartesiaCredential" + }, + { + "$ref": "#/components/schemas/CreateCerebrasCredentialDTO", + "title": "CerebrasCredential" + }, + { + "$ref": "#/components/schemas/CreateCloudflareCredentialDTO", + "title": "CloudflareCredential" + }, + { + "$ref": "#/components/schemas/CreateCustomLLMCredentialDTO", + "title": "CustomLLMCredential" + }, + { + "$ref": "#/components/schemas/CreateDeepgramCredentialDTO", + "title": "DeepgramCredential" + }, + { + "$ref": "#/components/schemas/CreateDeepInfraCredentialDTO", + "title": "DeepInfraCredential" + }, + { + "$ref": "#/components/schemas/CreateDeepSeekCredentialDTO", + "title": "DeepSeekCredential" + }, + { + "$ref": "#/components/schemas/CreateElevenLabsCredentialDTO", + "title": "ElevenLabsCredential" + }, + { + "$ref": "#/components/schemas/CreateGcpCredentialDTO", + "title": "GcpCredential" + }, + { + "$ref": "#/components/schemas/CreateGladiaCredentialDTO", + "title": "GladiaCredential" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelCredentialDTO", + "title": "GhlCredential" + }, + { + "$ref": "#/components/schemas/CreateGoogleCredentialDTO", + "title": "GoogleCredential" + }, + { + "$ref": "#/components/schemas/CreateGroqCredentialDTO", + "title": "GroqCredential" + }, + { + "$ref": "#/components/schemas/CreateHumeCredentialDTO", + "title": "HumeCredential" + }, + { + "$ref": "#/components/schemas/CreateInflectionAICredentialDTO", + "title": "InflectionAICredential" + }, + { + "$ref": "#/components/schemas/CreateLangfuseCredentialDTO", + "title": "LangfuseCredential" + }, + { + "$ref": "#/components/schemas/CreateLmntCredentialDTO", + "title": "LmntCredential" + }, + { + "$ref": "#/components/schemas/CreateMakeCredentialDTO", + "title": "MakeCredential" + }, + { + "$ref": "#/components/schemas/CreateMistralCredentialDTO", + "title": "MistralCredential" + }, + { + "$ref": "#/components/schemas/CreateNeuphonicCredentialDTO", + "title": "NeuphonicCredential" + }, + { + "$ref": "#/components/schemas/CreateOpenAICredentialDTO", + "title": "OpenAICredential" + }, + { + "$ref": "#/components/schemas/CreateOpenRouterCredentialDTO", + "title": "OpenRouterCredential" + }, + { + "$ref": "#/components/schemas/CreatePerplexityAICredentialDTO", + "title": "PerplexityAICredential" + }, + { + "$ref": "#/components/schemas/CreatePlayHTCredentialDTO", + "title": "PlayHTCredential" + }, + { + "$ref": "#/components/schemas/CreateRimeAICredentialDTO", + "title": "RimeAICredential" + }, + { + "$ref": "#/components/schemas/CreateRunpodCredentialDTO", + "title": "RunpodCredential" + }, + { + "$ref": "#/components/schemas/CreateS3CredentialDTO", + "title": "S3Credential" + }, + { + "$ref": "#/components/schemas/CreateS3CompatibleCredentialDTO", + "title": "S3CompatibleStorageCredential" + }, + { + "$ref": "#/components/schemas/CreateSmallestAICredentialDTO", + "title": "SmallestAICredential" + }, + { + "$ref": "#/components/schemas/CreateSpeechmaticsCredentialDTO", + "title": "SpeechmaticsCredential" + }, + { + "$ref": "#/components/schemas/CreateSonioxCredentialDTO", + "title": "SonioxCredential" + }, + { + "$ref": "#/components/schemas/CreateSupabaseCredentialDTO", + "title": "SupabaseCredential" + }, + { + "$ref": "#/components/schemas/CreateTavusCredentialDTO", + "title": "TavusCredential" + }, + { + "$ref": "#/components/schemas/CreateTogetherAICredentialDTO", + "title": "TogetherAICredential" + }, + { + "$ref": "#/components/schemas/CreateTwilioCredentialDTO", + "title": "TwilioCredential" + }, + { + "$ref": "#/components/schemas/CreateVonageCredentialDTO", + "title": "VonageCredential" + }, + { + "$ref": "#/components/schemas/CreateWebhookCredentialDTO", + "title": "WebhookCredential" + }, + { + "$ref": "#/components/schemas/CreateCustomCredentialDTO", + "title": "CustomCredential" + }, + { + "$ref": "#/components/schemas/CreateXAiCredentialDTO", + "title": "XAiCredential" + }, + { + "$ref": "#/components/schemas/CreateMicrosoftCredentialDTO", + "title": "MicrosoftCredential" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarOAuth2ClientCredentialDTO", + "title": "GoogleCalendarOAuth2ClientCredential" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarOAuth2AuthorizationCredentialDTO", + "title": "GoogleCalendarOAuth2AuthorizationCredential" + }, + { + "$ref": "#/components/schemas/CreateGoogleSheetsOAuth2AuthorizationCredentialDTO", + "title": "GoogleSheetsOAuth2AuthorizationCredential" + }, + { + "$ref": "#/components/schemas/CreateSlackOAuth2AuthorizationCredentialDTO", + "title": "SlackOAuth2AuthorizationCredential" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelMCPCredentialDTO", + "title": "GoHighLevelMCPCredential" + }, + { + "$ref": "#/components/schemas/CreateInworldCredentialDTO", + "title": "InworldCredential" + }, + { + "$ref": "#/components/schemas/CreateMinimaxCredentialDTO", + "title": "MinimaxCredential" + }, + { + "$ref": "#/components/schemas/CreateWellSaidCredentialDTO", + "title": "WellSaidCredential" + }, + { + "$ref": "#/components/schemas/CreateEmailCredentialDTO", + "title": "EmailCredential" + }, + { + "$ref": "#/components/schemas/CreateSlackWebhookCredentialDTO", + "title": "SlackWebhookCredential" + } + ], + "discriminator": { + "propertyName": "provider", + "mapping": { + "11labs": "#/components/schemas/CreateElevenLabsCredentialDTO", + "anthropic": "#/components/schemas/CreateAnthropicCredentialDTO", + "anthropic-bedrock": "#/components/schemas/CreateAnthropicBedrockCredentialDTO", + "anyscale": "#/components/schemas/CreateAnyscaleCredentialDTO", + "assembly-ai": "#/components/schemas/CreateAssemblyAICredentialDTO", + "azure-openai": "#/components/schemas/CreateAzureOpenAICredentialDTO", + "azure": "#/components/schemas/CreateAzureCredentialDTO", + "byo-sip-trunk": "#/components/schemas/CreateByoSipTrunkCredentialDTO", + "cartesia": "#/components/schemas/CreateCartesiaCredentialDTO", + "cerebras": "#/components/schemas/CreateCerebrasCredentialDTO", + "cloudflare": "#/components/schemas/CreateCloudflareCredentialDTO", + "custom-llm": "#/components/schemas/CreateCustomLLMCredentialDTO", + "deepgram": "#/components/schemas/CreateDeepgramCredentialDTO", + "deepinfra": "#/components/schemas/CreateDeepInfraCredentialDTO", + "deep-seek": "#/components/schemas/CreateDeepSeekCredentialDTO", + "gcp": "#/components/schemas/CreateGcpCredentialDTO", + "gladia": "#/components/schemas/CreateGladiaCredentialDTO", + "gohighlevel": "#/components/schemas/CreateGoHighLevelCredentialDTO", + "google": "#/components/schemas/CreateGoogleCredentialDTO", + "groq": "#/components/schemas/CreateGroqCredentialDTO", + "inflection-ai": "#/components/schemas/CreateInflectionAICredentialDTO", + "langfuse": "#/components/schemas/CreateLangfuseCredentialDTO", + "lmnt": "#/components/schemas/CreateLmntCredentialDTO", + "make": "#/components/schemas/CreateMakeCredentialDTO", + "openai": "#/components/schemas/CreateOpenAICredentialDTO", + "openrouter": "#/components/schemas/CreateOpenRouterCredentialDTO", + "perplexity-ai": "#/components/schemas/CreatePerplexityAICredentialDTO", + "playht": "#/components/schemas/CreatePlayHTCredentialDTO", + "rime-ai": "#/components/schemas/CreateRimeAICredentialDTO", + "runpod": "#/components/schemas/CreateRunpodCredentialDTO", + "s3": "#/components/schemas/CreateS3CredentialDTO", + "s3-compatible": "#/components/schemas/CreateS3CompatibleCredentialDTO", + "supabase": "#/components/schemas/CreateSupabaseCredentialDTO", + "smallest-ai": "#/components/schemas/CreateSmallestAICredentialDTO", + "tavus": "#/components/schemas/CreateTavusCredentialDTO", + "together-ai": "#/components/schemas/CreateTogetherAICredentialDTO", + "twilio": "#/components/schemas/CreateTwilioCredentialDTO", + "vonage": "#/components/schemas/CreateVonageCredentialDTO", + "webhook": "#/components/schemas/CreateWebhookCredentialDTO", + "custom-credential": "#/components/schemas/CreateCustomCredentialDTO", + "xai": "#/components/schemas/CreateXAiCredentialDTO", + "microsoft": "#/components/schemas/CreateMicrosoftCredentialDTO", + "neuphonic": "#/components/schemas/CreateNeuphonicCredentialDTO", + "hume": "#/components/schemas/CreateHumeCredentialDTO", + "mistral": "#/components/schemas/CreateMistralCredentialDTO", + "speechmatics": "#/components/schemas/CreateSpeechmaticsCredentialDTO", + "soniox": "#/components/schemas/CreateSonioxCredentialDTO", + "google.calendar.oauth2-client": "#/components/schemas/CreateGoogleCalendarOAuth2ClientCredentialDTO", + "google.calendar.oauth2-authorization": "#/components/schemas/CreateGoogleCalendarOAuth2AuthorizationCredentialDTO", + "google.sheets.oauth2-authorization": "#/components/schemas/CreateGoogleSheetsOAuth2AuthorizationCredentialDTO", + "slack.oauth2-authorization": "#/components/schemas/CreateSlackOAuth2AuthorizationCredentialDTO", + "ghl.oauth2-authorization": "#/components/schemas/CreateGoHighLevelMCPCredentialDTO", + "inworld": "#/components/schemas/CreateInworldCredentialDTO", + "minimax": "#/components/schemas/CreateMinimaxCredentialDTO", + "wellsaid": "#/components/schemas/CreateWellSaidCredentialDTO", + "email": "#/components/schemas/CreateEmailCredentialDTO", + "slack-webhook": "#/components/schemas/CreateSlackWebhookCredentialDTO" + } + } + } + }, + "hooks": { + "type": "array", + "description": "This is a set of actions that will be performed on certain events.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/CallHookCallEnding", + "title": "CallHookCallEnding" + }, + { + "$ref": "#/components/schemas/CallHookAssistantSpeechInterrupted", + "title": "CallHookAssistantSpeechInterrupted" + }, + { + "$ref": "#/components/schemas/CallHookCustomerSpeechInterrupted", + "title": "CallHookCustomerSpeechInterrupted" + }, + { + "$ref": "#/components/schemas/CallHookCustomerSpeechTimeout", + "title": "CallHookCustomerSpeechTimeout" + }, + { + "$ref": "#/components/schemas/SessionCreatedHook", + "title": "SessionCreatedHook" + } + ] + } + }, + "latestVersion": { + "type": "string", + "nullable": true, + "description": "This is the latest version label (e.g. `v3`) of the assistant in the\nversion history. `null` while the org is not yet\nonboarded to versioning, or for assistants that have not yet been\npublished under it." + }, + "name": { + "type": "string", + "description": "This is the name of the assistant.\n\nThis is required when you want to transfer between assistants in a call.", + "maxLength": 40 + }, + "voicemailMessage": { + "type": "string", + "description": "This is the message that the assistant will say if the call is forwarded to voicemail.\n\nIf unspecified, it will hang up.", + "maxLength": 1000 + }, + "endCallMessage": { + "type": "string", + "description": "This is the message that the assistant will say if it ends the call.\n\nIf unspecified, it will hang up without saying anything.", + "maxLength": 1000 + }, + "endCallPhrases": { + "description": "This list contains phrases that, if spoken by the assistant, will trigger the call to be hung up. Case insensitive.", + "type": "array", + "items": { + "type": "string", + "maxLength": 140, + "minLength": 2 + } + }, + "compliancePlan": { + "$ref": "#/components/schemas/CompliancePlan" + }, + "metadata": { + "type": "object", + "description": "This is for metadata you want to store on the assistant." + }, + "backgroundSpeechDenoisingPlan": { + "description": "This enables filtering of noise and background speech while the user is talking.\n\nFeatures:\n- Smart denoising using Krisp\n- Fourier denoising\n\nSmart denoising can be combined with or used independently of Fourier denoising.\n\nOrder of precedence:\n- Smart denoising\n- Fourier denoising", + "allOf": [ + { + "$ref": "#/components/schemas/BackgroundSpeechDenoisingPlan" + } + ] + }, + "analysisPlan": { + "description": "This is the plan for analysis of assistant's calls. Stored in `call.analysis`.", + "deprecated": true, + "allOf": [ + { + "$ref": "#/components/schemas/AnalysisPlan" + } + ] + }, + "artifactPlan": { + "description": "This is the plan for artifacts generated during assistant's calls. Stored in `call.artifact`.", + "allOf": [ + { + "$ref": "#/components/schemas/ArtifactPlan" + } + ] + }, + "startSpeakingPlan": { + "description": "This is the plan for when the assistant should start talking.\n\nYou should configure this if you're running into these issues:\n- The assistant is too slow to start talking after the customer is done speaking.\n- The assistant is too fast to start talking after the customer is done speaking.\n- The assistant is so fast that it's actually interrupting the customer.", + "allOf": [ + { + "$ref": "#/components/schemas/StartSpeakingPlan" + } + ] + }, + "stopSpeakingPlan": { + "description": "This is the plan for when assistant should stop talking on customer interruption.\n\nYou should configure this if you're running into these issues:\n- The assistant is too slow to recognize customer's interruption.\n- The assistant is too fast to recognize customer's interruption.\n- The assistant is getting interrupted by phrases that are just acknowledgments.\n- The assistant is getting interrupted by background noises.\n- The assistant is not properly stopping -- it starts talking right after getting interrupted.", + "allOf": [ + { + "$ref": "#/components/schemas/StopSpeakingPlan" + } + ] + }, + "monitorPlan": { + "description": "This is the plan for real-time monitoring of the assistant's calls.\n\nUsage:\n- To enable live listening of the assistant's calls, set `monitorPlan.listenEnabled` to `true`.\n- To enable live control of the assistant's calls, set `monitorPlan.controlEnabled` to `true`.\n- To attach monitors to the assistant, set `monitorPlan.monitorIds` to the set of monitor ids.", + "allOf": [ + { + "$ref": "#/components/schemas/MonitorPlan" + } + ] + }, + "credentialIds": { + "description": "These are the credentials that will be used for the assistant calls. By default, all the credentials are available for use in the call but you can provide a subset using this.", + "type": "array", + "items": { + "type": "string" + } + }, + "server": { + "description": "This is where Vapi will send webhooks. You can find all webhooks available along with their shape in ServerMessage schema.\n\nThe order of precedence is:\n\n1. assistant.server.url\n2. phoneNumber.serverUrl\n3. org.serverUrl", + "allOf": [ + { + "$ref": "#/components/schemas/Server" + } + ] + }, + "keypadInputPlan": { + "$ref": "#/components/schemas/KeypadInputPlan" + }, + "id": { + "type": "string", + "description": "This is the unique identifier for the assistant." + }, + "orgId": { + "type": "string", + "description": "This is the unique identifier for the org that this assistant belongs to." + }, + "createdAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the assistant was created." + }, + "updatedAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the assistant was last updated." + } + }, + "required": [ + "id", + "orgId", + "createdAt", + "updatedAt" + ] + }, + "PaginationMeta": { + "type": "object", + "properties": { + "itemsPerPage": { + "type": "number" + }, + "totalItems": { + "type": "number" + }, + "currentPage": { + "type": "number" + }, + "totalPages": { + "type": "number" + }, + "hasNextPage": { + "type": "boolean" + }, + "nextCursor": { + "type": "string", + "description": "Opaque cursor for the next page under keyset pagination (PRO-3163). Pass it\nback as the `cursor` query param to fetch the next page without an OFFSET\nscan. Present only when a further page likely exists." + }, + "sortOrder": { + "type": "string", + "enum": [ + "ASC", + "DESC" + ] + }, + "itemsBeyondRetention": { + "type": "boolean" + }, + "createdAtLe": { + "format": "date-time", + "type": "string" + }, + "createdAtGe": { + "format": "date-time", + "type": "string" + } + }, + "required": [ + "itemsPerPage", + "totalItems", + "currentPage" + ] + }, + "AssistantPaginatedResponse": { + "type": "object", + "properties": { + "results": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Assistant" + } + }, + "metadata": { + "$ref": "#/components/schemas/PaginationMeta" + } + }, + "required": [ + "results", + "metadata" + ] + }, + "AssistantDraft": { + "type": "object", + "properties": { + "transcriber": { + "description": "These are the options for the assistant's transcriber.", + "oneOf": [ + { + "$ref": "#/components/schemas/AssemblyAITranscriber", + "title": "AssemblyAITranscriber" + }, + { + "$ref": "#/components/schemas/AzureSpeechTranscriber", + "title": "AzureSpeechTranscriber" + }, + { + "$ref": "#/components/schemas/CustomTranscriber", + "title": "CustomTranscriber" + }, + { + "$ref": "#/components/schemas/DeepgramTranscriber", + "title": "DeepgramTranscriber" + }, + { + "$ref": "#/components/schemas/ElevenLabsTranscriber", + "title": "ElevenLabsTranscriber" + }, + { + "$ref": "#/components/schemas/GladiaTranscriber", + "title": "GladiaTranscriber" + }, + { + "$ref": "#/components/schemas/GoogleTranscriber", + "title": "GoogleTranscriber" + }, + { + "$ref": "#/components/schemas/SpeechmaticsTranscriber", + "title": "SpeechmaticsTranscriber" + }, + { + "$ref": "#/components/schemas/TalkscriberTranscriber", + "title": "TalkscriberTranscriber" + }, + { + "$ref": "#/components/schemas/OpenAITranscriber", + "title": "OpenAITranscriber" + }, + { + "$ref": "#/components/schemas/CartesiaTranscriber", + "title": "CartesiaTranscriber" + }, + { + "$ref": "#/components/schemas/SonioxTranscriber", + "title": "SonioxTranscriber" + }, + { + "$ref": "#/components/schemas/XaiTranscriber", + "title": "XaiTranscriber" + }, + { + "$ref": "#/components/schemas/VapiTranscriber", + "title": "VapiTranscriber" + } + ] + }, + "model": { + "description": "These are the options for the assistant's LLM.", + "oneOf": [ + { + "$ref": "#/components/schemas/AnthropicModel", + "title": "Anthropic" + }, + { + "$ref": "#/components/schemas/AnthropicBedrockModel", + "title": "AnthropicBedrock" + }, + { + "$ref": "#/components/schemas/AnyscaleModel", + "title": "Anyscale" + }, + { + "$ref": "#/components/schemas/CerebrasModel", + "title": "Cerebras" + }, + { + "$ref": "#/components/schemas/CustomLLMModel", + "title": "CustomLLM" + }, + { + "$ref": "#/components/schemas/DeepInfraModel", + "title": "DeepInfra" + }, + { + "$ref": "#/components/schemas/DeepSeekModel", + "title": "DeepSeek" + }, + { + "$ref": "#/components/schemas/GoogleModel", + "title": "Google" + }, + { + "$ref": "#/components/schemas/GroqModel", + "title": "Groq" + }, + { + "$ref": "#/components/schemas/InflectionAIModel", + "title": "InflectionAI" + }, + { + "$ref": "#/components/schemas/MinimaxLLMModel", + "title": "MiniMaxLLM" + }, + { + "$ref": "#/components/schemas/OpenAIModel", + "title": "OpenAI" + }, + { + "$ref": "#/components/schemas/OpenRouterModel", + "title": "OpenRouter" + }, + { + "$ref": "#/components/schemas/PerplexityAIModel", + "title": "PerplexityAI" + }, + { + "$ref": "#/components/schemas/TogetherAIModel", + "title": "Together" + }, + { + "$ref": "#/components/schemas/XaiModel", + "title": "XAI" + }, + { + "$ref": "#/components/schemas/VapiModel", + "title": "Vapi" + } + ] + }, + "voice": { + "description": "These are the options for the assistant's voice.", + "oneOf": [ + { + "$ref": "#/components/schemas/AzureVoice", + "title": "AzureVoice" + }, + { + "$ref": "#/components/schemas/CartesiaVoice", + "title": "CartesiaVoice" + }, + { + "$ref": "#/components/schemas/CustomVoice", + "title": "CustomVoice" + }, + { + "$ref": "#/components/schemas/DeepgramVoice", + "title": "DeepgramVoice" + }, + { + "$ref": "#/components/schemas/ElevenLabsVoice", + "title": "ElevenLabsVoice" + }, + { + "$ref": "#/components/schemas/HumeVoice", + "title": "HumeVoice" + }, + { + "$ref": "#/components/schemas/LMNTVoice", + "title": "LMNTVoice" + }, + { + "$ref": "#/components/schemas/NeuphonicVoice", + "title": "NeuphonicVoice" + }, + { + "$ref": "#/components/schemas/OpenAIVoice", + "title": "OpenAIVoice" + }, + { + "$ref": "#/components/schemas/PlayHTVoice", + "title": "PlayHTVoice" + }, + { + "$ref": "#/components/schemas/WellSaidVoice", + "title": "WellSaidVoice" + }, + { + "$ref": "#/components/schemas/RimeAIVoice", + "title": "RimeAIVoice" + }, + { + "$ref": "#/components/schemas/SmallestAIVoice", + "title": "SmallestAIVoice" + }, + { + "$ref": "#/components/schemas/TavusVoice", + "title": "TavusVoice" + }, + { + "$ref": "#/components/schemas/VapiVoice", + "title": "VapiVoice" + }, + { + "$ref": "#/components/schemas/SesameVoice", + "title": "SesameVoice" + }, + { + "$ref": "#/components/schemas/InworldVoice", + "title": "InworldVoice" + }, + { + "$ref": "#/components/schemas/MinimaxVoice", + "title": "MinimaxVoice" + }, + { + "$ref": "#/components/schemas/XaiVoice", + "title": "XaiVoice" + }, + { + "$ref": "#/components/schemas/MicrosoftVoice", + "title": "MicrosoftVoice" + } + ] + }, + "firstMessage": { + "type": "string", + "description": "This is the first message that the assistant will say. This can also be a URL to a containerized audio file (mp3, wav, etc.).\n\nIf unspecified, assistant will wait for user to speak and use the model to respond once they speak.", + "example": "Hello! How can I help you today?" + }, + "firstMessageInterruptionsEnabled": { + "type": "boolean", + "default": false + }, + "firstMessageMode": { + "type": "string", + "description": "This is the mode for the first message. Default is 'assistant-speaks-first'.\n\nUse:\n- 'assistant-speaks-first' to have the assistant speak first.\n- 'assistant-waits-for-user' to have the assistant wait for the user to speak first.\n- 'assistant-speaks-first-with-model-generated-message' to have the assistant speak first with a message generated by the model based on the conversation state. (`assistant.model.messages` at call start, `call.messages` at squad transfer points).\n\n@default 'assistant-speaks-first'", + "enum": [ + "assistant-speaks-first", + "assistant-speaks-first-with-model-generated-message", + "assistant-waits-for-user" + ], + "example": "assistant-speaks-first" + }, + "voicemailDetection": { + "description": "These are the settings to configure or disable voicemail detection. Alternatively, voicemail detection can be configured using the model.tools=[VoicemailTool].\nBy default, voicemail detection is disabled.", + "oneOf": [ + { + "type": "string", + "enum": [ + "off" + ] + }, + { + "$ref": "#/components/schemas/GoogleVoicemailDetectionPlan", + "title": "Google" + }, + { + "$ref": "#/components/schemas/OpenAIVoicemailDetectionPlan", + "title": "OpenAI" + }, + { + "$ref": "#/components/schemas/TwilioVoicemailDetectionPlan", + "title": "Twilio" + }, + { + "$ref": "#/components/schemas/VapiVoicemailDetectionPlan", + "title": "Vapi" + } + ] + }, + "clientMessages": { + "type": "array", + "enum": [ + "conversation-update", + "assistant.speechStarted", + "function-call", + "function-call-result", + "hang", + "language-changed", + "metadata", + "model-output", + "speech-update", + "status-update", + "transcript", + "tool-calls", + "tool-calls-result", + "tool.completed", + "transfer-update", + "user-interrupted", + "voice-input", + "workflow.node.started", + "assistant.started" + ], + "example": [ + "conversation-update", + "function-call", + "hang", + "model-output", + "speech-update", + "status-update", + "transfer-update", + "transcript", + "tool-calls", + "user-interrupted", + "voice-input", + "workflow.node.started", + "assistant.started" + ], + "description": "These are the messages that will be sent to your Client SDKs. Default is conversation-update,function-call,hang,model-output,speech-update,status-update,transfer-update,transcript,tool-calls,user-interrupted,voice-input,workflow.node.started,assistant.started. You can check the shape of the messages in ClientMessage schema.", + "items": { + "type": "string", + "enum": [ + "conversation-update", + "assistant.speechStarted", + "function-call", + "function-call-result", + "hang", + "language-changed", + "metadata", + "model-output", + "speech-update", + "status-update", + "transcript", + "tool-calls", + "tool-calls-result", + "tool.completed", + "transfer-update", + "user-interrupted", + "voice-input", + "workflow.node.started", + "assistant.started" + ] + } + }, + "serverMessages": { + "type": "array", + "enum": [ + "assistant.started", + "assistant.speechStarted", + "conversation-update", + "end-of-call-report", + "function-call", + "hang", + "language-changed", + "language-change-detected", + "model-output", + "phone-call-control", + "speech-update", + "status-update", + "transcript", + "transcript[transcriptType=\"final\"]", + "tool-calls", + "transfer-destination-request", + "handoff-destination-request", + "transfer-update", + "user-interrupted", + "voice-input", + "chat.created", + "chat.deleted", + "session.created", + "session.updated", + "session.deleted", + "call.deleted", + "call.delete.failed", + "call.artifact.upload" + ], + "example": [ + "conversation-update", + "end-of-call-report", + "function-call", + "hang", + "speech-update", + "status-update", + "tool-calls", + "transfer-destination-request", + "handoff-destination-request", + "user-interrupted", + "assistant.started" + ], + "description": "These are the messages that will be sent to your Server URL. Default is conversation-update,end-of-call-report,function-call,hang,speech-update,status-update,tool-calls,transfer-destination-request,handoff-destination-request,user-interrupted,assistant.started. You can check the shape of the messages in ServerMessage schema.", + "items": { + "type": "string", + "enum": [ + "assistant.started", + "assistant.speechStarted", + "conversation-update", + "end-of-call-report", + "function-call", + "hang", + "language-changed", + "language-change-detected", + "model-output", + "phone-call-control", + "speech-update", + "status-update", + "transcript", + "transcript[transcriptType=\"final\"]", + "tool-calls", + "transfer-destination-request", + "handoff-destination-request", + "transfer-update", + "user-interrupted", + "voice-input", + "chat.created", + "chat.deleted", + "session.created", + "session.updated", + "session.deleted", + "call.deleted", + "call.delete.failed", + "call.artifact.upload" + ] + } + }, + "maxDurationSeconds": { + "type": "number", + "description": "This is the maximum number of seconds that the call will last. When the call reaches this duration, it will be ended.\n\n@default 600 (10 minutes)", + "minimum": 10, + "maximum": 43200, + "example": 600 + }, + "backgroundSound": { + "description": "This is the background sound in the call. Default for phone calls is 'office' and default for web calls is 'off'.\nYou can also provide a custom sound by providing a URL to an audio file.", + "oneOf": [ + { + "type": "string", + "enum": [ + "off", + "office" + ], + "example": "office" + }, + { + "type": "string", + "format": "uri", + "example": "https://www.soundjay.com/ambient/sounds/people-in-lounge-1.mp3" + } + ] + }, + "modelOutputInMessagesEnabled": { + "type": "boolean", + "description": "This determines whether the model's output is used in conversation history rather than the transcription of assistant's speech.\n\n@default false", + "example": false + }, + "transportConfigurations": { + "type": "array", + "description": "These are the configurations to be passed to the transport providers of assistant's calls, like Twilio. You can store multiple configurations for different transport providers. For a call, only the configuration matching the call transport provider is used.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/TransportConfigurationTwilio", + "title": "Twilio" + } + ] + } + }, + "observabilityPlan": { + "description": "This is the plan for observability of assistant's calls.\n\nCurrently, only Langfuse is supported.", + "oneOf": [ + { + "$ref": "#/components/schemas/LangfuseObservabilityPlan", + "title": "Langfuse" + } + ], + "allOf": [ + { + "$ref": "#/components/schemas/LangfuseObservabilityPlan" + } + ] + }, + "credentials": { + "type": "array", + "description": "These are dynamic credentials that will be used for the assistant calls. By default, all the credentials are available for use in the call but you can supplement an additional credentials using this. Dynamic credentials override existing credentials.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/CreateAnthropicCredentialDTO", + "title": "AnthropicCredential" + }, + { + "$ref": "#/components/schemas/CreateAnthropicBedrockCredentialDTO", + "title": "AnthropicBedrockCredential" + }, + { + "$ref": "#/components/schemas/CreateAnyscaleCredentialDTO", + "title": "AnyscaleCredential" + }, + { + "$ref": "#/components/schemas/CreateAssemblyAICredentialDTO", + "title": "AssemblyAICredential" + }, + { + "$ref": "#/components/schemas/CreateAzureCredentialDTO", + "title": "AzureCredential" + }, + { + "$ref": "#/components/schemas/CreateAzureOpenAICredentialDTO", + "title": "AzureOpenAICredential" + }, + { + "$ref": "#/components/schemas/CreateByoSipTrunkCredentialDTO", + "title": "ByoSipTrunkCredential" + }, + { + "$ref": "#/components/schemas/CreateCartesiaCredentialDTO", + "title": "CartesiaCredential" + }, + { + "$ref": "#/components/schemas/CreateCerebrasCredentialDTO", + "title": "CerebrasCredential" + }, + { + "$ref": "#/components/schemas/CreateCloudflareCredentialDTO", + "title": "CloudflareCredential" + }, + { + "$ref": "#/components/schemas/CreateCustomLLMCredentialDTO", + "title": "CustomLLMCredential" + }, + { + "$ref": "#/components/schemas/CreateDeepgramCredentialDTO", + "title": "DeepgramCredential" + }, + { + "$ref": "#/components/schemas/CreateDeepInfraCredentialDTO", + "title": "DeepInfraCredential" + }, + { + "$ref": "#/components/schemas/CreateDeepSeekCredentialDTO", + "title": "DeepSeekCredential" + }, + { + "$ref": "#/components/schemas/CreateElevenLabsCredentialDTO", + "title": "ElevenLabsCredential" + }, + { + "$ref": "#/components/schemas/CreateGcpCredentialDTO", + "title": "GcpCredential" + }, + { + "$ref": "#/components/schemas/CreateGladiaCredentialDTO", + "title": "GladiaCredential" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelCredentialDTO", + "title": "GhlCredential" + }, + { + "$ref": "#/components/schemas/CreateGoogleCredentialDTO", + "title": "GoogleCredential" + }, + { + "$ref": "#/components/schemas/CreateGroqCredentialDTO", + "title": "GroqCredential" + }, + { + "$ref": "#/components/schemas/CreateHumeCredentialDTO", + "title": "HumeCredential" + }, + { + "$ref": "#/components/schemas/CreateInflectionAICredentialDTO", + "title": "InflectionAICredential" + }, + { + "$ref": "#/components/schemas/CreateLangfuseCredentialDTO", + "title": "LangfuseCredential" + }, + { + "$ref": "#/components/schemas/CreateLmntCredentialDTO", + "title": "LmntCredential" + }, + { + "$ref": "#/components/schemas/CreateMakeCredentialDTO", + "title": "MakeCredential" + }, + { + "$ref": "#/components/schemas/CreateMistralCredentialDTO", + "title": "MistralCredential" + }, + { + "$ref": "#/components/schemas/CreateNeuphonicCredentialDTO", + "title": "NeuphonicCredential" + }, + { + "$ref": "#/components/schemas/CreateOpenAICredentialDTO", + "title": "OpenAICredential" + }, + { + "$ref": "#/components/schemas/CreateOpenRouterCredentialDTO", + "title": "OpenRouterCredential" + }, + { + "$ref": "#/components/schemas/CreatePerplexityAICredentialDTO", + "title": "PerplexityAICredential" + }, + { + "$ref": "#/components/schemas/CreatePlayHTCredentialDTO", + "title": "PlayHTCredential" + }, + { + "$ref": "#/components/schemas/CreateRimeAICredentialDTO", + "title": "RimeAICredential" + }, + { + "$ref": "#/components/schemas/CreateRunpodCredentialDTO", + "title": "RunpodCredential" + }, + { + "$ref": "#/components/schemas/CreateS3CredentialDTO", + "title": "S3Credential" + }, + { + "$ref": "#/components/schemas/CreateS3CompatibleCredentialDTO", + "title": "S3CompatibleStorageCredential" + }, + { + "$ref": "#/components/schemas/CreateSmallestAICredentialDTO", + "title": "SmallestAICredential" + }, + { + "$ref": "#/components/schemas/CreateSpeechmaticsCredentialDTO", + "title": "SpeechmaticsCredential" + }, + { + "$ref": "#/components/schemas/CreateSonioxCredentialDTO", + "title": "SonioxCredential" + }, + { + "$ref": "#/components/schemas/CreateSupabaseCredentialDTO", + "title": "SupabaseCredential" + }, + { + "$ref": "#/components/schemas/CreateTavusCredentialDTO", + "title": "TavusCredential" + }, + { + "$ref": "#/components/schemas/CreateTogetherAICredentialDTO", + "title": "TogetherAICredential" + }, + { + "$ref": "#/components/schemas/CreateTwilioCredentialDTO", + "title": "TwilioCredential" + }, + { + "$ref": "#/components/schemas/CreateVonageCredentialDTO", + "title": "VonageCredential" + }, + { + "$ref": "#/components/schemas/CreateWebhookCredentialDTO", + "title": "WebhookCredential" + }, + { + "$ref": "#/components/schemas/CreateCustomCredentialDTO", + "title": "CustomCredential" + }, + { + "$ref": "#/components/schemas/CreateXAiCredentialDTO", + "title": "XAiCredential" + }, + { + "$ref": "#/components/schemas/CreateMicrosoftCredentialDTO", + "title": "MicrosoftCredential" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarOAuth2ClientCredentialDTO", + "title": "GoogleCalendarOAuth2ClientCredential" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarOAuth2AuthorizationCredentialDTO", + "title": "GoogleCalendarOAuth2AuthorizationCredential" + }, + { + "$ref": "#/components/schemas/CreateGoogleSheetsOAuth2AuthorizationCredentialDTO", + "title": "GoogleSheetsOAuth2AuthorizationCredential" + }, + { + "$ref": "#/components/schemas/CreateSlackOAuth2AuthorizationCredentialDTO", + "title": "SlackOAuth2AuthorizationCredential" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelMCPCredentialDTO", + "title": "GoHighLevelMCPCredential" + }, + { + "$ref": "#/components/schemas/CreateInworldCredentialDTO", + "title": "InworldCredential" + }, + { + "$ref": "#/components/schemas/CreateMinimaxCredentialDTO", + "title": "MinimaxCredential" + }, + { + "$ref": "#/components/schemas/CreateWellSaidCredentialDTO", + "title": "WellSaidCredential" + }, + { + "$ref": "#/components/schemas/CreateEmailCredentialDTO", + "title": "EmailCredential" + }, + { + "$ref": "#/components/schemas/CreateSlackWebhookCredentialDTO", + "title": "SlackWebhookCredential" + } + ], + "discriminator": { + "propertyName": "provider", + "mapping": { + "11labs": "#/components/schemas/CreateElevenLabsCredentialDTO", + "anthropic": "#/components/schemas/CreateAnthropicCredentialDTO", + "anthropic-bedrock": "#/components/schemas/CreateAnthropicBedrockCredentialDTO", + "anyscale": "#/components/schemas/CreateAnyscaleCredentialDTO", + "assembly-ai": "#/components/schemas/CreateAssemblyAICredentialDTO", + "azure-openai": "#/components/schemas/CreateAzureOpenAICredentialDTO", + "azure": "#/components/schemas/CreateAzureCredentialDTO", + "byo-sip-trunk": "#/components/schemas/CreateByoSipTrunkCredentialDTO", + "cartesia": "#/components/schemas/CreateCartesiaCredentialDTO", + "cerebras": "#/components/schemas/CreateCerebrasCredentialDTO", + "cloudflare": "#/components/schemas/CreateCloudflareCredentialDTO", + "custom-llm": "#/components/schemas/CreateCustomLLMCredentialDTO", + "deepgram": "#/components/schemas/CreateDeepgramCredentialDTO", + "deepinfra": "#/components/schemas/CreateDeepInfraCredentialDTO", + "deep-seek": "#/components/schemas/CreateDeepSeekCredentialDTO", + "gcp": "#/components/schemas/CreateGcpCredentialDTO", + "gladia": "#/components/schemas/CreateGladiaCredentialDTO", + "gohighlevel": "#/components/schemas/CreateGoHighLevelCredentialDTO", + "google": "#/components/schemas/CreateGoogleCredentialDTO", + "groq": "#/components/schemas/CreateGroqCredentialDTO", + "inflection-ai": "#/components/schemas/CreateInflectionAICredentialDTO", + "langfuse": "#/components/schemas/CreateLangfuseCredentialDTO", + "lmnt": "#/components/schemas/CreateLmntCredentialDTO", + "make": "#/components/schemas/CreateMakeCredentialDTO", + "openai": "#/components/schemas/CreateOpenAICredentialDTO", + "openrouter": "#/components/schemas/CreateOpenRouterCredentialDTO", + "perplexity-ai": "#/components/schemas/CreatePerplexityAICredentialDTO", + "playht": "#/components/schemas/CreatePlayHTCredentialDTO", + "rime-ai": "#/components/schemas/CreateRimeAICredentialDTO", + "runpod": "#/components/schemas/CreateRunpodCredentialDTO", + "s3": "#/components/schemas/CreateS3CredentialDTO", + "s3-compatible": "#/components/schemas/CreateS3CompatibleCredentialDTO", + "supabase": "#/components/schemas/CreateSupabaseCredentialDTO", + "smallest-ai": "#/components/schemas/CreateSmallestAICredentialDTO", + "tavus": "#/components/schemas/CreateTavusCredentialDTO", + "together-ai": "#/components/schemas/CreateTogetherAICredentialDTO", + "twilio": "#/components/schemas/CreateTwilioCredentialDTO", + "vonage": "#/components/schemas/CreateVonageCredentialDTO", + "webhook": "#/components/schemas/CreateWebhookCredentialDTO", + "custom-credential": "#/components/schemas/CreateCustomCredentialDTO", + "xai": "#/components/schemas/CreateXAiCredentialDTO", + "microsoft": "#/components/schemas/CreateMicrosoftCredentialDTO", + "neuphonic": "#/components/schemas/CreateNeuphonicCredentialDTO", + "hume": "#/components/schemas/CreateHumeCredentialDTO", + "mistral": "#/components/schemas/CreateMistralCredentialDTO", + "speechmatics": "#/components/schemas/CreateSpeechmaticsCredentialDTO", + "soniox": "#/components/schemas/CreateSonioxCredentialDTO", + "google.calendar.oauth2-client": "#/components/schemas/CreateGoogleCalendarOAuth2ClientCredentialDTO", + "google.calendar.oauth2-authorization": "#/components/schemas/CreateGoogleCalendarOAuth2AuthorizationCredentialDTO", + "google.sheets.oauth2-authorization": "#/components/schemas/CreateGoogleSheetsOAuth2AuthorizationCredentialDTO", + "slack.oauth2-authorization": "#/components/schemas/CreateSlackOAuth2AuthorizationCredentialDTO", + "ghl.oauth2-authorization": "#/components/schemas/CreateGoHighLevelMCPCredentialDTO", + "inworld": "#/components/schemas/CreateInworldCredentialDTO", + "minimax": "#/components/schemas/CreateMinimaxCredentialDTO", + "wellsaid": "#/components/schemas/CreateWellSaidCredentialDTO", + "email": "#/components/schemas/CreateEmailCredentialDTO", + "slack-webhook": "#/components/schemas/CreateSlackWebhookCredentialDTO" + } + } + } + }, + "hooks": { + "type": "array", + "description": "This is a set of actions that will be performed on certain events.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/CallHookCallEnding", + "title": "CallHookCallEnding" + }, + { + "$ref": "#/components/schemas/CallHookAssistantSpeechInterrupted", + "title": "CallHookAssistantSpeechInterrupted" + }, + { + "$ref": "#/components/schemas/CallHookCustomerSpeechInterrupted", + "title": "CallHookCustomerSpeechInterrupted" + }, + { + "$ref": "#/components/schemas/CallHookCustomerSpeechTimeout", + "title": "CallHookCustomerSpeechTimeout" + }, + { + "$ref": "#/components/schemas/SessionCreatedHook", + "title": "SessionCreatedHook" + } + ] + } + }, + "name": { + "type": "string", + "description": "This is the name of the assistant.\n\nThis is required when you want to transfer between assistants in a call.", + "maxLength": 40 + }, + "voicemailMessage": { + "type": "string", + "description": "This is the message that the assistant will say if the call is forwarded to voicemail.\n\nIf unspecified, it will hang up.", + "maxLength": 1000 + }, + "endCallMessage": { + "type": "string", + "description": "This is the message that the assistant will say if it ends the call.\n\nIf unspecified, it will hang up without saying anything.", + "maxLength": 1000 + }, + "endCallPhrases": { + "description": "This list contains phrases that, if spoken by the assistant, will trigger the call to be hung up. Case insensitive.", + "type": "array", + "items": { + "type": "string", + "maxLength": 140, + "minLength": 2 + } + }, + "compliancePlan": { + "$ref": "#/components/schemas/CompliancePlan" + }, + "metadata": { + "type": "object", + "description": "This is for metadata you want to store on the assistant." + }, + "backgroundSpeechDenoisingPlan": { + "description": "This enables filtering of noise and background speech while the user is talking.\n\nFeatures:\n- Smart denoising using Krisp\n- Fourier denoising\n\nSmart denoising can be combined with or used independently of Fourier denoising.\n\nOrder of precedence:\n- Smart denoising\n- Fourier denoising", + "allOf": [ + { + "$ref": "#/components/schemas/BackgroundSpeechDenoisingPlan" + } + ] + }, + "analysisPlan": { + "description": "This is the plan for analysis of assistant's calls. Stored in `call.analysis`.", + "deprecated": true, + "allOf": [ + { + "$ref": "#/components/schemas/AnalysisPlan" + } + ] + }, + "artifactPlan": { + "description": "This is the plan for artifacts generated during assistant's calls. Stored in `call.artifact`.", + "allOf": [ + { + "$ref": "#/components/schemas/ArtifactPlan" + } + ] + }, + "startSpeakingPlan": { + "description": "This is the plan for when the assistant should start talking.\n\nYou should configure this if you're running into these issues:\n- The assistant is too slow to start talking after the customer is done speaking.\n- The assistant is too fast to start talking after the customer is done speaking.\n- The assistant is so fast that it's actually interrupting the customer.", + "allOf": [ + { + "$ref": "#/components/schemas/StartSpeakingPlan" + } + ] + }, + "stopSpeakingPlan": { + "description": "This is the plan for when assistant should stop talking on customer interruption.\n\nYou should configure this if you're running into these issues:\n- The assistant is too slow to recognize customer's interruption.\n- The assistant is too fast to recognize customer's interruption.\n- The assistant is getting interrupted by phrases that are just acknowledgments.\n- The assistant is getting interrupted by background noises.\n- The assistant is not properly stopping -- it starts talking right after getting interrupted.", + "allOf": [ + { + "$ref": "#/components/schemas/StopSpeakingPlan" + } + ] + }, + "monitorPlan": { + "description": "This is the plan for real-time monitoring of the assistant's calls.\n\nUsage:\n- To enable live listening of the assistant's calls, set `monitorPlan.listenEnabled` to `true`.\n- To enable live control of the assistant's calls, set `monitorPlan.controlEnabled` to `true`.\n- To attach monitors to the assistant, set `monitorPlan.monitorIds` to the set of monitor ids.", + "allOf": [ + { + "$ref": "#/components/schemas/MonitorPlan" + } + ] + }, + "credentialIds": { + "description": "These are the credentials that will be used for the assistant calls. By default, all the credentials are available for use in the call but you can provide a subset using this.", + "type": "array", + "items": { + "type": "string" + } + }, + "server": { + "description": "This is where Vapi will send webhooks. You can find all webhooks available along with their shape in ServerMessage schema.\n\nThe order of precedence is:\n\n1. assistant.server.url\n2. phoneNumber.serverUrl\n3. org.serverUrl", + "allOf": [ + { + "$ref": "#/components/schemas/Server" + } + ] + }, + "keypadInputPlan": { + "$ref": "#/components/schemas/KeypadInputPlan" + }, + "baseVersion": { + "type": "string", + "description": "Server-resolved baseVersion (always set after POST)." + }, + "id": { + "type": "string", + "description": "Surrogate key used as `draftId` in URLs." + }, + "orgId": { + "type": "string", + "description": "Org this draft belongs to." + }, + "assistantId": { + "type": "string", + "description": "Parent assistant the draft was forked from. FK to assistant.id ON DELETE CASCADE." + }, + "createdBy": { + "type": "string", + "nullable": true, + "description": "Email when JWT, null when API or external JWT. Set on POST, never rewritten on PATCH." + }, + "createdAt": { + "format": "date-time", + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + } + }, + "required": [ + "baseVersion", + "id", + "orgId", + "assistantId", + "createdAt", + "updatedAt" + ] + }, + "AssistantDraftPaginatedMetadata": { + "type": "object", + "properties": { + "nextCursor": { + "type": "string", + "nullable": true + }, + "hasNextPage": { + "type": "boolean" + }, + "limit": { + "type": "number" + } + }, + "required": [ + "nextCursor", + "hasNextPage", + "limit" + ] + }, + "AssistantDraftPaginatedResponse": { + "type": "object", + "properties": { + "results": { + "type": "array", + "items": { + "$ref": "#/components/schemas/AssistantDraft" + } + }, + "metadata": { + "$ref": "#/components/schemas/AssistantDraftPaginatedMetadata" + } + }, + "required": [ + "results", + "metadata" + ] + }, + "LegacyAssistantVersion": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "assistantId": { + "type": "string" + }, + "orgId": { + "type": "string" + }, + "data": { + "type": "string" + }, + "createdAt": { + "format": "date-time", + "type": "string" + } + }, + "required": [ + "id", + "assistantId", + "orgId", + "createdAt" + ] + }, + "LegacyAssistantVersionPaginatedResponse": { + "type": "object", + "properties": { + "results": { + "type": "array", + "items": { + "$ref": "#/components/schemas/LegacyAssistantVersion" + } + }, + "metadata": { + "$ref": "#/components/schemas/PaginationMeta" + }, + "nextPageState": { + "type": "string" + } + }, + "required": [ + "results", + "metadata" + ] + }, + "AssistantVersion": { + "type": "object", + "properties": { + "transcriber": { + "description": "These are the options for the assistant's transcriber.", + "oneOf": [ + { + "$ref": "#/components/schemas/AssemblyAITranscriber", + "title": "AssemblyAITranscriber" + }, + { + "$ref": "#/components/schemas/AzureSpeechTranscriber", + "title": "AzureSpeechTranscriber" + }, + { + "$ref": "#/components/schemas/CustomTranscriber", + "title": "CustomTranscriber" + }, + { + "$ref": "#/components/schemas/DeepgramTranscriber", + "title": "DeepgramTranscriber" + }, + { + "$ref": "#/components/schemas/ElevenLabsTranscriber", + "title": "ElevenLabsTranscriber" + }, + { + "$ref": "#/components/schemas/GladiaTranscriber", + "title": "GladiaTranscriber" + }, + { + "$ref": "#/components/schemas/GoogleTranscriber", + "title": "GoogleTranscriber" + }, + { + "$ref": "#/components/schemas/SpeechmaticsTranscriber", + "title": "SpeechmaticsTranscriber" + }, + { + "$ref": "#/components/schemas/TalkscriberTranscriber", + "title": "TalkscriberTranscriber" + }, + { + "$ref": "#/components/schemas/OpenAITranscriber", + "title": "OpenAITranscriber" + }, + { + "$ref": "#/components/schemas/CartesiaTranscriber", + "title": "CartesiaTranscriber" + }, + { + "$ref": "#/components/schemas/SonioxTranscriber", + "title": "SonioxTranscriber" + }, + { + "$ref": "#/components/schemas/XaiTranscriber", + "title": "XaiTranscriber" + }, + { + "$ref": "#/components/schemas/VapiTranscriber", + "title": "VapiTranscriber" + } + ] + }, + "model": { + "description": "These are the options for the assistant's LLM.", + "oneOf": [ + { + "$ref": "#/components/schemas/AnthropicModel", + "title": "Anthropic" + }, + { + "$ref": "#/components/schemas/AnthropicBedrockModel", + "title": "AnthropicBedrock" + }, + { + "$ref": "#/components/schemas/AnyscaleModel", + "title": "Anyscale" + }, + { + "$ref": "#/components/schemas/CerebrasModel", + "title": "Cerebras" + }, + { + "$ref": "#/components/schemas/CustomLLMModel", + "title": "CustomLLM" + }, + { + "$ref": "#/components/schemas/DeepInfraModel", + "title": "DeepInfra" + }, + { + "$ref": "#/components/schemas/DeepSeekModel", + "title": "DeepSeek" + }, + { + "$ref": "#/components/schemas/GoogleModel", + "title": "Google" + }, + { + "$ref": "#/components/schemas/GroqModel", + "title": "Groq" + }, + { + "$ref": "#/components/schemas/InflectionAIModel", + "title": "InflectionAI" + }, + { + "$ref": "#/components/schemas/MinimaxLLMModel", + "title": "MiniMaxLLM" + }, + { + "$ref": "#/components/schemas/OpenAIModel", + "title": "OpenAI" + }, + { + "$ref": "#/components/schemas/OpenRouterModel", + "title": "OpenRouter" + }, + { + "$ref": "#/components/schemas/PerplexityAIModel", + "title": "PerplexityAI" + }, + { + "$ref": "#/components/schemas/TogetherAIModel", + "title": "Together" + }, + { + "$ref": "#/components/schemas/XaiModel", + "title": "XAI" + }, + { + "$ref": "#/components/schemas/VapiModel", + "title": "Vapi" + } + ] + }, + "voice": { + "description": "These are the options for the assistant's voice.", + "oneOf": [ + { + "$ref": "#/components/schemas/AzureVoice", + "title": "AzureVoice" + }, + { + "$ref": "#/components/schemas/CartesiaVoice", + "title": "CartesiaVoice" + }, + { + "$ref": "#/components/schemas/CustomVoice", + "title": "CustomVoice" + }, + { + "$ref": "#/components/schemas/DeepgramVoice", + "title": "DeepgramVoice" + }, + { + "$ref": "#/components/schemas/ElevenLabsVoice", + "title": "ElevenLabsVoice" + }, + { + "$ref": "#/components/schemas/HumeVoice", + "title": "HumeVoice" + }, + { + "$ref": "#/components/schemas/LMNTVoice", + "title": "LMNTVoice" + }, + { + "$ref": "#/components/schemas/NeuphonicVoice", + "title": "NeuphonicVoice" + }, + { + "$ref": "#/components/schemas/OpenAIVoice", + "title": "OpenAIVoice" + }, + { + "$ref": "#/components/schemas/PlayHTVoice", + "title": "PlayHTVoice" + }, + { + "$ref": "#/components/schemas/WellSaidVoice", + "title": "WellSaidVoice" + }, + { + "$ref": "#/components/schemas/RimeAIVoice", + "title": "RimeAIVoice" + }, + { + "$ref": "#/components/schemas/SmallestAIVoice", + "title": "SmallestAIVoice" + }, + { + "$ref": "#/components/schemas/TavusVoice", + "title": "TavusVoice" + }, + { + "$ref": "#/components/schemas/VapiVoice", + "title": "VapiVoice" + }, + { + "$ref": "#/components/schemas/SesameVoice", + "title": "SesameVoice" + }, + { + "$ref": "#/components/schemas/InworldVoice", + "title": "InworldVoice" + }, + { + "$ref": "#/components/schemas/MinimaxVoice", + "title": "MinimaxVoice" + }, + { + "$ref": "#/components/schemas/XaiVoice", + "title": "XaiVoice" + }, + { + "$ref": "#/components/schemas/MicrosoftVoice", + "title": "MicrosoftVoice" + } + ] + }, + "firstMessage": { + "type": "string", + "description": "This is the first message that the assistant will say. This can also be a URL to a containerized audio file (mp3, wav, etc.).\n\nIf unspecified, assistant will wait for user to speak and use the model to respond once they speak.", + "example": "Hello! How can I help you today?" + }, + "firstMessageInterruptionsEnabled": { + "type": "boolean", + "default": false + }, + "firstMessageMode": { + "type": "string", + "description": "This is the mode for the first message. Default is 'assistant-speaks-first'.\n\nUse:\n- 'assistant-speaks-first' to have the assistant speak first.\n- 'assistant-waits-for-user' to have the assistant wait for the user to speak first.\n- 'assistant-speaks-first-with-model-generated-message' to have the assistant speak first with a message generated by the model based on the conversation state. (`assistant.model.messages` at call start, `call.messages` at squad transfer points).\n\n@default 'assistant-speaks-first'", + "enum": [ + "assistant-speaks-first", + "assistant-speaks-first-with-model-generated-message", + "assistant-waits-for-user" + ], + "example": "assistant-speaks-first" + }, + "voicemailDetection": { + "description": "These are the settings to configure or disable voicemail detection. Alternatively, voicemail detection can be configured using the model.tools=[VoicemailTool].\nBy default, voicemail detection is disabled.", + "oneOf": [ + { + "type": "string", + "enum": [ + "off" + ] + }, + { + "$ref": "#/components/schemas/GoogleVoicemailDetectionPlan", + "title": "Google" + }, + { + "$ref": "#/components/schemas/OpenAIVoicemailDetectionPlan", + "title": "OpenAI" + }, + { + "$ref": "#/components/schemas/TwilioVoicemailDetectionPlan", + "title": "Twilio" + }, + { + "$ref": "#/components/schemas/VapiVoicemailDetectionPlan", + "title": "Vapi" + } + ] + }, + "clientMessages": { + "type": "array", + "enum": [ + "conversation-update", + "assistant.speechStarted", + "function-call", + "function-call-result", + "hang", + "language-changed", + "metadata", + "model-output", + "speech-update", + "status-update", + "transcript", + "tool-calls", + "tool-calls-result", + "tool.completed", + "transfer-update", + "user-interrupted", + "voice-input", + "workflow.node.started", + "assistant.started" + ], + "example": [ + "conversation-update", + "function-call", + "hang", + "model-output", + "speech-update", + "status-update", + "transfer-update", + "transcript", + "tool-calls", + "user-interrupted", + "voice-input", + "workflow.node.started", + "assistant.started" + ], + "description": "These are the messages that will be sent to your Client SDKs. Default is conversation-update,function-call,hang,model-output,speech-update,status-update,transfer-update,transcript,tool-calls,user-interrupted,voice-input,workflow.node.started,assistant.started. You can check the shape of the messages in ClientMessage schema.", + "items": { + "type": "string", + "enum": [ + "conversation-update", + "assistant.speechStarted", + "function-call", + "function-call-result", + "hang", + "language-changed", + "metadata", + "model-output", + "speech-update", + "status-update", + "transcript", + "tool-calls", + "tool-calls-result", + "tool.completed", + "transfer-update", + "user-interrupted", + "voice-input", + "workflow.node.started", + "assistant.started" + ] + } + }, + "serverMessages": { + "type": "array", + "enum": [ + "assistant.started", + "assistant.speechStarted", + "conversation-update", + "end-of-call-report", + "function-call", + "hang", + "language-changed", + "language-change-detected", + "model-output", + "phone-call-control", + "speech-update", + "status-update", + "transcript", + "transcript[transcriptType=\"final\"]", + "tool-calls", + "transfer-destination-request", + "handoff-destination-request", + "transfer-update", + "user-interrupted", + "voice-input", + "chat.created", + "chat.deleted", + "session.created", + "session.updated", + "session.deleted", + "call.deleted", + "call.delete.failed", + "call.artifact.upload" + ], + "example": [ + "conversation-update", + "end-of-call-report", + "function-call", + "hang", + "speech-update", + "status-update", + "tool-calls", + "transfer-destination-request", + "handoff-destination-request", + "user-interrupted", + "assistant.started" + ], + "description": "These are the messages that will be sent to your Server URL. Default is conversation-update,end-of-call-report,function-call,hang,speech-update,status-update,tool-calls,transfer-destination-request,handoff-destination-request,user-interrupted,assistant.started. You can check the shape of the messages in ServerMessage schema.", + "items": { + "type": "string", + "enum": [ + "assistant.started", + "assistant.speechStarted", + "conversation-update", + "end-of-call-report", + "function-call", + "hang", + "language-changed", + "language-change-detected", + "model-output", + "phone-call-control", + "speech-update", + "status-update", + "transcript", + "transcript[transcriptType=\"final\"]", + "tool-calls", + "transfer-destination-request", + "handoff-destination-request", + "transfer-update", + "user-interrupted", + "voice-input", + "chat.created", + "chat.deleted", + "session.created", + "session.updated", + "session.deleted", + "call.deleted", + "call.delete.failed", + "call.artifact.upload" + ] + } + }, + "maxDurationSeconds": { + "type": "number", + "description": "This is the maximum number of seconds that the call will last. When the call reaches this duration, it will be ended.\n\n@default 600 (10 minutes)", + "minimum": 10, + "maximum": 43200, + "example": 600 + }, + "backgroundSound": { + "description": "This is the background sound in the call. Default for phone calls is 'office' and default for web calls is 'off'.\nYou can also provide a custom sound by providing a URL to an audio file.", + "oneOf": [ + { + "type": "string", + "enum": [ + "off", + "office" + ], + "example": "office" + }, + { + "type": "string", + "format": "uri", + "example": "https://www.soundjay.com/ambient/sounds/people-in-lounge-1.mp3" + } + ] + }, + "modelOutputInMessagesEnabled": { + "type": "boolean", + "description": "This determines whether the model's output is used in conversation history rather than the transcription of assistant's speech.\n\n@default false", + "example": false + }, + "transportConfigurations": { + "type": "array", + "description": "These are the configurations to be passed to the transport providers of assistant's calls, like Twilio. You can store multiple configurations for different transport providers. For a call, only the configuration matching the call transport provider is used.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/TransportConfigurationTwilio", + "title": "Twilio" + } + ] + } + }, + "observabilityPlan": { + "description": "This is the plan for observability of assistant's calls.\n\nCurrently, only Langfuse is supported.", + "oneOf": [ + { + "$ref": "#/components/schemas/LangfuseObservabilityPlan", + "title": "Langfuse" + } + ], + "allOf": [ + { + "$ref": "#/components/schemas/LangfuseObservabilityPlan" + } + ] + }, + "credentials": { + "type": "array", + "description": "These are dynamic credentials that will be used for the assistant calls. By default, all the credentials are available for use in the call but you can supplement an additional credentials using this. Dynamic credentials override existing credentials.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/CreateAnthropicCredentialDTO", + "title": "AnthropicCredential" + }, + { + "$ref": "#/components/schemas/CreateAnthropicBedrockCredentialDTO", + "title": "AnthropicBedrockCredential" + }, + { + "$ref": "#/components/schemas/CreateAnyscaleCredentialDTO", + "title": "AnyscaleCredential" + }, + { + "$ref": "#/components/schemas/CreateAssemblyAICredentialDTO", + "title": "AssemblyAICredential" + }, + { + "$ref": "#/components/schemas/CreateAzureCredentialDTO", + "title": "AzureCredential" + }, + { + "$ref": "#/components/schemas/CreateAzureOpenAICredentialDTO", + "title": "AzureOpenAICredential" + }, + { + "$ref": "#/components/schemas/CreateByoSipTrunkCredentialDTO", + "title": "ByoSipTrunkCredential" + }, + { + "$ref": "#/components/schemas/CreateCartesiaCredentialDTO", + "title": "CartesiaCredential" + }, + { + "$ref": "#/components/schemas/CreateCerebrasCredentialDTO", + "title": "CerebrasCredential" + }, + { + "$ref": "#/components/schemas/CreateCloudflareCredentialDTO", + "title": "CloudflareCredential" + }, + { + "$ref": "#/components/schemas/CreateCustomLLMCredentialDTO", + "title": "CustomLLMCredential" + }, + { + "$ref": "#/components/schemas/CreateDeepgramCredentialDTO", + "title": "DeepgramCredential" + }, + { + "$ref": "#/components/schemas/CreateDeepInfraCredentialDTO", + "title": "DeepInfraCredential" + }, + { + "$ref": "#/components/schemas/CreateDeepSeekCredentialDTO", + "title": "DeepSeekCredential" + }, + { + "$ref": "#/components/schemas/CreateElevenLabsCredentialDTO", + "title": "ElevenLabsCredential" + }, + { + "$ref": "#/components/schemas/CreateGcpCredentialDTO", + "title": "GcpCredential" + }, + { + "$ref": "#/components/schemas/CreateGladiaCredentialDTO", + "title": "GladiaCredential" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelCredentialDTO", + "title": "GhlCredential" + }, + { + "$ref": "#/components/schemas/CreateGoogleCredentialDTO", + "title": "GoogleCredential" + }, + { + "$ref": "#/components/schemas/CreateGroqCredentialDTO", + "title": "GroqCredential" + }, + { + "$ref": "#/components/schemas/CreateHumeCredentialDTO", + "title": "HumeCredential" + }, + { + "$ref": "#/components/schemas/CreateInflectionAICredentialDTO", + "title": "InflectionAICredential" + }, + { + "$ref": "#/components/schemas/CreateLangfuseCredentialDTO", + "title": "LangfuseCredential" + }, + { + "$ref": "#/components/schemas/CreateLmntCredentialDTO", + "title": "LmntCredential" + }, + { + "$ref": "#/components/schemas/CreateMakeCredentialDTO", + "title": "MakeCredential" + }, + { + "$ref": "#/components/schemas/CreateMistralCredentialDTO", + "title": "MistralCredential" + }, + { + "$ref": "#/components/schemas/CreateNeuphonicCredentialDTO", + "title": "NeuphonicCredential" + }, + { + "$ref": "#/components/schemas/CreateOpenAICredentialDTO", + "title": "OpenAICredential" + }, + { + "$ref": "#/components/schemas/CreateOpenRouterCredentialDTO", + "title": "OpenRouterCredential" + }, + { + "$ref": "#/components/schemas/CreatePerplexityAICredentialDTO", + "title": "PerplexityAICredential" + }, + { + "$ref": "#/components/schemas/CreatePlayHTCredentialDTO", + "title": "PlayHTCredential" + }, + { + "$ref": "#/components/schemas/CreateRimeAICredentialDTO", + "title": "RimeAICredential" + }, + { + "$ref": "#/components/schemas/CreateRunpodCredentialDTO", + "title": "RunpodCredential" + }, + { + "$ref": "#/components/schemas/CreateS3CredentialDTO", + "title": "S3Credential" + }, + { + "$ref": "#/components/schemas/CreateS3CompatibleCredentialDTO", + "title": "S3CompatibleStorageCredential" + }, + { + "$ref": "#/components/schemas/CreateSmallestAICredentialDTO", + "title": "SmallestAICredential" + }, + { + "$ref": "#/components/schemas/CreateSpeechmaticsCredentialDTO", + "title": "SpeechmaticsCredential" + }, + { + "$ref": "#/components/schemas/CreateSonioxCredentialDTO", + "title": "SonioxCredential" + }, + { + "$ref": "#/components/schemas/CreateSupabaseCredentialDTO", + "title": "SupabaseCredential" + }, + { + "$ref": "#/components/schemas/CreateTavusCredentialDTO", + "title": "TavusCredential" + }, + { + "$ref": "#/components/schemas/CreateTogetherAICredentialDTO", + "title": "TogetherAICredential" + }, + { + "$ref": "#/components/schemas/CreateTwilioCredentialDTO", + "title": "TwilioCredential" + }, + { + "$ref": "#/components/schemas/CreateVonageCredentialDTO", + "title": "VonageCredential" + }, + { + "$ref": "#/components/schemas/CreateWebhookCredentialDTO", + "title": "WebhookCredential" + }, + { + "$ref": "#/components/schemas/CreateCustomCredentialDTO", + "title": "CustomCredential" + }, + { + "$ref": "#/components/schemas/CreateXAiCredentialDTO", + "title": "XAiCredential" + }, + { + "$ref": "#/components/schemas/CreateMicrosoftCredentialDTO", + "title": "MicrosoftCredential" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarOAuth2ClientCredentialDTO", + "title": "GoogleCalendarOAuth2ClientCredential" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarOAuth2AuthorizationCredentialDTO", + "title": "GoogleCalendarOAuth2AuthorizationCredential" + }, + { + "$ref": "#/components/schemas/CreateGoogleSheetsOAuth2AuthorizationCredentialDTO", + "title": "GoogleSheetsOAuth2AuthorizationCredential" + }, + { + "$ref": "#/components/schemas/CreateSlackOAuth2AuthorizationCredentialDTO", + "title": "SlackOAuth2AuthorizationCredential" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelMCPCredentialDTO", + "title": "GoHighLevelMCPCredential" + }, + { + "$ref": "#/components/schemas/CreateInworldCredentialDTO", + "title": "InworldCredential" + }, + { + "$ref": "#/components/schemas/CreateMinimaxCredentialDTO", + "title": "MinimaxCredential" + }, + { + "$ref": "#/components/schemas/CreateWellSaidCredentialDTO", + "title": "WellSaidCredential" + }, + { + "$ref": "#/components/schemas/CreateEmailCredentialDTO", + "title": "EmailCredential" + }, + { + "$ref": "#/components/schemas/CreateSlackWebhookCredentialDTO", + "title": "SlackWebhookCredential" + } + ], + "discriminator": { + "propertyName": "provider", + "mapping": { + "11labs": "#/components/schemas/CreateElevenLabsCredentialDTO", + "anthropic": "#/components/schemas/CreateAnthropicCredentialDTO", + "anthropic-bedrock": "#/components/schemas/CreateAnthropicBedrockCredentialDTO", + "anyscale": "#/components/schemas/CreateAnyscaleCredentialDTO", + "assembly-ai": "#/components/schemas/CreateAssemblyAICredentialDTO", + "azure-openai": "#/components/schemas/CreateAzureOpenAICredentialDTO", + "azure": "#/components/schemas/CreateAzureCredentialDTO", + "byo-sip-trunk": "#/components/schemas/CreateByoSipTrunkCredentialDTO", + "cartesia": "#/components/schemas/CreateCartesiaCredentialDTO", + "cerebras": "#/components/schemas/CreateCerebrasCredentialDTO", + "cloudflare": "#/components/schemas/CreateCloudflareCredentialDTO", + "custom-llm": "#/components/schemas/CreateCustomLLMCredentialDTO", + "deepgram": "#/components/schemas/CreateDeepgramCredentialDTO", + "deepinfra": "#/components/schemas/CreateDeepInfraCredentialDTO", + "deep-seek": "#/components/schemas/CreateDeepSeekCredentialDTO", + "gcp": "#/components/schemas/CreateGcpCredentialDTO", + "gladia": "#/components/schemas/CreateGladiaCredentialDTO", + "gohighlevel": "#/components/schemas/CreateGoHighLevelCredentialDTO", + "google": "#/components/schemas/CreateGoogleCredentialDTO", + "groq": "#/components/schemas/CreateGroqCredentialDTO", + "inflection-ai": "#/components/schemas/CreateInflectionAICredentialDTO", + "langfuse": "#/components/schemas/CreateLangfuseCredentialDTO", + "lmnt": "#/components/schemas/CreateLmntCredentialDTO", + "make": "#/components/schemas/CreateMakeCredentialDTO", + "openai": "#/components/schemas/CreateOpenAICredentialDTO", + "openrouter": "#/components/schemas/CreateOpenRouterCredentialDTO", + "perplexity-ai": "#/components/schemas/CreatePerplexityAICredentialDTO", + "playht": "#/components/schemas/CreatePlayHTCredentialDTO", + "rime-ai": "#/components/schemas/CreateRimeAICredentialDTO", + "runpod": "#/components/schemas/CreateRunpodCredentialDTO", + "s3": "#/components/schemas/CreateS3CredentialDTO", + "s3-compatible": "#/components/schemas/CreateS3CompatibleCredentialDTO", + "supabase": "#/components/schemas/CreateSupabaseCredentialDTO", + "smallest-ai": "#/components/schemas/CreateSmallestAICredentialDTO", + "tavus": "#/components/schemas/CreateTavusCredentialDTO", + "together-ai": "#/components/schemas/CreateTogetherAICredentialDTO", + "twilio": "#/components/schemas/CreateTwilioCredentialDTO", + "vonage": "#/components/schemas/CreateVonageCredentialDTO", + "webhook": "#/components/schemas/CreateWebhookCredentialDTO", + "custom-credential": "#/components/schemas/CreateCustomCredentialDTO", + "xai": "#/components/schemas/CreateXAiCredentialDTO", + "microsoft": "#/components/schemas/CreateMicrosoftCredentialDTO", + "neuphonic": "#/components/schemas/CreateNeuphonicCredentialDTO", + "hume": "#/components/schemas/CreateHumeCredentialDTO", + "mistral": "#/components/schemas/CreateMistralCredentialDTO", + "speechmatics": "#/components/schemas/CreateSpeechmaticsCredentialDTO", + "soniox": "#/components/schemas/CreateSonioxCredentialDTO", + "google.calendar.oauth2-client": "#/components/schemas/CreateGoogleCalendarOAuth2ClientCredentialDTO", + "google.calendar.oauth2-authorization": "#/components/schemas/CreateGoogleCalendarOAuth2AuthorizationCredentialDTO", + "google.sheets.oauth2-authorization": "#/components/schemas/CreateGoogleSheetsOAuth2AuthorizationCredentialDTO", + "slack.oauth2-authorization": "#/components/schemas/CreateSlackOAuth2AuthorizationCredentialDTO", + "ghl.oauth2-authorization": "#/components/schemas/CreateGoHighLevelMCPCredentialDTO", + "inworld": "#/components/schemas/CreateInworldCredentialDTO", + "minimax": "#/components/schemas/CreateMinimaxCredentialDTO", + "wellsaid": "#/components/schemas/CreateWellSaidCredentialDTO", + "email": "#/components/schemas/CreateEmailCredentialDTO", + "slack-webhook": "#/components/schemas/CreateSlackWebhookCredentialDTO" + } + } + } + }, + "hooks": { + "type": "array", + "description": "This is a set of actions that will be performed on certain events.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/CallHookCallEnding", + "title": "CallHookCallEnding" + }, + { + "$ref": "#/components/schemas/CallHookAssistantSpeechInterrupted", + "title": "CallHookAssistantSpeechInterrupted" + }, + { + "$ref": "#/components/schemas/CallHookCustomerSpeechInterrupted", + "title": "CallHookCustomerSpeechInterrupted" + }, + { + "$ref": "#/components/schemas/CallHookCustomerSpeechTimeout", + "title": "CallHookCustomerSpeechTimeout" + }, + { + "$ref": "#/components/schemas/SessionCreatedHook", + "title": "SessionCreatedHook" + } + ] + } + }, + "versionName": { + "type": "string", + "nullable": true, + "description": "Optional human-readable label for this version. Pass `null` to clear.", + "maxLength": 80 + }, + "versionDescription": { + "type": "string", + "nullable": true, + "description": "Optional description for this version. Pass `null` to clear.", + "maxLength": 500 + }, + "id": { + "type": "string", + "description": "This is the unique identifier for the version row.", + "format": "uuid" + }, + "orgId": { + "type": "string", + "description": "This is the unique identifier for the org that owns this version.", + "format": "uuid" + }, + "assistantId": { + "type": "string", + "description": "This is the unique identifier for the assistant this version was snapshotted from.", + "format": "uuid" + }, + "version": { + "type": "string", + "description": "This is the public monotonic version label, e.g. \"v1\".\nSystem-owned and incremented per assistant; never user-supplied.", + "example": "v1" + }, + "configHash": { + "type": "string", + "description": "This is the SHA-256 hex of the snapshotted content used for no-op detection." + }, + "parentVersion": { + "type": "string", + "nullable": true, + "description": "This is the prior version label (vN-1). Null on v1 or for branch roots." + }, + "restoredFromVersion": { + "type": "string", + "nullable": true, + "description": "The version this version was restored from. Null when it was not restored." + }, + "createdBy": { + "type": "string", + "nullable": true, + "description": "This is the actor that wrote this version. Email when created via JWT, null when created via API." + }, + "deletedAt": { + "type": "string", + "nullable": true, + "description": "This is the soft-delete timestamp. Null when active.", + "format": "date-time" + }, + "createdAt": { + "type": "string", + "description": "This is the ISO 8601 date-time string of when the version was created.", + "format": "date-time" + }, + "name": { + "type": "string", + "description": "This is the name of the assistant.\n\nThis is required when you want to transfer between assistants in a call.", + "maxLength": 40 + }, + "voicemailMessage": { + "type": "string", + "description": "This is the message that the assistant will say if the call is forwarded to voicemail.\n\nIf unspecified, it will hang up.", + "maxLength": 1000 + }, + "endCallMessage": { + "type": "string", + "description": "This is the message that the assistant will say if it ends the call.\n\nIf unspecified, it will hang up without saying anything.", + "maxLength": 1000 + }, + "endCallPhrases": { + "description": "This list contains phrases that, if spoken by the assistant, will trigger the call to be hung up. Case insensitive.", + "type": "array", + "items": { + "type": "string", + "maxLength": 140, + "minLength": 2 + } + }, + "compliancePlan": { + "$ref": "#/components/schemas/CompliancePlan" + }, + "metadata": { + "type": "object", + "description": "This is for metadata you want to store on the assistant." + }, + "backgroundSpeechDenoisingPlan": { + "description": "This enables filtering of noise and background speech while the user is talking.\n\nFeatures:\n- Smart denoising using Krisp\n- Fourier denoising\n\nSmart denoising can be combined with or used independently of Fourier denoising.\n\nOrder of precedence:\n- Smart denoising\n- Fourier denoising", + "allOf": [ + { + "$ref": "#/components/schemas/BackgroundSpeechDenoisingPlan" + } + ] + }, + "analysisPlan": { + "description": "This is the plan for analysis of assistant's calls. Stored in `call.analysis`.", + "deprecated": true, + "allOf": [ + { + "$ref": "#/components/schemas/AnalysisPlan" + } + ] + }, + "artifactPlan": { + "description": "This is the plan for artifacts generated during assistant's calls. Stored in `call.artifact`.", + "allOf": [ + { + "$ref": "#/components/schemas/ArtifactPlan" + } + ] + }, + "startSpeakingPlan": { + "description": "This is the plan for when the assistant should start talking.\n\nYou should configure this if you're running into these issues:\n- The assistant is too slow to start talking after the customer is done speaking.\n- The assistant is too fast to start talking after the customer is done speaking.\n- The assistant is so fast that it's actually interrupting the customer.", + "allOf": [ + { + "$ref": "#/components/schemas/StartSpeakingPlan" + } + ] + }, + "stopSpeakingPlan": { + "description": "This is the plan for when assistant should stop talking on customer interruption.\n\nYou should configure this if you're running into these issues:\n- The assistant is too slow to recognize customer's interruption.\n- The assistant is too fast to recognize customer's interruption.\n- The assistant is getting interrupted by phrases that are just acknowledgments.\n- The assistant is getting interrupted by background noises.\n- The assistant is not properly stopping -- it starts talking right after getting interrupted.", + "allOf": [ + { + "$ref": "#/components/schemas/StopSpeakingPlan" + } + ] + }, + "monitorPlan": { + "description": "This is the plan for real-time monitoring of the assistant's calls.\n\nUsage:\n- To enable live listening of the assistant's calls, set `monitorPlan.listenEnabled` to `true`.\n- To enable live control of the assistant's calls, set `monitorPlan.controlEnabled` to `true`.\n- To attach monitors to the assistant, set `monitorPlan.monitorIds` to the set of monitor ids.", + "allOf": [ + { + "$ref": "#/components/schemas/MonitorPlan" + } + ] + }, + "credentialIds": { + "description": "These are the credentials that will be used for the assistant calls. By default, all the credentials are available for use in the call but you can provide a subset using this.", + "type": "array", + "items": { + "type": "string" + } + }, + "server": { + "description": "This is where Vapi will send webhooks. You can find all webhooks available along with their shape in ServerMessage schema.\n\nThe order of precedence is:\n\n1. assistant.server.url\n2. phoneNumber.serverUrl\n3. org.serverUrl", + "allOf": [ + { + "$ref": "#/components/schemas/Server" + } + ] + }, + "keypadInputPlan": { + "$ref": "#/components/schemas/KeypadInputPlan" + } + }, + "required": [ + "id", + "orgId", + "assistantId", + "version", + "configHash", + "createdAt" + ] + }, + "AssistantVersionPaginatedMetadata": { + "type": "object", + "properties": { + "nextCursor": { + "type": "string", + "nullable": true + }, + "hasNextPage": { + "type": "boolean" + }, + "limit": { + "type": "number" + } + }, + "required": [ + "hasNextPage", + "limit" + ] + }, + "AssistantVersionPaginatedResponse": { + "type": "object", + "properties": { + "results": { + "type": "array", + "items": { + "$ref": "#/components/schemas/AssistantVersion" + } + }, + "metadata": { + "$ref": "#/components/schemas/AssistantVersionPaginatedMetadata" + } + }, + "required": [ + "results", + "metadata" + ] + }, + "UpdateAssistantVersionMetadataDTO": { + "type": "object", + "properties": { + "versionName": { + "type": "string", + "nullable": true, + "description": "Optional human-readable label for this version. Pass `null` to clear.", + "maxLength": 80 + }, + "versionDescription": { + "type": "string", + "nullable": true, + "description": "Optional description for this version. Pass `null` to clear.", + "maxLength": 500 + } + } + }, + "VersionPinReference": { + "type": "object", + "properties": { + "sourceType": { + "type": "string", + "enum": [ + "assistant_version", + "squad", + "tool_version" + ], + "description": "Kind of source row the pin originates from." + }, + "sourceId": { + "type": "string", + "format": "uuid", + "description": "UUID of the source row (polymorphic, not FK-enforced)." + } + }, + "required": [ + "sourceType", + "sourceId" + ] + }, + "VersionPinConflictResponseDTO": { + "type": "object", + "properties": { + "error": { + "type": "string", + "enum": [ + "version_pinned" + ] + }, + "message": { + "type": "string", + "description": "Human-readable reason the delete was rejected." + }, + "pinnedBy": { + "description": "Pins that block the delete.", + "type": "array", + "items": { + "$ref": "#/components/schemas/VersionPinReference" + } + } + }, + "required": [ + "error", + "message", + "pinnedBy" + ] + }, + "CreateAssistantDraftDTO": { + "type": "object", + "properties": { + "transcriber": { + "description": "These are the options for the assistant's transcriber.", + "oneOf": [ + { + "$ref": "#/components/schemas/AssemblyAITranscriber", + "title": "AssemblyAITranscriber" + }, + { + "$ref": "#/components/schemas/AzureSpeechTranscriber", + "title": "AzureSpeechTranscriber" + }, + { + "$ref": "#/components/schemas/CustomTranscriber", + "title": "CustomTranscriber" + }, + { + "$ref": "#/components/schemas/DeepgramTranscriber", + "title": "DeepgramTranscriber" + }, + { + "$ref": "#/components/schemas/ElevenLabsTranscriber", + "title": "ElevenLabsTranscriber" + }, + { + "$ref": "#/components/schemas/GladiaTranscriber", + "title": "GladiaTranscriber" + }, + { + "$ref": "#/components/schemas/GoogleTranscriber", + "title": "GoogleTranscriber" + }, + { + "$ref": "#/components/schemas/SpeechmaticsTranscriber", + "title": "SpeechmaticsTranscriber" + }, + { + "$ref": "#/components/schemas/TalkscriberTranscriber", + "title": "TalkscriberTranscriber" + }, + { + "$ref": "#/components/schemas/OpenAITranscriber", + "title": "OpenAITranscriber" + }, + { + "$ref": "#/components/schemas/CartesiaTranscriber", + "title": "CartesiaTranscriber" + }, + { + "$ref": "#/components/schemas/SonioxTranscriber", + "title": "SonioxTranscriber" + }, + { + "$ref": "#/components/schemas/XaiTranscriber", + "title": "XaiTranscriber" + }, + { + "$ref": "#/components/schemas/VapiTranscriber", + "title": "VapiTranscriber" + } + ] + }, + "model": { + "description": "These are the options for the assistant's LLM.", + "oneOf": [ + { + "$ref": "#/components/schemas/AnthropicModel", + "title": "Anthropic" + }, + { + "$ref": "#/components/schemas/AnthropicBedrockModel", + "title": "AnthropicBedrock" + }, + { + "$ref": "#/components/schemas/AnyscaleModel", + "title": "Anyscale" + }, + { + "$ref": "#/components/schemas/CerebrasModel", + "title": "Cerebras" + }, + { + "$ref": "#/components/schemas/CustomLLMModel", + "title": "CustomLLM" + }, + { + "$ref": "#/components/schemas/DeepInfraModel", + "title": "DeepInfra" + }, + { + "$ref": "#/components/schemas/DeepSeekModel", + "title": "DeepSeek" + }, + { + "$ref": "#/components/schemas/GoogleModel", + "title": "Google" + }, + { + "$ref": "#/components/schemas/GroqModel", + "title": "Groq" + }, + { + "$ref": "#/components/schemas/InflectionAIModel", + "title": "InflectionAI" + }, + { + "$ref": "#/components/schemas/MinimaxLLMModel", + "title": "MiniMaxLLM" + }, + { + "$ref": "#/components/schemas/OpenAIModel", + "title": "OpenAI" + }, + { + "$ref": "#/components/schemas/OpenRouterModel", + "title": "OpenRouter" + }, + { + "$ref": "#/components/schemas/PerplexityAIModel", + "title": "PerplexityAI" + }, + { + "$ref": "#/components/schemas/TogetherAIModel", + "title": "Together" + }, + { + "$ref": "#/components/schemas/XaiModel", + "title": "XAI" + }, + { + "$ref": "#/components/schemas/VapiModel", + "title": "Vapi" + } + ] + }, + "voice": { + "description": "These are the options for the assistant's voice.", + "oneOf": [ + { + "$ref": "#/components/schemas/AzureVoice", + "title": "AzureVoice" + }, + { + "$ref": "#/components/schemas/CartesiaVoice", + "title": "CartesiaVoice" + }, + { + "$ref": "#/components/schemas/CustomVoice", + "title": "CustomVoice" + }, + { + "$ref": "#/components/schemas/DeepgramVoice", + "title": "DeepgramVoice" + }, + { + "$ref": "#/components/schemas/ElevenLabsVoice", + "title": "ElevenLabsVoice" + }, + { + "$ref": "#/components/schemas/HumeVoice", + "title": "HumeVoice" + }, + { + "$ref": "#/components/schemas/LMNTVoice", + "title": "LMNTVoice" + }, + { + "$ref": "#/components/schemas/NeuphonicVoice", + "title": "NeuphonicVoice" + }, + { + "$ref": "#/components/schemas/OpenAIVoice", + "title": "OpenAIVoice" + }, + { + "$ref": "#/components/schemas/PlayHTVoice", + "title": "PlayHTVoice" + }, + { + "$ref": "#/components/schemas/WellSaidVoice", + "title": "WellSaidVoice" + }, + { + "$ref": "#/components/schemas/RimeAIVoice", + "title": "RimeAIVoice" + }, + { + "$ref": "#/components/schemas/SmallestAIVoice", + "title": "SmallestAIVoice" + }, + { + "$ref": "#/components/schemas/TavusVoice", + "title": "TavusVoice" + }, + { + "$ref": "#/components/schemas/VapiVoice", + "title": "VapiVoice" + }, + { + "$ref": "#/components/schemas/SesameVoice", + "title": "SesameVoice" + }, + { + "$ref": "#/components/schemas/InworldVoice", + "title": "InworldVoice" + }, + { + "$ref": "#/components/schemas/MinimaxVoice", + "title": "MinimaxVoice" + }, + { + "$ref": "#/components/schemas/XaiVoice", + "title": "XaiVoice" + }, + { + "$ref": "#/components/schemas/MicrosoftVoice", + "title": "MicrosoftVoice" + } + ] + }, + "firstMessage": { + "type": "string", + "description": "This is the first message that the assistant will say. This can also be a URL to a containerized audio file (mp3, wav, etc.).\n\nIf unspecified, assistant will wait for user to speak and use the model to respond once they speak.", + "example": "Hello! How can I help you today?" + }, + "firstMessageInterruptionsEnabled": { + "type": "boolean", + "default": false + }, + "firstMessageMode": { + "type": "string", + "description": "This is the mode for the first message. Default is 'assistant-speaks-first'.\n\nUse:\n- 'assistant-speaks-first' to have the assistant speak first.\n- 'assistant-waits-for-user' to have the assistant wait for the user to speak first.\n- 'assistant-speaks-first-with-model-generated-message' to have the assistant speak first with a message generated by the model based on the conversation state. (`assistant.model.messages` at call start, `call.messages` at squad transfer points).\n\n@default 'assistant-speaks-first'", + "enum": [ + "assistant-speaks-first", + "assistant-speaks-first-with-model-generated-message", + "assistant-waits-for-user" + ], + "example": "assistant-speaks-first" + }, + "voicemailDetection": { + "description": "These are the settings to configure or disable voicemail detection. Alternatively, voicemail detection can be configured using the model.tools=[VoicemailTool].\nBy default, voicemail detection is disabled.", + "oneOf": [ + { + "type": "string", + "enum": [ + "off" + ] + }, + { + "$ref": "#/components/schemas/GoogleVoicemailDetectionPlan", + "title": "Google" + }, + { + "$ref": "#/components/schemas/OpenAIVoicemailDetectionPlan", + "title": "OpenAI" + }, + { + "$ref": "#/components/schemas/TwilioVoicemailDetectionPlan", + "title": "Twilio" + }, + { + "$ref": "#/components/schemas/VapiVoicemailDetectionPlan", + "title": "Vapi" + } + ] + }, + "clientMessages": { + "type": "array", + "enum": [ + "conversation-update", + "assistant.speechStarted", + "function-call", + "function-call-result", + "hang", + "language-changed", + "metadata", + "model-output", + "speech-update", + "status-update", + "transcript", + "tool-calls", + "tool-calls-result", + "tool.completed", + "transfer-update", + "user-interrupted", + "voice-input", + "workflow.node.started", + "assistant.started" + ], + "example": [ + "conversation-update", + "function-call", + "hang", + "model-output", + "speech-update", + "status-update", + "transfer-update", + "transcript", + "tool-calls", + "user-interrupted", + "voice-input", + "workflow.node.started", + "assistant.started" + ], + "description": "These are the messages that will be sent to your Client SDKs. Default is conversation-update,function-call,hang,model-output,speech-update,status-update,transfer-update,transcript,tool-calls,user-interrupted,voice-input,workflow.node.started,assistant.started. You can check the shape of the messages in ClientMessage schema.", + "items": { + "type": "string", + "enum": [ + "conversation-update", + "assistant.speechStarted", + "function-call", + "function-call-result", + "hang", + "language-changed", + "metadata", + "model-output", + "speech-update", + "status-update", + "transcript", + "tool-calls", + "tool-calls-result", + "tool.completed", + "transfer-update", + "user-interrupted", + "voice-input", + "workflow.node.started", + "assistant.started" + ] + } + }, + "serverMessages": { + "type": "array", + "enum": [ + "assistant.started", + "assistant.speechStarted", + "conversation-update", + "end-of-call-report", + "function-call", + "hang", + "language-changed", + "language-change-detected", + "model-output", + "phone-call-control", + "speech-update", + "status-update", + "transcript", + "transcript[transcriptType=\"final\"]", + "tool-calls", + "transfer-destination-request", + "handoff-destination-request", + "transfer-update", + "user-interrupted", + "voice-input", + "chat.created", + "chat.deleted", + "session.created", + "session.updated", + "session.deleted", + "call.deleted", + "call.delete.failed", + "call.artifact.upload" + ], + "example": [ + "conversation-update", + "end-of-call-report", + "function-call", + "hang", + "speech-update", + "status-update", + "tool-calls", + "transfer-destination-request", + "handoff-destination-request", + "user-interrupted", + "assistant.started" + ], + "description": "These are the messages that will be sent to your Server URL. Default is conversation-update,end-of-call-report,function-call,hang,speech-update,status-update,tool-calls,transfer-destination-request,handoff-destination-request,user-interrupted,assistant.started. You can check the shape of the messages in ServerMessage schema.", + "items": { + "type": "string", + "enum": [ + "assistant.started", + "assistant.speechStarted", + "conversation-update", + "end-of-call-report", + "function-call", + "hang", + "language-changed", + "language-change-detected", + "model-output", + "phone-call-control", + "speech-update", + "status-update", + "transcript", + "transcript[transcriptType=\"final\"]", + "tool-calls", + "transfer-destination-request", + "handoff-destination-request", + "transfer-update", + "user-interrupted", + "voice-input", + "chat.created", + "chat.deleted", + "session.created", + "session.updated", + "session.deleted", + "call.deleted", + "call.delete.failed", + "call.artifact.upload" + ] + } + }, + "maxDurationSeconds": { + "type": "number", + "description": "This is the maximum number of seconds that the call will last. When the call reaches this duration, it will be ended.\n\n@default 600 (10 minutes)", + "minimum": 10, + "maximum": 43200, + "example": 600 + }, + "backgroundSound": { + "description": "This is the background sound in the call. Default for phone calls is 'office' and default for web calls is 'off'.\nYou can also provide a custom sound by providing a URL to an audio file.", + "oneOf": [ + { + "type": "string", + "enum": [ + "off", + "office" + ], + "example": "office" + }, + { + "type": "string", + "format": "uri", + "example": "https://www.soundjay.com/ambient/sounds/people-in-lounge-1.mp3" + } + ] + }, + "modelOutputInMessagesEnabled": { + "type": "boolean", + "description": "This determines whether the model's output is used in conversation history rather than the transcription of assistant's speech.\n\n@default false", + "example": false + }, + "transportConfigurations": { + "type": "array", + "description": "These are the configurations to be passed to the transport providers of assistant's calls, like Twilio. You can store multiple configurations for different transport providers. For a call, only the configuration matching the call transport provider is used.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/TransportConfigurationTwilio", + "title": "Twilio" + } + ] + } + }, + "observabilityPlan": { + "description": "This is the plan for observability of assistant's calls.\n\nCurrently, only Langfuse is supported.", + "oneOf": [ + { + "$ref": "#/components/schemas/LangfuseObservabilityPlan", + "title": "Langfuse" + } + ], + "allOf": [ + { + "$ref": "#/components/schemas/LangfuseObservabilityPlan" + } + ] + }, + "credentials": { + "type": "array", + "description": "These are dynamic credentials that will be used for the assistant calls. By default, all the credentials are available for use in the call but you can supplement an additional credentials using this. Dynamic credentials override existing credentials.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/CreateAnthropicCredentialDTO", + "title": "AnthropicCredential" + }, + { + "$ref": "#/components/schemas/CreateAnthropicBedrockCredentialDTO", + "title": "AnthropicBedrockCredential" + }, + { + "$ref": "#/components/schemas/CreateAnyscaleCredentialDTO", + "title": "AnyscaleCredential" + }, + { + "$ref": "#/components/schemas/CreateAssemblyAICredentialDTO", + "title": "AssemblyAICredential" + }, + { + "$ref": "#/components/schemas/CreateAzureCredentialDTO", + "title": "AzureCredential" + }, + { + "$ref": "#/components/schemas/CreateAzureOpenAICredentialDTO", + "title": "AzureOpenAICredential" + }, + { + "$ref": "#/components/schemas/CreateByoSipTrunkCredentialDTO", + "title": "ByoSipTrunkCredential" + }, + { + "$ref": "#/components/schemas/CreateCartesiaCredentialDTO", + "title": "CartesiaCredential" + }, + { + "$ref": "#/components/schemas/CreateCerebrasCredentialDTO", + "title": "CerebrasCredential" + }, + { + "$ref": "#/components/schemas/CreateCloudflareCredentialDTO", + "title": "CloudflareCredential" + }, + { + "$ref": "#/components/schemas/CreateCustomLLMCredentialDTO", + "title": "CustomLLMCredential" + }, + { + "$ref": "#/components/schemas/CreateDeepgramCredentialDTO", + "title": "DeepgramCredential" + }, + { + "$ref": "#/components/schemas/CreateDeepInfraCredentialDTO", + "title": "DeepInfraCredential" + }, + { + "$ref": "#/components/schemas/CreateDeepSeekCredentialDTO", + "title": "DeepSeekCredential" + }, + { + "$ref": "#/components/schemas/CreateElevenLabsCredentialDTO", + "title": "ElevenLabsCredential" + }, + { + "$ref": "#/components/schemas/CreateGcpCredentialDTO", + "title": "GcpCredential" + }, + { + "$ref": "#/components/schemas/CreateGladiaCredentialDTO", + "title": "GladiaCredential" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelCredentialDTO", + "title": "GhlCredential" + }, + { + "$ref": "#/components/schemas/CreateGoogleCredentialDTO", + "title": "GoogleCredential" + }, + { + "$ref": "#/components/schemas/CreateGroqCredentialDTO", + "title": "GroqCredential" + }, + { + "$ref": "#/components/schemas/CreateHumeCredentialDTO", + "title": "HumeCredential" + }, + { + "$ref": "#/components/schemas/CreateInflectionAICredentialDTO", + "title": "InflectionAICredential" + }, + { + "$ref": "#/components/schemas/CreateLangfuseCredentialDTO", + "title": "LangfuseCredential" + }, + { + "$ref": "#/components/schemas/CreateLmntCredentialDTO", + "title": "LmntCredential" + }, + { + "$ref": "#/components/schemas/CreateMakeCredentialDTO", + "title": "MakeCredential" + }, + { + "$ref": "#/components/schemas/CreateMistralCredentialDTO", + "title": "MistralCredential" + }, + { + "$ref": "#/components/schemas/CreateNeuphonicCredentialDTO", + "title": "NeuphonicCredential" + }, + { + "$ref": "#/components/schemas/CreateOpenAICredentialDTO", + "title": "OpenAICredential" + }, + { + "$ref": "#/components/schemas/CreateOpenRouterCredentialDTO", + "title": "OpenRouterCredential" + }, + { + "$ref": "#/components/schemas/CreatePerplexityAICredentialDTO", + "title": "PerplexityAICredential" + }, + { + "$ref": "#/components/schemas/CreatePlayHTCredentialDTO", + "title": "PlayHTCredential" + }, + { + "$ref": "#/components/schemas/CreateRimeAICredentialDTO", + "title": "RimeAICredential" + }, + { + "$ref": "#/components/schemas/CreateRunpodCredentialDTO", + "title": "RunpodCredential" + }, + { + "$ref": "#/components/schemas/CreateS3CredentialDTO", + "title": "S3Credential" + }, + { + "$ref": "#/components/schemas/CreateS3CompatibleCredentialDTO", + "title": "S3CompatibleStorageCredential" + }, + { + "$ref": "#/components/schemas/CreateSmallestAICredentialDTO", + "title": "SmallestAICredential" + }, + { + "$ref": "#/components/schemas/CreateSpeechmaticsCredentialDTO", + "title": "SpeechmaticsCredential" + }, + { + "$ref": "#/components/schemas/CreateSonioxCredentialDTO", + "title": "SonioxCredential" + }, + { + "$ref": "#/components/schemas/CreateSupabaseCredentialDTO", + "title": "SupabaseCredential" + }, + { + "$ref": "#/components/schemas/CreateTavusCredentialDTO", + "title": "TavusCredential" + }, + { + "$ref": "#/components/schemas/CreateTogetherAICredentialDTO", + "title": "TogetherAICredential" + }, + { + "$ref": "#/components/schemas/CreateTwilioCredentialDTO", + "title": "TwilioCredential" + }, + { + "$ref": "#/components/schemas/CreateVonageCredentialDTO", + "title": "VonageCredential" + }, + { + "$ref": "#/components/schemas/CreateWebhookCredentialDTO", + "title": "WebhookCredential" + }, + { + "$ref": "#/components/schemas/CreateCustomCredentialDTO", + "title": "CustomCredential" + }, + { + "$ref": "#/components/schemas/CreateXAiCredentialDTO", + "title": "XAiCredential" + }, + { + "$ref": "#/components/schemas/CreateMicrosoftCredentialDTO", + "title": "MicrosoftCredential" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarOAuth2ClientCredentialDTO", + "title": "GoogleCalendarOAuth2ClientCredential" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarOAuth2AuthorizationCredentialDTO", + "title": "GoogleCalendarOAuth2AuthorizationCredential" + }, + { + "$ref": "#/components/schemas/CreateGoogleSheetsOAuth2AuthorizationCredentialDTO", + "title": "GoogleSheetsOAuth2AuthorizationCredential" + }, + { + "$ref": "#/components/schemas/CreateSlackOAuth2AuthorizationCredentialDTO", + "title": "SlackOAuth2AuthorizationCredential" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelMCPCredentialDTO", + "title": "GoHighLevelMCPCredential" + }, + { + "$ref": "#/components/schemas/CreateInworldCredentialDTO", + "title": "InworldCredential" + }, + { + "$ref": "#/components/schemas/CreateMinimaxCredentialDTO", + "title": "MinimaxCredential" + }, + { + "$ref": "#/components/schemas/CreateWellSaidCredentialDTO", + "title": "WellSaidCredential" + }, + { + "$ref": "#/components/schemas/CreateEmailCredentialDTO", + "title": "EmailCredential" + }, + { + "$ref": "#/components/schemas/CreateSlackWebhookCredentialDTO", + "title": "SlackWebhookCredential" + } + ], + "discriminator": { + "propertyName": "provider", + "mapping": { + "11labs": "#/components/schemas/CreateElevenLabsCredentialDTO", + "anthropic": "#/components/schemas/CreateAnthropicCredentialDTO", + "anthropic-bedrock": "#/components/schemas/CreateAnthropicBedrockCredentialDTO", + "anyscale": "#/components/schemas/CreateAnyscaleCredentialDTO", + "assembly-ai": "#/components/schemas/CreateAssemblyAICredentialDTO", + "azure-openai": "#/components/schemas/CreateAzureOpenAICredentialDTO", + "azure": "#/components/schemas/CreateAzureCredentialDTO", + "byo-sip-trunk": "#/components/schemas/CreateByoSipTrunkCredentialDTO", + "cartesia": "#/components/schemas/CreateCartesiaCredentialDTO", + "cerebras": "#/components/schemas/CreateCerebrasCredentialDTO", + "cloudflare": "#/components/schemas/CreateCloudflareCredentialDTO", + "custom-llm": "#/components/schemas/CreateCustomLLMCredentialDTO", + "deepgram": "#/components/schemas/CreateDeepgramCredentialDTO", + "deepinfra": "#/components/schemas/CreateDeepInfraCredentialDTO", + "deep-seek": "#/components/schemas/CreateDeepSeekCredentialDTO", + "gcp": "#/components/schemas/CreateGcpCredentialDTO", + "gladia": "#/components/schemas/CreateGladiaCredentialDTO", + "gohighlevel": "#/components/schemas/CreateGoHighLevelCredentialDTO", + "google": "#/components/schemas/CreateGoogleCredentialDTO", + "groq": "#/components/schemas/CreateGroqCredentialDTO", + "inflection-ai": "#/components/schemas/CreateInflectionAICredentialDTO", + "langfuse": "#/components/schemas/CreateLangfuseCredentialDTO", + "lmnt": "#/components/schemas/CreateLmntCredentialDTO", + "make": "#/components/schemas/CreateMakeCredentialDTO", + "openai": "#/components/schemas/CreateOpenAICredentialDTO", + "openrouter": "#/components/schemas/CreateOpenRouterCredentialDTO", + "perplexity-ai": "#/components/schemas/CreatePerplexityAICredentialDTO", + "playht": "#/components/schemas/CreatePlayHTCredentialDTO", + "rime-ai": "#/components/schemas/CreateRimeAICredentialDTO", + "runpod": "#/components/schemas/CreateRunpodCredentialDTO", + "s3": "#/components/schemas/CreateS3CredentialDTO", + "s3-compatible": "#/components/schemas/CreateS3CompatibleCredentialDTO", + "supabase": "#/components/schemas/CreateSupabaseCredentialDTO", + "smallest-ai": "#/components/schemas/CreateSmallestAICredentialDTO", + "tavus": "#/components/schemas/CreateTavusCredentialDTO", + "together-ai": "#/components/schemas/CreateTogetherAICredentialDTO", + "twilio": "#/components/schemas/CreateTwilioCredentialDTO", + "vonage": "#/components/schemas/CreateVonageCredentialDTO", + "webhook": "#/components/schemas/CreateWebhookCredentialDTO", + "custom-credential": "#/components/schemas/CreateCustomCredentialDTO", + "xai": "#/components/schemas/CreateXAiCredentialDTO", + "microsoft": "#/components/schemas/CreateMicrosoftCredentialDTO", + "neuphonic": "#/components/schemas/CreateNeuphonicCredentialDTO", + "hume": "#/components/schemas/CreateHumeCredentialDTO", + "mistral": "#/components/schemas/CreateMistralCredentialDTO", + "speechmatics": "#/components/schemas/CreateSpeechmaticsCredentialDTO", + "soniox": "#/components/schemas/CreateSonioxCredentialDTO", + "google.calendar.oauth2-client": "#/components/schemas/CreateGoogleCalendarOAuth2ClientCredentialDTO", + "google.calendar.oauth2-authorization": "#/components/schemas/CreateGoogleCalendarOAuth2AuthorizationCredentialDTO", + "google.sheets.oauth2-authorization": "#/components/schemas/CreateGoogleSheetsOAuth2AuthorizationCredentialDTO", + "slack.oauth2-authorization": "#/components/schemas/CreateSlackOAuth2AuthorizationCredentialDTO", + "ghl.oauth2-authorization": "#/components/schemas/CreateGoHighLevelMCPCredentialDTO", + "inworld": "#/components/schemas/CreateInworldCredentialDTO", + "minimax": "#/components/schemas/CreateMinimaxCredentialDTO", + "wellsaid": "#/components/schemas/CreateWellSaidCredentialDTO", + "email": "#/components/schemas/CreateEmailCredentialDTO", + "slack-webhook": "#/components/schemas/CreateSlackWebhookCredentialDTO" + } + } + } + }, + "hooks": { + "type": "array", + "description": "This is a set of actions that will be performed on certain events.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/CallHookCallEnding", + "title": "CallHookCallEnding" + }, + { + "$ref": "#/components/schemas/CallHookAssistantSpeechInterrupted", + "title": "CallHookAssistantSpeechInterrupted" + }, + { + "$ref": "#/components/schemas/CallHookCustomerSpeechInterrupted", + "title": "CallHookCustomerSpeechInterrupted" + }, + { + "$ref": "#/components/schemas/CallHookCustomerSpeechTimeout", + "title": "CallHookCustomerSpeechTimeout" + }, + { + "$ref": "#/components/schemas/SessionCreatedHook", + "title": "SessionCreatedHook" + } + ] + } + }, + "name": { + "type": "string", + "description": "This is the name of the assistant.\n\nThis is required when you want to transfer between assistants in a call.", + "maxLength": 40 + }, + "voicemailMessage": { + "type": "string", + "description": "This is the message that the assistant will say if the call is forwarded to voicemail.\n\nIf unspecified, it will hang up.", + "maxLength": 1000 + }, + "endCallMessage": { + "type": "string", + "description": "This is the message that the assistant will say if it ends the call.\n\nIf unspecified, it will hang up without saying anything.", + "maxLength": 1000 + }, + "endCallPhrases": { + "description": "This list contains phrases that, if spoken by the assistant, will trigger the call to be hung up. Case insensitive.", + "type": "array", + "items": { + "type": "string", + "maxLength": 140, + "minLength": 2 + } + }, + "compliancePlan": { + "$ref": "#/components/schemas/CompliancePlan" + }, + "metadata": { + "type": "object", + "description": "This is for metadata you want to store on the assistant." + }, + "backgroundSpeechDenoisingPlan": { + "description": "This enables filtering of noise and background speech while the user is talking.\n\nFeatures:\n- Smart denoising using Krisp\n- Fourier denoising\n\nSmart denoising can be combined with or used independently of Fourier denoising.\n\nOrder of precedence:\n- Smart denoising\n- Fourier denoising", + "allOf": [ + { + "$ref": "#/components/schemas/BackgroundSpeechDenoisingPlan" + } + ] + }, + "analysisPlan": { + "description": "This is the plan for analysis of assistant's calls. Stored in `call.analysis`.", + "deprecated": true, + "allOf": [ + { + "$ref": "#/components/schemas/AnalysisPlan" + } + ] + }, + "artifactPlan": { + "description": "This is the plan for artifacts generated during assistant's calls. Stored in `call.artifact`.", + "allOf": [ + { + "$ref": "#/components/schemas/ArtifactPlan" + } + ] + }, + "startSpeakingPlan": { + "description": "This is the plan for when the assistant should start talking.\n\nYou should configure this if you're running into these issues:\n- The assistant is too slow to start talking after the customer is done speaking.\n- The assistant is too fast to start talking after the customer is done speaking.\n- The assistant is so fast that it's actually interrupting the customer.", + "allOf": [ + { + "$ref": "#/components/schemas/StartSpeakingPlan" + } + ] + }, + "stopSpeakingPlan": { + "description": "This is the plan for when assistant should stop talking on customer interruption.\n\nYou should configure this if you're running into these issues:\n- The assistant is too slow to recognize customer's interruption.\n- The assistant is too fast to recognize customer's interruption.\n- The assistant is getting interrupted by phrases that are just acknowledgments.\n- The assistant is getting interrupted by background noises.\n- The assistant is not properly stopping -- it starts talking right after getting interrupted.", + "allOf": [ + { + "$ref": "#/components/schemas/StopSpeakingPlan" + } + ] + }, + "monitorPlan": { + "description": "This is the plan for real-time monitoring of the assistant's calls.\n\nUsage:\n- To enable live listening of the assistant's calls, set `monitorPlan.listenEnabled` to `true`.\n- To enable live control of the assistant's calls, set `monitorPlan.controlEnabled` to `true`.\n- To attach monitors to the assistant, set `monitorPlan.monitorIds` to the set of monitor ids.", + "allOf": [ + { + "$ref": "#/components/schemas/MonitorPlan" + } + ] + }, + "credentialIds": { + "description": "These are the credentials that will be used for the assistant calls. By default, all the credentials are available for use in the call but you can provide a subset using this.", + "type": "array", + "items": { + "type": "string" + } + }, + "server": { + "description": "This is where Vapi will send webhooks. You can find all webhooks available along with their shape in ServerMessage schema.\n\nThe order of precedence is:\n\n1. assistant.server.url\n2. phoneNumber.serverUrl\n3. org.serverUrl", + "allOf": [ + { + "$ref": "#/components/schemas/Server" + } + ] + }, + "keypadInputPlan": { + "$ref": "#/components/schemas/KeypadInputPlan" + }, + "baseVersion": { + "type": "string", + "description": "Optional pointer to the published version this draft was forked from.\nWhen omitted on `POST /assistant/:id/draft`, defaults server-side to the\nparent assistant's current `latestVersion` (which is lazy-created via\n`assistantBaselineVersionEnsureInTx` if the parent has never been\nversioned). Immutable for the lifetime of the draft." + } + } + }, + "AssistantDraftConflictResponseDTO": { + "type": "object", + "properties": { + "existingDraftId": { + "type": "string", + "nullable": true + }, + "error": { + "type": "string" + }, + "message": { + "type": "string" + } + }, + "required": [ + "existingDraftId", + "error", + "message" + ] + }, + "UpdateAssistantDraftDTO": { + "type": "object", + "properties": { + "transcriber": { + "description": "These are the options for the assistant's transcriber.", + "oneOf": [ + { + "$ref": "#/components/schemas/AssemblyAITranscriber", + "title": "AssemblyAITranscriber" + }, + { + "$ref": "#/components/schemas/AzureSpeechTranscriber", + "title": "AzureSpeechTranscriber" + }, + { + "$ref": "#/components/schemas/CustomTranscriber", + "title": "CustomTranscriber" + }, + { + "$ref": "#/components/schemas/DeepgramTranscriber", + "title": "DeepgramTranscriber" + }, + { + "$ref": "#/components/schemas/ElevenLabsTranscriber", + "title": "ElevenLabsTranscriber" + }, + { + "$ref": "#/components/schemas/GladiaTranscriber", + "title": "GladiaTranscriber" + }, + { + "$ref": "#/components/schemas/GoogleTranscriber", + "title": "GoogleTranscriber" + }, + { + "$ref": "#/components/schemas/SpeechmaticsTranscriber", + "title": "SpeechmaticsTranscriber" + }, + { + "$ref": "#/components/schemas/TalkscriberTranscriber", + "title": "TalkscriberTranscriber" + }, + { + "$ref": "#/components/schemas/OpenAITranscriber", + "title": "OpenAITranscriber" + }, + { + "$ref": "#/components/schemas/CartesiaTranscriber", + "title": "CartesiaTranscriber" + }, + { + "$ref": "#/components/schemas/SonioxTranscriber", + "title": "SonioxTranscriber" + }, + { + "$ref": "#/components/schemas/XaiTranscriber", + "title": "XaiTranscriber" + }, + { + "$ref": "#/components/schemas/VapiTranscriber", + "title": "VapiTranscriber" + } + ] + }, + "model": { + "description": "These are the options for the assistant's LLM.", + "oneOf": [ + { + "$ref": "#/components/schemas/AnthropicModel", + "title": "Anthropic" + }, + { + "$ref": "#/components/schemas/AnthropicBedrockModel", + "title": "AnthropicBedrock" + }, + { + "$ref": "#/components/schemas/AnyscaleModel", + "title": "Anyscale" + }, + { + "$ref": "#/components/schemas/CerebrasModel", + "title": "Cerebras" + }, + { + "$ref": "#/components/schemas/CustomLLMModel", + "title": "CustomLLM" + }, + { + "$ref": "#/components/schemas/DeepInfraModel", + "title": "DeepInfra" + }, + { + "$ref": "#/components/schemas/DeepSeekModel", + "title": "DeepSeek" + }, + { + "$ref": "#/components/schemas/GoogleModel", + "title": "Google" + }, + { + "$ref": "#/components/schemas/GroqModel", + "title": "Groq" + }, + { + "$ref": "#/components/schemas/InflectionAIModel", + "title": "InflectionAI" + }, + { + "$ref": "#/components/schemas/MinimaxLLMModel", + "title": "MiniMaxLLM" + }, + { + "$ref": "#/components/schemas/OpenAIModel", + "title": "OpenAI" + }, + { + "$ref": "#/components/schemas/OpenRouterModel", + "title": "OpenRouter" + }, + { + "$ref": "#/components/schemas/PerplexityAIModel", + "title": "PerplexityAI" + }, + { + "$ref": "#/components/schemas/TogetherAIModel", + "title": "Together" + }, + { + "$ref": "#/components/schemas/XaiModel", + "title": "XAI" + }, + { + "$ref": "#/components/schemas/VapiModel", + "title": "Vapi" + } + ] + }, + "voice": { + "description": "These are the options for the assistant's voice.", + "oneOf": [ + { + "$ref": "#/components/schemas/AzureVoice", + "title": "AzureVoice" + }, + { + "$ref": "#/components/schemas/CartesiaVoice", + "title": "CartesiaVoice" + }, + { + "$ref": "#/components/schemas/CustomVoice", + "title": "CustomVoice" + }, + { + "$ref": "#/components/schemas/DeepgramVoice", + "title": "DeepgramVoice" + }, + { + "$ref": "#/components/schemas/ElevenLabsVoice", + "title": "ElevenLabsVoice" + }, + { + "$ref": "#/components/schemas/HumeVoice", + "title": "HumeVoice" + }, + { + "$ref": "#/components/schemas/LMNTVoice", + "title": "LMNTVoice" + }, + { + "$ref": "#/components/schemas/NeuphonicVoice", + "title": "NeuphonicVoice" + }, + { + "$ref": "#/components/schemas/OpenAIVoice", + "title": "OpenAIVoice" + }, + { + "$ref": "#/components/schemas/PlayHTVoice", + "title": "PlayHTVoice" + }, + { + "$ref": "#/components/schemas/WellSaidVoice", + "title": "WellSaidVoice" + }, + { + "$ref": "#/components/schemas/RimeAIVoice", + "title": "RimeAIVoice" + }, + { + "$ref": "#/components/schemas/SmallestAIVoice", + "title": "SmallestAIVoice" + }, + { + "$ref": "#/components/schemas/TavusVoice", + "title": "TavusVoice" + }, + { + "$ref": "#/components/schemas/VapiVoice", + "title": "VapiVoice" + }, + { + "$ref": "#/components/schemas/SesameVoice", + "title": "SesameVoice" + }, + { + "$ref": "#/components/schemas/InworldVoice", + "title": "InworldVoice" + }, + { + "$ref": "#/components/schemas/MinimaxVoice", + "title": "MinimaxVoice" + }, + { + "$ref": "#/components/schemas/XaiVoice", + "title": "XaiVoice" + }, + { + "$ref": "#/components/schemas/MicrosoftVoice", + "title": "MicrosoftVoice" + } + ] + }, + "firstMessage": { + "type": "string", + "description": "This is the first message that the assistant will say. This can also be a URL to a containerized audio file (mp3, wav, etc.).\n\nIf unspecified, assistant will wait for user to speak and use the model to respond once they speak.", + "example": "Hello! How can I help you today?" + }, + "firstMessageInterruptionsEnabled": { + "type": "boolean", + "default": false + }, + "firstMessageMode": { + "type": "string", + "description": "This is the mode for the first message. Default is 'assistant-speaks-first'.\n\nUse:\n- 'assistant-speaks-first' to have the assistant speak first.\n- 'assistant-waits-for-user' to have the assistant wait for the user to speak first.\n- 'assistant-speaks-first-with-model-generated-message' to have the assistant speak first with a message generated by the model based on the conversation state. (`assistant.model.messages` at call start, `call.messages` at squad transfer points).\n\n@default 'assistant-speaks-first'", + "enum": [ + "assistant-speaks-first", + "assistant-speaks-first-with-model-generated-message", + "assistant-waits-for-user" + ], + "example": "assistant-speaks-first" + }, + "voicemailDetection": { + "description": "These are the settings to configure or disable voicemail detection. Alternatively, voicemail detection can be configured using the model.tools=[VoicemailTool].\nBy default, voicemail detection is disabled.", + "oneOf": [ + { + "type": "string", + "enum": [ + "off" + ] + }, + { + "$ref": "#/components/schemas/GoogleVoicemailDetectionPlan", + "title": "Google" + }, + { + "$ref": "#/components/schemas/OpenAIVoicemailDetectionPlan", + "title": "OpenAI" + }, + { + "$ref": "#/components/schemas/TwilioVoicemailDetectionPlan", + "title": "Twilio" + }, + { + "$ref": "#/components/schemas/VapiVoicemailDetectionPlan", + "title": "Vapi" + } + ] + }, + "clientMessages": { + "type": "array", + "enum": [ + "conversation-update", + "assistant.speechStarted", + "function-call", + "function-call-result", + "hang", + "language-changed", + "metadata", + "model-output", + "speech-update", + "status-update", + "transcript", + "tool-calls", + "tool-calls-result", + "tool.completed", + "transfer-update", + "user-interrupted", + "voice-input", + "workflow.node.started", + "assistant.started" + ], + "example": [ + "conversation-update", + "function-call", + "hang", + "model-output", + "speech-update", + "status-update", + "transfer-update", + "transcript", + "tool-calls", + "user-interrupted", + "voice-input", + "workflow.node.started", + "assistant.started" + ], + "description": "These are the messages that will be sent to your Client SDKs. Default is conversation-update,function-call,hang,model-output,speech-update,status-update,transfer-update,transcript,tool-calls,user-interrupted,voice-input,workflow.node.started,assistant.started. You can check the shape of the messages in ClientMessage schema.", + "items": { + "type": "string", + "enum": [ + "conversation-update", + "assistant.speechStarted", + "function-call", + "function-call-result", + "hang", + "language-changed", + "metadata", + "model-output", + "speech-update", + "status-update", + "transcript", + "tool-calls", + "tool-calls-result", + "tool.completed", + "transfer-update", + "user-interrupted", + "voice-input", + "workflow.node.started", + "assistant.started" + ] + } + }, + "serverMessages": { + "type": "array", + "enum": [ + "assistant.started", + "assistant.speechStarted", + "conversation-update", + "end-of-call-report", + "function-call", + "hang", + "language-changed", + "language-change-detected", + "model-output", + "phone-call-control", + "speech-update", + "status-update", + "transcript", + "transcript[transcriptType=\"final\"]", + "tool-calls", + "transfer-destination-request", + "handoff-destination-request", + "transfer-update", + "user-interrupted", + "voice-input", + "chat.created", + "chat.deleted", + "session.created", + "session.updated", + "session.deleted", + "call.deleted", + "call.delete.failed", + "call.artifact.upload" + ], + "example": [ + "conversation-update", + "end-of-call-report", + "function-call", + "hang", + "speech-update", + "status-update", + "tool-calls", + "transfer-destination-request", + "handoff-destination-request", + "user-interrupted", + "assistant.started" + ], + "description": "These are the messages that will be sent to your Server URL. Default is conversation-update,end-of-call-report,function-call,hang,speech-update,status-update,tool-calls,transfer-destination-request,handoff-destination-request,user-interrupted,assistant.started. You can check the shape of the messages in ServerMessage schema.", + "items": { + "type": "string", + "enum": [ + "assistant.started", + "assistant.speechStarted", + "conversation-update", + "end-of-call-report", + "function-call", + "hang", + "language-changed", + "language-change-detected", + "model-output", + "phone-call-control", + "speech-update", + "status-update", + "transcript", + "transcript[transcriptType=\"final\"]", + "tool-calls", + "transfer-destination-request", + "handoff-destination-request", + "transfer-update", + "user-interrupted", + "voice-input", + "chat.created", + "chat.deleted", + "session.created", + "session.updated", + "session.deleted", + "call.deleted", + "call.delete.failed", + "call.artifact.upload" + ] + } + }, + "maxDurationSeconds": { + "type": "number", + "description": "This is the maximum number of seconds that the call will last. When the call reaches this duration, it will be ended.\n\n@default 600 (10 minutes)", + "minimum": 10, + "maximum": 43200, + "example": 600 + }, + "backgroundSound": { + "description": "This is the background sound in the call. Default for phone calls is 'office' and default for web calls is 'off'.\nYou can also provide a custom sound by providing a URL to an audio file.", + "oneOf": [ + { + "type": "string", + "enum": [ + "off", + "office" + ], + "example": "office" + }, + { + "type": "string", + "format": "uri", + "example": "https://www.soundjay.com/ambient/sounds/people-in-lounge-1.mp3" + } + ] + }, + "modelOutputInMessagesEnabled": { + "type": "boolean", + "description": "This determines whether the model's output is used in conversation history rather than the transcription of assistant's speech.\n\n@default false", + "example": false + }, + "transportConfigurations": { + "type": "array", + "description": "These are the configurations to be passed to the transport providers of assistant's calls, like Twilio. You can store multiple configurations for different transport providers. For a call, only the configuration matching the call transport provider is used.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/TransportConfigurationTwilio", + "title": "Twilio" + } + ] + } + }, + "observabilityPlan": { + "description": "This is the plan for observability of assistant's calls.\n\nCurrently, only Langfuse is supported.", + "oneOf": [ + { + "$ref": "#/components/schemas/LangfuseObservabilityPlan", + "title": "Langfuse" + } + ], + "allOf": [ + { + "$ref": "#/components/schemas/LangfuseObservabilityPlan" + } + ] + }, + "credentials": { + "type": "array", + "description": "These are dynamic credentials that will be used for the assistant calls. By default, all the credentials are available for use in the call but you can supplement an additional credentials using this. Dynamic credentials override existing credentials.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/CreateAnthropicCredentialDTO", + "title": "AnthropicCredential" + }, + { + "$ref": "#/components/schemas/CreateAnthropicBedrockCredentialDTO", + "title": "AnthropicBedrockCredential" + }, + { + "$ref": "#/components/schemas/CreateAnyscaleCredentialDTO", + "title": "AnyscaleCredential" + }, + { + "$ref": "#/components/schemas/CreateAssemblyAICredentialDTO", + "title": "AssemblyAICredential" + }, + { + "$ref": "#/components/schemas/CreateAzureCredentialDTO", + "title": "AzureCredential" + }, + { + "$ref": "#/components/schemas/CreateAzureOpenAICredentialDTO", + "title": "AzureOpenAICredential" + }, + { + "$ref": "#/components/schemas/CreateByoSipTrunkCredentialDTO", + "title": "ByoSipTrunkCredential" + }, + { + "$ref": "#/components/schemas/CreateCartesiaCredentialDTO", + "title": "CartesiaCredential" + }, + { + "$ref": "#/components/schemas/CreateCerebrasCredentialDTO", + "title": "CerebrasCredential" + }, + { + "$ref": "#/components/schemas/CreateCloudflareCredentialDTO", + "title": "CloudflareCredential" + }, + { + "$ref": "#/components/schemas/CreateCustomLLMCredentialDTO", + "title": "CustomLLMCredential" + }, + { + "$ref": "#/components/schemas/CreateDeepgramCredentialDTO", + "title": "DeepgramCredential" + }, + { + "$ref": "#/components/schemas/CreateDeepInfraCredentialDTO", + "title": "DeepInfraCredential" + }, + { + "$ref": "#/components/schemas/CreateDeepSeekCredentialDTO", + "title": "DeepSeekCredential" + }, + { + "$ref": "#/components/schemas/CreateElevenLabsCredentialDTO", + "title": "ElevenLabsCredential" + }, + { + "$ref": "#/components/schemas/CreateGcpCredentialDTO", + "title": "GcpCredential" + }, + { + "$ref": "#/components/schemas/CreateGladiaCredentialDTO", + "title": "GladiaCredential" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelCredentialDTO", + "title": "GhlCredential" + }, + { + "$ref": "#/components/schemas/CreateGoogleCredentialDTO", + "title": "GoogleCredential" + }, + { + "$ref": "#/components/schemas/CreateGroqCredentialDTO", + "title": "GroqCredential" + }, + { + "$ref": "#/components/schemas/CreateHumeCredentialDTO", + "title": "HumeCredential" + }, + { + "$ref": "#/components/schemas/CreateInflectionAICredentialDTO", + "title": "InflectionAICredential" + }, + { + "$ref": "#/components/schemas/CreateLangfuseCredentialDTO", + "title": "LangfuseCredential" + }, + { + "$ref": "#/components/schemas/CreateLmntCredentialDTO", + "title": "LmntCredential" + }, + { + "$ref": "#/components/schemas/CreateMakeCredentialDTO", + "title": "MakeCredential" + }, + { + "$ref": "#/components/schemas/CreateMistralCredentialDTO", + "title": "MistralCredential" + }, + { + "$ref": "#/components/schemas/CreateNeuphonicCredentialDTO", + "title": "NeuphonicCredential" + }, + { + "$ref": "#/components/schemas/CreateOpenAICredentialDTO", + "title": "OpenAICredential" + }, + { + "$ref": "#/components/schemas/CreateOpenRouterCredentialDTO", + "title": "OpenRouterCredential" + }, + { + "$ref": "#/components/schemas/CreatePerplexityAICredentialDTO", + "title": "PerplexityAICredential" + }, + { + "$ref": "#/components/schemas/CreatePlayHTCredentialDTO", + "title": "PlayHTCredential" + }, + { + "$ref": "#/components/schemas/CreateRimeAICredentialDTO", + "title": "RimeAICredential" + }, + { + "$ref": "#/components/schemas/CreateRunpodCredentialDTO", + "title": "RunpodCredential" + }, + { + "$ref": "#/components/schemas/CreateS3CredentialDTO", + "title": "S3Credential" + }, + { + "$ref": "#/components/schemas/CreateS3CompatibleCredentialDTO", + "title": "S3CompatibleStorageCredential" + }, + { + "$ref": "#/components/schemas/CreateSmallestAICredentialDTO", + "title": "SmallestAICredential" + }, + { + "$ref": "#/components/schemas/CreateSpeechmaticsCredentialDTO", + "title": "SpeechmaticsCredential" + }, + { + "$ref": "#/components/schemas/CreateSonioxCredentialDTO", + "title": "SonioxCredential" + }, + { + "$ref": "#/components/schemas/CreateSupabaseCredentialDTO", + "title": "SupabaseCredential" + }, + { + "$ref": "#/components/schemas/CreateTavusCredentialDTO", + "title": "TavusCredential" + }, + { + "$ref": "#/components/schemas/CreateTogetherAICredentialDTO", + "title": "TogetherAICredential" + }, + { + "$ref": "#/components/schemas/CreateTwilioCredentialDTO", + "title": "TwilioCredential" + }, + { + "$ref": "#/components/schemas/CreateVonageCredentialDTO", + "title": "VonageCredential" + }, + { + "$ref": "#/components/schemas/CreateWebhookCredentialDTO", + "title": "WebhookCredential" + }, + { + "$ref": "#/components/schemas/CreateCustomCredentialDTO", + "title": "CustomCredential" + }, + { + "$ref": "#/components/schemas/CreateXAiCredentialDTO", + "title": "XAiCredential" + }, + { + "$ref": "#/components/schemas/CreateMicrosoftCredentialDTO", + "title": "MicrosoftCredential" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarOAuth2ClientCredentialDTO", + "title": "GoogleCalendarOAuth2ClientCredential" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarOAuth2AuthorizationCredentialDTO", + "title": "GoogleCalendarOAuth2AuthorizationCredential" + }, + { + "$ref": "#/components/schemas/CreateGoogleSheetsOAuth2AuthorizationCredentialDTO", + "title": "GoogleSheetsOAuth2AuthorizationCredential" + }, + { + "$ref": "#/components/schemas/CreateSlackOAuth2AuthorizationCredentialDTO", + "title": "SlackOAuth2AuthorizationCredential" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelMCPCredentialDTO", + "title": "GoHighLevelMCPCredential" + }, + { + "$ref": "#/components/schemas/CreateInworldCredentialDTO", + "title": "InworldCredential" + }, + { + "$ref": "#/components/schemas/CreateMinimaxCredentialDTO", + "title": "MinimaxCredential" + }, + { + "$ref": "#/components/schemas/CreateWellSaidCredentialDTO", + "title": "WellSaidCredential" + }, + { + "$ref": "#/components/schemas/CreateEmailCredentialDTO", + "title": "EmailCredential" + }, + { + "$ref": "#/components/schemas/CreateSlackWebhookCredentialDTO", + "title": "SlackWebhookCredential" + } + ], + "discriminator": { + "propertyName": "provider", + "mapping": { + "11labs": "#/components/schemas/CreateElevenLabsCredentialDTO", + "anthropic": "#/components/schemas/CreateAnthropicCredentialDTO", + "anthropic-bedrock": "#/components/schemas/CreateAnthropicBedrockCredentialDTO", + "anyscale": "#/components/schemas/CreateAnyscaleCredentialDTO", + "assembly-ai": "#/components/schemas/CreateAssemblyAICredentialDTO", + "azure-openai": "#/components/schemas/CreateAzureOpenAICredentialDTO", + "azure": "#/components/schemas/CreateAzureCredentialDTO", + "byo-sip-trunk": "#/components/schemas/CreateByoSipTrunkCredentialDTO", + "cartesia": "#/components/schemas/CreateCartesiaCredentialDTO", + "cerebras": "#/components/schemas/CreateCerebrasCredentialDTO", + "cloudflare": "#/components/schemas/CreateCloudflareCredentialDTO", + "custom-llm": "#/components/schemas/CreateCustomLLMCredentialDTO", + "deepgram": "#/components/schemas/CreateDeepgramCredentialDTO", + "deepinfra": "#/components/schemas/CreateDeepInfraCredentialDTO", + "deep-seek": "#/components/schemas/CreateDeepSeekCredentialDTO", + "gcp": "#/components/schemas/CreateGcpCredentialDTO", + "gladia": "#/components/schemas/CreateGladiaCredentialDTO", + "gohighlevel": "#/components/schemas/CreateGoHighLevelCredentialDTO", + "google": "#/components/schemas/CreateGoogleCredentialDTO", + "groq": "#/components/schemas/CreateGroqCredentialDTO", + "inflection-ai": "#/components/schemas/CreateInflectionAICredentialDTO", + "langfuse": "#/components/schemas/CreateLangfuseCredentialDTO", + "lmnt": "#/components/schemas/CreateLmntCredentialDTO", + "make": "#/components/schemas/CreateMakeCredentialDTO", + "openai": "#/components/schemas/CreateOpenAICredentialDTO", + "openrouter": "#/components/schemas/CreateOpenRouterCredentialDTO", + "perplexity-ai": "#/components/schemas/CreatePerplexityAICredentialDTO", + "playht": "#/components/schemas/CreatePlayHTCredentialDTO", + "rime-ai": "#/components/schemas/CreateRimeAICredentialDTO", + "runpod": "#/components/schemas/CreateRunpodCredentialDTO", + "s3": "#/components/schemas/CreateS3CredentialDTO", + "s3-compatible": "#/components/schemas/CreateS3CompatibleCredentialDTO", + "supabase": "#/components/schemas/CreateSupabaseCredentialDTO", + "smallest-ai": "#/components/schemas/CreateSmallestAICredentialDTO", + "tavus": "#/components/schemas/CreateTavusCredentialDTO", + "together-ai": "#/components/schemas/CreateTogetherAICredentialDTO", + "twilio": "#/components/schemas/CreateTwilioCredentialDTO", + "vonage": "#/components/schemas/CreateVonageCredentialDTO", + "webhook": "#/components/schemas/CreateWebhookCredentialDTO", + "custom-credential": "#/components/schemas/CreateCustomCredentialDTO", + "xai": "#/components/schemas/CreateXAiCredentialDTO", + "microsoft": "#/components/schemas/CreateMicrosoftCredentialDTO", + "neuphonic": "#/components/schemas/CreateNeuphonicCredentialDTO", + "hume": "#/components/schemas/CreateHumeCredentialDTO", + "mistral": "#/components/schemas/CreateMistralCredentialDTO", + "speechmatics": "#/components/schemas/CreateSpeechmaticsCredentialDTO", + "soniox": "#/components/schemas/CreateSonioxCredentialDTO", + "google.calendar.oauth2-client": "#/components/schemas/CreateGoogleCalendarOAuth2ClientCredentialDTO", + "google.calendar.oauth2-authorization": "#/components/schemas/CreateGoogleCalendarOAuth2AuthorizationCredentialDTO", + "google.sheets.oauth2-authorization": "#/components/schemas/CreateGoogleSheetsOAuth2AuthorizationCredentialDTO", + "slack.oauth2-authorization": "#/components/schemas/CreateSlackOAuth2AuthorizationCredentialDTO", + "ghl.oauth2-authorization": "#/components/schemas/CreateGoHighLevelMCPCredentialDTO", + "inworld": "#/components/schemas/CreateInworldCredentialDTO", + "minimax": "#/components/schemas/CreateMinimaxCredentialDTO", + "wellsaid": "#/components/schemas/CreateWellSaidCredentialDTO", + "email": "#/components/schemas/CreateEmailCredentialDTO", + "slack-webhook": "#/components/schemas/CreateSlackWebhookCredentialDTO" + } + } + } + }, + "hooks": { + "type": "array", + "description": "This is a set of actions that will be performed on certain events.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/CallHookCallEnding", + "title": "CallHookCallEnding" + }, + { + "$ref": "#/components/schemas/CallHookAssistantSpeechInterrupted", + "title": "CallHookAssistantSpeechInterrupted" + }, + { + "$ref": "#/components/schemas/CallHookCustomerSpeechInterrupted", + "title": "CallHookCustomerSpeechInterrupted" + }, + { + "$ref": "#/components/schemas/CallHookCustomerSpeechTimeout", + "title": "CallHookCustomerSpeechTimeout" + }, + { + "$ref": "#/components/schemas/SessionCreatedHook", + "title": "SessionCreatedHook" + } + ] + } + }, + "name": { + "type": "string", + "description": "This is the name of the assistant.\n\nThis is required when you want to transfer between assistants in a call.", + "maxLength": 40 + }, + "voicemailMessage": { + "type": "string", + "description": "This is the message that the assistant will say if the call is forwarded to voicemail.\n\nIf unspecified, it will hang up.", + "maxLength": 1000 + }, + "endCallMessage": { + "type": "string", + "description": "This is the message that the assistant will say if it ends the call.\n\nIf unspecified, it will hang up without saying anything.", + "maxLength": 1000 + }, + "endCallPhrases": { + "description": "This list contains phrases that, if spoken by the assistant, will trigger the call to be hung up. Case insensitive.", + "type": "array", + "items": { + "type": "string", + "maxLength": 140, + "minLength": 2 + } + }, + "compliancePlan": { + "$ref": "#/components/schemas/CompliancePlan" + }, + "metadata": { + "type": "object", + "description": "This is for metadata you want to store on the assistant." + }, + "backgroundSpeechDenoisingPlan": { + "description": "This enables filtering of noise and background speech while the user is talking.\n\nFeatures:\n- Smart denoising using Krisp\n- Fourier denoising\n\nSmart denoising can be combined with or used independently of Fourier denoising.\n\nOrder of precedence:\n- Smart denoising\n- Fourier denoising", + "allOf": [ + { + "$ref": "#/components/schemas/BackgroundSpeechDenoisingPlan" + } + ] + }, + "analysisPlan": { + "description": "This is the plan for analysis of assistant's calls. Stored in `call.analysis`.", + "deprecated": true, + "allOf": [ + { + "$ref": "#/components/schemas/AnalysisPlan" + } + ] + }, + "artifactPlan": { + "description": "This is the plan for artifacts generated during assistant's calls. Stored in `call.artifact`.", + "allOf": [ + { + "$ref": "#/components/schemas/ArtifactPlan" + } + ] + }, + "startSpeakingPlan": { + "description": "This is the plan for when the assistant should start talking.\n\nYou should configure this if you're running into these issues:\n- The assistant is too slow to start talking after the customer is done speaking.\n- The assistant is too fast to start talking after the customer is done speaking.\n- The assistant is so fast that it's actually interrupting the customer.", + "allOf": [ + { + "$ref": "#/components/schemas/StartSpeakingPlan" + } + ] + }, + "stopSpeakingPlan": { + "description": "This is the plan for when assistant should stop talking on customer interruption.\n\nYou should configure this if you're running into these issues:\n- The assistant is too slow to recognize customer's interruption.\n- The assistant is too fast to recognize customer's interruption.\n- The assistant is getting interrupted by phrases that are just acknowledgments.\n- The assistant is getting interrupted by background noises.\n- The assistant is not properly stopping -- it starts talking right after getting interrupted.", + "allOf": [ + { + "$ref": "#/components/schemas/StopSpeakingPlan" + } + ] + }, + "monitorPlan": { + "description": "This is the plan for real-time monitoring of the assistant's calls.\n\nUsage:\n- To enable live listening of the assistant's calls, set `monitorPlan.listenEnabled` to `true`.\n- To enable live control of the assistant's calls, set `monitorPlan.controlEnabled` to `true`.\n- To attach monitors to the assistant, set `monitorPlan.monitorIds` to the set of monitor ids.", + "allOf": [ + { + "$ref": "#/components/schemas/MonitorPlan" + } + ] + }, + "credentialIds": { + "description": "These are the credentials that will be used for the assistant calls. By default, all the credentials are available for use in the call but you can provide a subset using this.", + "type": "array", + "items": { + "type": "string" + } + }, + "server": { + "description": "This is where Vapi will send webhooks. You can find all webhooks available along with their shape in ServerMessage schema.\n\nThe order of precedence is:\n\n1. assistant.server.url\n2. phoneNumber.serverUrl\n3. org.serverUrl", + "allOf": [ + { + "$ref": "#/components/schemas/Server" + } + ] + }, + "keypadInputPlan": { + "$ref": "#/components/schemas/KeypadInputPlan" + } + } + }, + "UpdateAssistantDTO": { + "type": "object", + "properties": { + "transcriber": { + "description": "These are the options for the assistant's transcriber.", + "oneOf": [ + { + "$ref": "#/components/schemas/AssemblyAITranscriber", + "title": "AssemblyAITranscriber" + }, + { + "$ref": "#/components/schemas/AzureSpeechTranscriber", + "title": "AzureSpeechTranscriber" + }, + { + "$ref": "#/components/schemas/CustomTranscriber", + "title": "CustomTranscriber" + }, + { + "$ref": "#/components/schemas/DeepgramTranscriber", + "title": "DeepgramTranscriber" + }, + { + "$ref": "#/components/schemas/ElevenLabsTranscriber", + "title": "ElevenLabsTranscriber" + }, + { + "$ref": "#/components/schemas/GladiaTranscriber", + "title": "GladiaTranscriber" + }, + { + "$ref": "#/components/schemas/GoogleTranscriber", + "title": "GoogleTranscriber" + }, + { + "$ref": "#/components/schemas/SpeechmaticsTranscriber", + "title": "SpeechmaticsTranscriber" + }, + { + "$ref": "#/components/schemas/TalkscriberTranscriber", + "title": "TalkscriberTranscriber" + }, + { + "$ref": "#/components/schemas/OpenAITranscriber", + "title": "OpenAITranscriber" + }, + { + "$ref": "#/components/schemas/CartesiaTranscriber", + "title": "CartesiaTranscriber" + }, + { + "$ref": "#/components/schemas/SonioxTranscriber", + "title": "SonioxTranscriber" + }, + { + "$ref": "#/components/schemas/XaiTranscriber", + "title": "XaiTranscriber" + }, + { + "$ref": "#/components/schemas/VapiTranscriber", + "title": "VapiTranscriber" + } + ] + }, + "model": { + "description": "These are the options for the assistant's LLM.", + "oneOf": [ + { + "$ref": "#/components/schemas/AnthropicModel", + "title": "Anthropic" + }, + { + "$ref": "#/components/schemas/AnthropicBedrockModel", + "title": "AnthropicBedrock" + }, + { + "$ref": "#/components/schemas/AnyscaleModel", + "title": "Anyscale" + }, + { + "$ref": "#/components/schemas/CerebrasModel", + "title": "Cerebras" + }, + { + "$ref": "#/components/schemas/CustomLLMModel", + "title": "CustomLLM" + }, + { + "$ref": "#/components/schemas/DeepInfraModel", + "title": "DeepInfra" + }, + { + "$ref": "#/components/schemas/DeepSeekModel", + "title": "DeepSeek" + }, + { + "$ref": "#/components/schemas/GoogleModel", + "title": "Google" + }, + { + "$ref": "#/components/schemas/GroqModel", + "title": "Groq" + }, + { + "$ref": "#/components/schemas/InflectionAIModel", + "title": "InflectionAI" + }, + { + "$ref": "#/components/schemas/MinimaxLLMModel", + "title": "MiniMaxLLM" + }, + { + "$ref": "#/components/schemas/OpenAIModel", + "title": "OpenAI" + }, + { + "$ref": "#/components/schemas/OpenRouterModel", + "title": "OpenRouter" + }, + { + "$ref": "#/components/schemas/PerplexityAIModel", + "title": "PerplexityAI" + }, + { + "$ref": "#/components/schemas/TogetherAIModel", + "title": "Together" + }, + { + "$ref": "#/components/schemas/XaiModel", + "title": "XAI" + }, + { + "$ref": "#/components/schemas/VapiModel", + "title": "Vapi" + } + ] + }, + "voice": { + "description": "These are the options for the assistant's voice.", + "oneOf": [ + { + "$ref": "#/components/schemas/AzureVoice", + "title": "AzureVoice" + }, + { + "$ref": "#/components/schemas/CartesiaVoice", + "title": "CartesiaVoice" + }, + { + "$ref": "#/components/schemas/CustomVoice", + "title": "CustomVoice" + }, + { + "$ref": "#/components/schemas/DeepgramVoice", + "title": "DeepgramVoice" + }, + { + "$ref": "#/components/schemas/ElevenLabsVoice", + "title": "ElevenLabsVoice" + }, + { + "$ref": "#/components/schemas/HumeVoice", + "title": "HumeVoice" + }, + { + "$ref": "#/components/schemas/LMNTVoice", + "title": "LMNTVoice" + }, + { + "$ref": "#/components/schemas/NeuphonicVoice", + "title": "NeuphonicVoice" + }, + { + "$ref": "#/components/schemas/OpenAIVoice", + "title": "OpenAIVoice" + }, + { + "$ref": "#/components/schemas/PlayHTVoice", + "title": "PlayHTVoice" + }, + { + "$ref": "#/components/schemas/WellSaidVoice", + "title": "WellSaidVoice" + }, + { + "$ref": "#/components/schemas/RimeAIVoice", + "title": "RimeAIVoice" + }, + { + "$ref": "#/components/schemas/SmallestAIVoice", + "title": "SmallestAIVoice" + }, + { + "$ref": "#/components/schemas/TavusVoice", + "title": "TavusVoice" + }, + { + "$ref": "#/components/schemas/VapiVoice", + "title": "VapiVoice" + }, + { + "$ref": "#/components/schemas/SesameVoice", + "title": "SesameVoice" + }, + { + "$ref": "#/components/schemas/InworldVoice", + "title": "InworldVoice" + }, + { + "$ref": "#/components/schemas/MinimaxVoice", + "title": "MinimaxVoice" + }, + { + "$ref": "#/components/schemas/XaiVoice", + "title": "XaiVoice" + }, + { + "$ref": "#/components/schemas/MicrosoftVoice", + "title": "MicrosoftVoice" + } + ] + }, + "firstMessage": { + "type": "string", + "description": "This is the first message that the assistant will say. This can also be a URL to a containerized audio file (mp3, wav, etc.).\n\nIf unspecified, assistant will wait for user to speak and use the model to respond once they speak.", + "example": "Hello! How can I help you today?" + }, + "firstMessageInterruptionsEnabled": { + "type": "boolean", + "default": false + }, + "firstMessageMode": { + "type": "string", + "description": "This is the mode for the first message. Default is 'assistant-speaks-first'.\n\nUse:\n- 'assistant-speaks-first' to have the assistant speak first.\n- 'assistant-waits-for-user' to have the assistant wait for the user to speak first.\n- 'assistant-speaks-first-with-model-generated-message' to have the assistant speak first with a message generated by the model based on the conversation state. (`assistant.model.messages` at call start, `call.messages` at squad transfer points).\n\n@default 'assistant-speaks-first'", + "enum": [ + "assistant-speaks-first", + "assistant-speaks-first-with-model-generated-message", + "assistant-waits-for-user" + ], + "example": "assistant-speaks-first" + }, + "voicemailDetection": { + "description": "These are the settings to configure or disable voicemail detection. Alternatively, voicemail detection can be configured using the model.tools=[VoicemailTool].\nBy default, voicemail detection is disabled.", + "oneOf": [ + { + "type": "string", + "enum": [ + "off" + ] + }, + { + "$ref": "#/components/schemas/GoogleVoicemailDetectionPlan", + "title": "Google" + }, + { + "$ref": "#/components/schemas/OpenAIVoicemailDetectionPlan", + "title": "OpenAI" + }, + { + "$ref": "#/components/schemas/TwilioVoicemailDetectionPlan", + "title": "Twilio" + }, + { + "$ref": "#/components/schemas/VapiVoicemailDetectionPlan", + "title": "Vapi" + } + ] + }, + "clientMessages": { + "type": "array", + "enum": [ + "conversation-update", + "assistant.speechStarted", + "function-call", + "function-call-result", + "hang", + "language-changed", + "metadata", + "model-output", + "speech-update", + "status-update", + "transcript", + "tool-calls", + "tool-calls-result", + "tool.completed", + "transfer-update", + "user-interrupted", + "voice-input", + "workflow.node.started", + "assistant.started" + ], + "example": [ + "conversation-update", + "function-call", + "hang", + "model-output", + "speech-update", + "status-update", + "transfer-update", + "transcript", + "tool-calls", + "user-interrupted", + "voice-input", + "workflow.node.started", + "assistant.started" + ], + "description": "These are the messages that will be sent to your Client SDKs. Default is conversation-update,function-call,hang,model-output,speech-update,status-update,transfer-update,transcript,tool-calls,user-interrupted,voice-input,workflow.node.started,assistant.started. You can check the shape of the messages in ClientMessage schema.", + "items": { + "type": "string", + "enum": [ + "conversation-update", + "assistant.speechStarted", + "function-call", + "function-call-result", + "hang", + "language-changed", + "metadata", + "model-output", + "speech-update", + "status-update", + "transcript", + "tool-calls", + "tool-calls-result", + "tool.completed", + "transfer-update", + "user-interrupted", + "voice-input", + "workflow.node.started", + "assistant.started" + ] + } + }, + "serverMessages": { + "type": "array", + "enum": [ + "assistant.started", + "assistant.speechStarted", + "conversation-update", + "end-of-call-report", + "function-call", + "hang", + "language-changed", + "language-change-detected", + "model-output", + "phone-call-control", + "speech-update", + "status-update", + "transcript", + "transcript[transcriptType=\"final\"]", + "tool-calls", + "transfer-destination-request", + "handoff-destination-request", + "transfer-update", + "user-interrupted", + "voice-input", + "chat.created", + "chat.deleted", + "session.created", + "session.updated", + "session.deleted", + "call.deleted", + "call.delete.failed", + "call.artifact.upload" + ], + "example": [ + "conversation-update", + "end-of-call-report", + "function-call", + "hang", + "speech-update", + "status-update", + "tool-calls", + "transfer-destination-request", + "handoff-destination-request", + "user-interrupted", + "assistant.started" + ], + "description": "These are the messages that will be sent to your Server URL. Default is conversation-update,end-of-call-report,function-call,hang,speech-update,status-update,tool-calls,transfer-destination-request,handoff-destination-request,user-interrupted,assistant.started. You can check the shape of the messages in ServerMessage schema.", + "items": { + "type": "string", + "enum": [ + "assistant.started", + "assistant.speechStarted", + "conversation-update", + "end-of-call-report", + "function-call", + "hang", + "language-changed", + "language-change-detected", + "model-output", + "phone-call-control", + "speech-update", + "status-update", + "transcript", + "transcript[transcriptType=\"final\"]", + "tool-calls", + "transfer-destination-request", + "handoff-destination-request", + "transfer-update", + "user-interrupted", + "voice-input", + "chat.created", + "chat.deleted", + "session.created", + "session.updated", + "session.deleted", + "call.deleted", + "call.delete.failed", + "call.artifact.upload" + ] + } + }, + "maxDurationSeconds": { + "type": "number", + "description": "This is the maximum number of seconds that the call will last. When the call reaches this duration, it will be ended.\n\n@default 600 (10 minutes)", + "minimum": 10, + "maximum": 43200, + "example": 600 + }, + "backgroundSound": { + "description": "This is the background sound in the call. Default for phone calls is 'office' and default for web calls is 'off'.\nYou can also provide a custom sound by providing a URL to an audio file.", + "oneOf": [ + { + "type": "string", + "enum": [ + "off", + "office" + ], + "example": "office" + }, + { + "type": "string", + "format": "uri", + "example": "https://www.soundjay.com/ambient/sounds/people-in-lounge-1.mp3" + } + ] + }, + "modelOutputInMessagesEnabled": { + "type": "boolean", + "description": "This determines whether the model's output is used in conversation history rather than the transcription of assistant's speech.\n\n@default false", + "example": false + }, + "transportConfigurations": { + "type": "array", + "description": "These are the configurations to be passed to the transport providers of assistant's calls, like Twilio. You can store multiple configurations for different transport providers. For a call, only the configuration matching the call transport provider is used.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/TransportConfigurationTwilio", + "title": "Twilio" + } + ] + } + }, + "observabilityPlan": { + "description": "This is the plan for observability of assistant's calls.\n\nCurrently, only Langfuse is supported.", + "oneOf": [ + { + "$ref": "#/components/schemas/LangfuseObservabilityPlan", + "title": "Langfuse" + } + ], + "allOf": [ + { + "$ref": "#/components/schemas/LangfuseObservabilityPlan" + } + ] + }, + "credentials": { + "type": "array", + "description": "These are dynamic credentials that will be used for the assistant calls. By default, all the credentials are available for use in the call but you can supplement an additional credentials using this. Dynamic credentials override existing credentials.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/CreateAnthropicCredentialDTO", + "title": "AnthropicCredential" + }, + { + "$ref": "#/components/schemas/CreateAnthropicBedrockCredentialDTO", + "title": "AnthropicBedrockCredential" + }, + { + "$ref": "#/components/schemas/CreateAnyscaleCredentialDTO", + "title": "AnyscaleCredential" + }, + { + "$ref": "#/components/schemas/CreateAssemblyAICredentialDTO", + "title": "AssemblyAICredential" + }, + { + "$ref": "#/components/schemas/CreateAzureCredentialDTO", + "title": "AzureCredential" + }, + { + "$ref": "#/components/schemas/CreateAzureOpenAICredentialDTO", + "title": "AzureOpenAICredential" + }, + { + "$ref": "#/components/schemas/CreateByoSipTrunkCredentialDTO", + "title": "ByoSipTrunkCredential" + }, + { + "$ref": "#/components/schemas/CreateCartesiaCredentialDTO", + "title": "CartesiaCredential" + }, + { + "$ref": "#/components/schemas/CreateCerebrasCredentialDTO", + "title": "CerebrasCredential" + }, + { + "$ref": "#/components/schemas/CreateCloudflareCredentialDTO", + "title": "CloudflareCredential" + }, + { + "$ref": "#/components/schemas/CreateCustomLLMCredentialDTO", + "title": "CustomLLMCredential" + }, + { + "$ref": "#/components/schemas/CreateDeepgramCredentialDTO", + "title": "DeepgramCredential" + }, + { + "$ref": "#/components/schemas/CreateDeepInfraCredentialDTO", + "title": "DeepInfraCredential" + }, + { + "$ref": "#/components/schemas/CreateDeepSeekCredentialDTO", + "title": "DeepSeekCredential" + }, + { + "$ref": "#/components/schemas/CreateElevenLabsCredentialDTO", + "title": "ElevenLabsCredential" + }, + { + "$ref": "#/components/schemas/CreateGcpCredentialDTO", + "title": "GcpCredential" + }, + { + "$ref": "#/components/schemas/CreateGladiaCredentialDTO", + "title": "GladiaCredential" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelCredentialDTO", + "title": "GhlCredential" + }, + { + "$ref": "#/components/schemas/CreateGoogleCredentialDTO", + "title": "GoogleCredential" + }, + { + "$ref": "#/components/schemas/CreateGroqCredentialDTO", + "title": "GroqCredential" + }, + { + "$ref": "#/components/schemas/CreateHumeCredentialDTO", + "title": "HumeCredential" + }, + { + "$ref": "#/components/schemas/CreateInflectionAICredentialDTO", + "title": "InflectionAICredential" + }, + { + "$ref": "#/components/schemas/CreateLangfuseCredentialDTO", + "title": "LangfuseCredential" + }, + { + "$ref": "#/components/schemas/CreateLmntCredentialDTO", + "title": "LmntCredential" + }, + { + "$ref": "#/components/schemas/CreateMakeCredentialDTO", + "title": "MakeCredential" + }, + { + "$ref": "#/components/schemas/CreateMistralCredentialDTO", + "title": "MistralCredential" + }, + { + "$ref": "#/components/schemas/CreateNeuphonicCredentialDTO", + "title": "NeuphonicCredential" + }, + { + "$ref": "#/components/schemas/CreateOpenAICredentialDTO", + "title": "OpenAICredential" + }, + { + "$ref": "#/components/schemas/CreateOpenRouterCredentialDTO", + "title": "OpenRouterCredential" + }, + { + "$ref": "#/components/schemas/CreatePerplexityAICredentialDTO", + "title": "PerplexityAICredential" + }, + { + "$ref": "#/components/schemas/CreatePlayHTCredentialDTO", + "title": "PlayHTCredential" + }, + { + "$ref": "#/components/schemas/CreateRimeAICredentialDTO", + "title": "RimeAICredential" + }, + { + "$ref": "#/components/schemas/CreateRunpodCredentialDTO", + "title": "RunpodCredential" + }, + { + "$ref": "#/components/schemas/CreateS3CredentialDTO", + "title": "S3Credential" + }, + { + "$ref": "#/components/schemas/CreateS3CompatibleCredentialDTO", + "title": "S3CompatibleStorageCredential" + }, + { + "$ref": "#/components/schemas/CreateSmallestAICredentialDTO", + "title": "SmallestAICredential" + }, + { + "$ref": "#/components/schemas/CreateSpeechmaticsCredentialDTO", + "title": "SpeechmaticsCredential" + }, + { + "$ref": "#/components/schemas/CreateSonioxCredentialDTO", + "title": "SonioxCredential" + }, + { + "$ref": "#/components/schemas/CreateSupabaseCredentialDTO", + "title": "SupabaseCredential" + }, + { + "$ref": "#/components/schemas/CreateTavusCredentialDTO", + "title": "TavusCredential" + }, + { + "$ref": "#/components/schemas/CreateTogetherAICredentialDTO", + "title": "TogetherAICredential" + }, + { + "$ref": "#/components/schemas/CreateTwilioCredentialDTO", + "title": "TwilioCredential" + }, + { + "$ref": "#/components/schemas/CreateVonageCredentialDTO", + "title": "VonageCredential" + }, + { + "$ref": "#/components/schemas/CreateWebhookCredentialDTO", + "title": "WebhookCredential" + }, + { + "$ref": "#/components/schemas/CreateCustomCredentialDTO", + "title": "CustomCredential" + }, + { + "$ref": "#/components/schemas/CreateXAiCredentialDTO", + "title": "XAiCredential" + }, + { + "$ref": "#/components/schemas/CreateMicrosoftCredentialDTO", + "title": "MicrosoftCredential" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarOAuth2ClientCredentialDTO", + "title": "GoogleCalendarOAuth2ClientCredential" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarOAuth2AuthorizationCredentialDTO", + "title": "GoogleCalendarOAuth2AuthorizationCredential" + }, + { + "$ref": "#/components/schemas/CreateGoogleSheetsOAuth2AuthorizationCredentialDTO", + "title": "GoogleSheetsOAuth2AuthorizationCredential" + }, + { + "$ref": "#/components/schemas/CreateSlackOAuth2AuthorizationCredentialDTO", + "title": "SlackOAuth2AuthorizationCredential" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelMCPCredentialDTO", + "title": "GoHighLevelMCPCredential" + }, + { + "$ref": "#/components/schemas/CreateInworldCredentialDTO", + "title": "InworldCredential" + }, + { + "$ref": "#/components/schemas/CreateMinimaxCredentialDTO", + "title": "MinimaxCredential" + }, + { + "$ref": "#/components/schemas/CreateWellSaidCredentialDTO", + "title": "WellSaidCredential" + }, + { + "$ref": "#/components/schemas/CreateEmailCredentialDTO", + "title": "EmailCredential" + }, + { + "$ref": "#/components/schemas/CreateSlackWebhookCredentialDTO", + "title": "SlackWebhookCredential" + } + ], + "discriminator": { + "propertyName": "provider", + "mapping": { + "11labs": "#/components/schemas/CreateElevenLabsCredentialDTO", + "anthropic": "#/components/schemas/CreateAnthropicCredentialDTO", + "anthropic-bedrock": "#/components/schemas/CreateAnthropicBedrockCredentialDTO", + "anyscale": "#/components/schemas/CreateAnyscaleCredentialDTO", + "assembly-ai": "#/components/schemas/CreateAssemblyAICredentialDTO", + "azure-openai": "#/components/schemas/CreateAzureOpenAICredentialDTO", + "azure": "#/components/schemas/CreateAzureCredentialDTO", + "byo-sip-trunk": "#/components/schemas/CreateByoSipTrunkCredentialDTO", + "cartesia": "#/components/schemas/CreateCartesiaCredentialDTO", + "cerebras": "#/components/schemas/CreateCerebrasCredentialDTO", + "cloudflare": "#/components/schemas/CreateCloudflareCredentialDTO", + "custom-llm": "#/components/schemas/CreateCustomLLMCredentialDTO", + "deepgram": "#/components/schemas/CreateDeepgramCredentialDTO", + "deepinfra": "#/components/schemas/CreateDeepInfraCredentialDTO", + "deep-seek": "#/components/schemas/CreateDeepSeekCredentialDTO", + "gcp": "#/components/schemas/CreateGcpCredentialDTO", + "gladia": "#/components/schemas/CreateGladiaCredentialDTO", + "gohighlevel": "#/components/schemas/CreateGoHighLevelCredentialDTO", + "google": "#/components/schemas/CreateGoogleCredentialDTO", + "groq": "#/components/schemas/CreateGroqCredentialDTO", + "inflection-ai": "#/components/schemas/CreateInflectionAICredentialDTO", + "langfuse": "#/components/schemas/CreateLangfuseCredentialDTO", + "lmnt": "#/components/schemas/CreateLmntCredentialDTO", + "make": "#/components/schemas/CreateMakeCredentialDTO", + "openai": "#/components/schemas/CreateOpenAICredentialDTO", + "openrouter": "#/components/schemas/CreateOpenRouterCredentialDTO", + "perplexity-ai": "#/components/schemas/CreatePerplexityAICredentialDTO", + "playht": "#/components/schemas/CreatePlayHTCredentialDTO", + "rime-ai": "#/components/schemas/CreateRimeAICredentialDTO", + "runpod": "#/components/schemas/CreateRunpodCredentialDTO", + "s3": "#/components/schemas/CreateS3CredentialDTO", + "s3-compatible": "#/components/schemas/CreateS3CompatibleCredentialDTO", + "supabase": "#/components/schemas/CreateSupabaseCredentialDTO", + "smallest-ai": "#/components/schemas/CreateSmallestAICredentialDTO", + "tavus": "#/components/schemas/CreateTavusCredentialDTO", + "together-ai": "#/components/schemas/CreateTogetherAICredentialDTO", + "twilio": "#/components/schemas/CreateTwilioCredentialDTO", + "vonage": "#/components/schemas/CreateVonageCredentialDTO", + "webhook": "#/components/schemas/CreateWebhookCredentialDTO", + "custom-credential": "#/components/schemas/CreateCustomCredentialDTO", + "xai": "#/components/schemas/CreateXAiCredentialDTO", + "microsoft": "#/components/schemas/CreateMicrosoftCredentialDTO", + "neuphonic": "#/components/schemas/CreateNeuphonicCredentialDTO", + "hume": "#/components/schemas/CreateHumeCredentialDTO", + "mistral": "#/components/schemas/CreateMistralCredentialDTO", + "speechmatics": "#/components/schemas/CreateSpeechmaticsCredentialDTO", + "soniox": "#/components/schemas/CreateSonioxCredentialDTO", + "google.calendar.oauth2-client": "#/components/schemas/CreateGoogleCalendarOAuth2ClientCredentialDTO", + "google.calendar.oauth2-authorization": "#/components/schemas/CreateGoogleCalendarOAuth2AuthorizationCredentialDTO", + "google.sheets.oauth2-authorization": "#/components/schemas/CreateGoogleSheetsOAuth2AuthorizationCredentialDTO", + "slack.oauth2-authorization": "#/components/schemas/CreateSlackOAuth2AuthorizationCredentialDTO", + "ghl.oauth2-authorization": "#/components/schemas/CreateGoHighLevelMCPCredentialDTO", + "inworld": "#/components/schemas/CreateInworldCredentialDTO", + "minimax": "#/components/schemas/CreateMinimaxCredentialDTO", + "wellsaid": "#/components/schemas/CreateWellSaidCredentialDTO", + "email": "#/components/schemas/CreateEmailCredentialDTO", + "slack-webhook": "#/components/schemas/CreateSlackWebhookCredentialDTO" + } + } + } + }, + "hooks": { + "type": "array", + "description": "This is a set of actions that will be performed on certain events.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/CallHookCallEnding", + "title": "CallHookCallEnding" + }, + { + "$ref": "#/components/schemas/CallHookAssistantSpeechInterrupted", + "title": "CallHookAssistantSpeechInterrupted" + }, + { + "$ref": "#/components/schemas/CallHookCustomerSpeechInterrupted", + "title": "CallHookCustomerSpeechInterrupted" + }, + { + "$ref": "#/components/schemas/CallHookCustomerSpeechTimeout", + "title": "CallHookCustomerSpeechTimeout" + }, + { + "$ref": "#/components/schemas/SessionCreatedHook", + "title": "SessionCreatedHook" + } + ] + } + }, + "name": { + "type": "string", + "description": "This is the name of the assistant.\n\nThis is required when you want to transfer between assistants in a call.", + "maxLength": 40 + }, + "voicemailMessage": { + "type": "string", + "description": "This is the message that the assistant will say if the call is forwarded to voicemail.\n\nIf unspecified, it will hang up.", + "maxLength": 1000 + }, + "endCallMessage": { + "type": "string", + "description": "This is the message that the assistant will say if it ends the call.\n\nIf unspecified, it will hang up without saying anything.", + "maxLength": 1000 + }, + "endCallPhrases": { + "description": "This list contains phrases that, if spoken by the assistant, will trigger the call to be hung up. Case insensitive.", + "type": "array", + "items": { + "type": "string", + "maxLength": 140, + "minLength": 2 + } + }, + "compliancePlan": { + "$ref": "#/components/schemas/CompliancePlan" + }, + "metadata": { + "type": "object", + "description": "This is for metadata you want to store on the assistant." + }, + "backgroundSpeechDenoisingPlan": { + "description": "This enables filtering of noise and background speech while the user is talking.\n\nFeatures:\n- Smart denoising using Krisp\n- Fourier denoising\n\nSmart denoising can be combined with or used independently of Fourier denoising.\n\nOrder of precedence:\n- Smart denoising\n- Fourier denoising", + "allOf": [ + { + "$ref": "#/components/schemas/BackgroundSpeechDenoisingPlan" + } + ] + }, + "analysisPlan": { + "description": "This is the plan for analysis of assistant's calls. Stored in `call.analysis`.", + "deprecated": true, + "allOf": [ + { + "$ref": "#/components/schemas/AnalysisPlan" + } + ] + }, + "artifactPlan": { + "description": "This is the plan for artifacts generated during assistant's calls. Stored in `call.artifact`.", + "allOf": [ + { + "$ref": "#/components/schemas/ArtifactPlan" + } + ] + }, + "startSpeakingPlan": { + "description": "This is the plan for when the assistant should start talking.\n\nYou should configure this if you're running into these issues:\n- The assistant is too slow to start talking after the customer is done speaking.\n- The assistant is too fast to start talking after the customer is done speaking.\n- The assistant is so fast that it's actually interrupting the customer.", + "allOf": [ + { + "$ref": "#/components/schemas/StartSpeakingPlan" + } + ] + }, + "stopSpeakingPlan": { + "description": "This is the plan for when assistant should stop talking on customer interruption.\n\nYou should configure this if you're running into these issues:\n- The assistant is too slow to recognize customer's interruption.\n- The assistant is too fast to recognize customer's interruption.\n- The assistant is getting interrupted by phrases that are just acknowledgments.\n- The assistant is getting interrupted by background noises.\n- The assistant is not properly stopping -- it starts talking right after getting interrupted.", + "allOf": [ + { + "$ref": "#/components/schemas/StopSpeakingPlan" + } + ] + }, + "monitorPlan": { + "description": "This is the plan for real-time monitoring of the assistant's calls.\n\nUsage:\n- To enable live listening of the assistant's calls, set `monitorPlan.listenEnabled` to `true`.\n- To enable live control of the assistant's calls, set `monitorPlan.controlEnabled` to `true`.\n- To attach monitors to the assistant, set `monitorPlan.monitorIds` to the set of monitor ids.", + "allOf": [ + { + "$ref": "#/components/schemas/MonitorPlan" + } + ] + }, + "credentialIds": { + "description": "These are the credentials that will be used for the assistant calls. By default, all the credentials are available for use in the call but you can provide a subset using this.", + "type": "array", + "items": { + "type": "string" + } + }, + "server": { + "description": "This is where Vapi will send webhooks. You can find all webhooks available along with their shape in ServerMessage schema.\n\nThe order of precedence is:\n\n1. assistant.server.url\n2. phoneNumber.serverUrl\n3. org.serverUrl", + "allOf": [ + { + "$ref": "#/components/schemas/Server" + } + ] + }, + "keypadInputPlan": { + "$ref": "#/components/schemas/KeypadInputPlan" + } + } + }, + "AssistantPinnedConflictResponseDTO": { + "type": "object", + "properties": { + "error": { + "type": "string", + "enum": [ + "assistant_pinned" + ] + }, + "message": { + "type": "string", + "description": "Human-readable reason the parent-assistant delete was rejected." + } + }, + "required": [ + "error", + "message" + ] + }, + "Squad": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "This is the name of the squad." + }, + "members": { + "description": "This is the list of assistants that make up the squad.\n\nThe call will start with the first assistant in the list.", + "type": "array", + "items": { + "$ref": "#/components/schemas/SquadMemberDTO" + } + }, + "membersOverrides": { + "description": "This can be used to override all the assistants' settings and provide values for their template variables.\n\nBoth `membersOverrides` and `members[n].assistantOverrides` can be used together. First, `members[n].assistantOverrides` is applied. Then, `membersOverrides` is applied as a global override.", + "allOf": [ + { + "$ref": "#/components/schemas/AssistantOverrides" + } + ] + }, + "id": { + "type": "string", + "description": "This is the unique identifier for the squad." + }, + "orgId": { + "type": "string", + "description": "This is the unique identifier for the org that this squad belongs to." + }, + "createdAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the squad was created." + }, + "updatedAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the squad was last updated." + } + }, + "required": [ + "members", + "id", + "orgId", + "createdAt", + "updatedAt" + ] + }, + "UpdateSquadDTO": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "This is the name of the squad." + }, + "members": { + "description": "This is the list of assistants that make up the squad.\n\nThe call will start with the first assistant in the list.", + "type": "array", + "items": { + "$ref": "#/components/schemas/SquadMemberDTO" + } + }, + "membersOverrides": { + "description": "This can be used to override all the assistants' settings and provide values for their template variables.\n\nBoth `membersOverrides` and `members[n].assistantOverrides` can be used together. First, `members[n].assistantOverrides` is applied. Then, `membersOverrides` is applied as a global override.", + "allOf": [ + { + "$ref": "#/components/schemas/AssistantOverrides" + } + ] + } + }, + "required": [ + "members" + ] + }, + "Workflow": { + "type": "object", + "properties": { + "nodes": { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/ConversationNode", + "title": "ConversationNode" + }, + { + "$ref": "#/components/schemas/ToolNode", + "title": "ToolNode" + } + ] + } + }, + "model": { + "description": "This is the model for the workflow.\n\nThis can be overridden at node level using `nodes[n].model`.", + "oneOf": [ + { + "$ref": "#/components/schemas/WorkflowOpenAIModel", + "title": "WorkflowOpenAIModel" + }, + { + "$ref": "#/components/schemas/WorkflowAnthropicModel", + "title": "WorkflowAnthropicModel" + }, + { + "$ref": "#/components/schemas/WorkflowAnthropicBedrockModel", + "title": "WorkflowAnthropicBedrockModel" + }, + { + "$ref": "#/components/schemas/WorkflowGoogleModel", + "title": "WorkflowGoogleModel" + }, + { + "$ref": "#/components/schemas/WorkflowCustomModel", + "title": "WorkflowCustomModel" + } + ] + }, + "transcriber": { + "description": "This is the transcriber for the workflow.\n\nThis can be overridden at node level using `nodes[n].transcriber`.", + "oneOf": [ + { + "$ref": "#/components/schemas/AssemblyAITranscriber", + "title": "AssemblyAITranscriber" + }, + { + "$ref": "#/components/schemas/AzureSpeechTranscriber", + "title": "AzureSpeechTranscriber" + }, + { + "$ref": "#/components/schemas/CustomTranscriber", + "title": "CustomTranscriber" + }, + { + "$ref": "#/components/schemas/DeepgramTranscriber", + "title": "DeepgramTranscriber" + }, + { + "$ref": "#/components/schemas/ElevenLabsTranscriber", + "title": "ElevenLabsTranscriber" + }, + { + "$ref": "#/components/schemas/GladiaTranscriber", + "title": "GladiaTranscriber" + }, + { + "$ref": "#/components/schemas/GoogleTranscriber", + "title": "GoogleTranscriber" + }, + { + "$ref": "#/components/schemas/SpeechmaticsTranscriber", + "title": "SpeechmaticsTranscriber" + }, + { + "$ref": "#/components/schemas/TalkscriberTranscriber", + "title": "TalkscriberTranscriber" + }, + { + "$ref": "#/components/schemas/OpenAITranscriber", + "title": "OpenAITranscriber" + }, + { + "$ref": "#/components/schemas/CartesiaTranscriber", + "title": "CartesiaTranscriber" + }, + { + "$ref": "#/components/schemas/SonioxTranscriber", + "title": "SonioxTranscriber" + }, + { + "$ref": "#/components/schemas/XaiTranscriber", + "title": "XaiTranscriber" + }, + { + "$ref": "#/components/schemas/VapiTranscriber", + "title": "VapiTranscriber" + } + ] + }, + "voice": { + "description": "This is the voice for the workflow.\n\nThis can be overridden at node level using `nodes[n].voice`.", + "oneOf": [ + { + "$ref": "#/components/schemas/AzureVoice", + "title": "AzureVoice" + }, + { + "$ref": "#/components/schemas/CartesiaVoice", + "title": "CartesiaVoice" + }, + { + "$ref": "#/components/schemas/CustomVoice", + "title": "CustomVoice" + }, + { + "$ref": "#/components/schemas/DeepgramVoice", + "title": "DeepgramVoice" + }, + { + "$ref": "#/components/schemas/ElevenLabsVoice", + "title": "ElevenLabsVoice" + }, + { + "$ref": "#/components/schemas/HumeVoice", + "title": "HumeVoice" + }, + { + "$ref": "#/components/schemas/LMNTVoice", + "title": "LMNTVoice" + }, + { + "$ref": "#/components/schemas/NeuphonicVoice", + "title": "NeuphonicVoice" + }, + { + "$ref": "#/components/schemas/OpenAIVoice", + "title": "OpenAIVoice" + }, + { + "$ref": "#/components/schemas/PlayHTVoice", + "title": "PlayHTVoice" + }, + { + "$ref": "#/components/schemas/WellSaidVoice", + "title": "WellSaidVoice" + }, + { + "$ref": "#/components/schemas/RimeAIVoice", + "title": "RimeAIVoice" + }, + { + "$ref": "#/components/schemas/SmallestAIVoice", + "title": "SmallestAIVoice" + }, + { + "$ref": "#/components/schemas/TavusVoice", + "title": "TavusVoice" + }, + { + "$ref": "#/components/schemas/VapiVoice", + "title": "VapiVoice" + }, + { + "$ref": "#/components/schemas/SesameVoice", + "title": "SesameVoice" + }, + { + "$ref": "#/components/schemas/InworldVoice", + "title": "InworldVoice" + }, + { + "$ref": "#/components/schemas/MinimaxVoice", + "title": "MinimaxVoice" + }, + { + "$ref": "#/components/schemas/XaiVoice", + "title": "XaiVoice" + }, + { + "$ref": "#/components/schemas/MicrosoftVoice", + "title": "MicrosoftVoice" + } + ] + }, + "observabilityPlan": { + "description": "This is the plan for observability of workflow's calls.\n\nCurrently, only Langfuse is supported.", + "oneOf": [ + { + "$ref": "#/components/schemas/LangfuseObservabilityPlan", + "title": "Langfuse" + } + ], + "allOf": [ + { + "$ref": "#/components/schemas/LangfuseObservabilityPlan" + } + ] + }, + "backgroundSound": { + "description": "This is the background sound in the call. Default for phone calls is 'office' and default for web calls is 'off'.\nYou can also provide a custom sound by providing a URL to an audio file.", + "oneOf": [ + { + "type": "string", + "enum": [ + "off", + "office" + ], + "example": "office" + }, + { + "type": "string", + "format": "uri", + "example": "https://www.soundjay.com/ambient/sounds/people-in-lounge-1.mp3" + } + ] + }, + "hooks": { + "type": "array", + "description": "This is a set of actions that will be performed on certain events.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/CallHookCallEnding", + "title": "CallHookCallEnding" + }, + { + "$ref": "#/components/schemas/CallHookAssistantSpeechInterrupted", + "title": "CallHookAssistantSpeechInterrupted" + }, + { + "$ref": "#/components/schemas/CallHookCustomerSpeechInterrupted", + "title": "CallHookCustomerSpeechInterrupted" + }, + { + "$ref": "#/components/schemas/CallHookCustomerSpeechTimeout", + "title": "CallHookCustomerSpeechTimeout" + }, + { + "$ref": "#/components/schemas/CallHookModelResponseTimeout", + "title": "CallHookModelResponseTimeout" + } + ] + } + }, + "credentials": { + "type": "array", + "description": "These are dynamic credentials that will be used for the workflow calls. By default, all the credentials are available for use in the call but you can supplement an additional credentials using this. Dynamic credentials override existing credentials.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/CreateAnthropicCredentialDTO", + "title": "AnthropicCredential" + }, + { + "$ref": "#/components/schemas/CreateAnthropicBedrockCredentialDTO", + "title": "AnthropicBedrockCredential" + }, + { + "$ref": "#/components/schemas/CreateAnyscaleCredentialDTO", + "title": "AnyscaleCredential" + }, + { + "$ref": "#/components/schemas/CreateAssemblyAICredentialDTO", + "title": "AssemblyAICredential" + }, + { + "$ref": "#/components/schemas/CreateAzureCredentialDTO", + "title": "AzureCredential" + }, + { + "$ref": "#/components/schemas/CreateAzureOpenAICredentialDTO", + "title": "AzureOpenAICredential" + }, + { + "$ref": "#/components/schemas/CreateByoSipTrunkCredentialDTO", + "title": "ByoSipTrunkCredential" + }, + { + "$ref": "#/components/schemas/CreateCartesiaCredentialDTO", + "title": "CartesiaCredential" + }, + { + "$ref": "#/components/schemas/CreateCerebrasCredentialDTO", + "title": "CerebrasCredential" + }, + { + "$ref": "#/components/schemas/CreateCloudflareCredentialDTO", + "title": "CloudflareCredential" + }, + { + "$ref": "#/components/schemas/CreateCustomLLMCredentialDTO", + "title": "CustomLLMCredential" + }, + { + "$ref": "#/components/schemas/CreateDeepgramCredentialDTO", + "title": "DeepgramCredential" + }, + { + "$ref": "#/components/schemas/CreateDeepInfraCredentialDTO", + "title": "DeepInfraCredential" + }, + { + "$ref": "#/components/schemas/CreateDeepSeekCredentialDTO", + "title": "DeepSeekCredential" + }, + { + "$ref": "#/components/schemas/CreateElevenLabsCredentialDTO", + "title": "ElevenLabsCredential" + }, + { + "$ref": "#/components/schemas/CreateGcpCredentialDTO", + "title": "GcpCredential" + }, + { + "$ref": "#/components/schemas/CreateGladiaCredentialDTO", + "title": "GladiaCredential" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelCredentialDTO", + "title": "GhlCredential" + }, + { + "$ref": "#/components/schemas/CreateGoogleCredentialDTO", + "title": "GoogleCredential" + }, + { + "$ref": "#/components/schemas/CreateGroqCredentialDTO", + "title": "GroqCredential" + }, + { + "$ref": "#/components/schemas/CreateHumeCredentialDTO", + "title": "HumeCredential" + }, + { + "$ref": "#/components/schemas/CreateInflectionAICredentialDTO", + "title": "InflectionAICredential" + }, + { + "$ref": "#/components/schemas/CreateLangfuseCredentialDTO", + "title": "LangfuseCredential" + }, + { + "$ref": "#/components/schemas/CreateLmntCredentialDTO", + "title": "LmntCredential" + }, + { + "$ref": "#/components/schemas/CreateMakeCredentialDTO", + "title": "MakeCredential" + }, + { + "$ref": "#/components/schemas/CreateMistralCredentialDTO", + "title": "MistralCredential" + }, + { + "$ref": "#/components/schemas/CreateNeuphonicCredentialDTO", + "title": "NeuphonicCredential" + }, + { + "$ref": "#/components/schemas/CreateOpenAICredentialDTO", + "title": "OpenAICredential" + }, + { + "$ref": "#/components/schemas/CreateOpenRouterCredentialDTO", + "title": "OpenRouterCredential" + }, + { + "$ref": "#/components/schemas/CreatePerplexityAICredentialDTO", + "title": "PerplexityAICredential" + }, + { + "$ref": "#/components/schemas/CreatePlayHTCredentialDTO", + "title": "PlayHTCredential" + }, + { + "$ref": "#/components/schemas/CreateRimeAICredentialDTO", + "title": "RimeAICredential" + }, + { + "$ref": "#/components/schemas/CreateRunpodCredentialDTO", + "title": "RunpodCredential" + }, + { + "$ref": "#/components/schemas/CreateS3CredentialDTO", + "title": "S3Credential" + }, + { + "$ref": "#/components/schemas/CreateS3CompatibleCredentialDTO", + "title": "S3CompatibleStorageCredential" + }, + { + "$ref": "#/components/schemas/CreateSmallestAICredentialDTO", + "title": "SmallestAICredential" + }, + { + "$ref": "#/components/schemas/CreateSpeechmaticsCredentialDTO", + "title": "SpeechmaticsCredential" + }, + { + "$ref": "#/components/schemas/CreateSonioxCredentialDTO", + "title": "SonioxCredential" + }, + { + "$ref": "#/components/schemas/CreateSupabaseCredentialDTO", + "title": "SupabaseCredential" + }, + { + "$ref": "#/components/schemas/CreateTavusCredentialDTO", + "title": "TavusCredential" + }, + { + "$ref": "#/components/schemas/CreateTogetherAICredentialDTO", + "title": "TogetherAICredential" + }, + { + "$ref": "#/components/schemas/CreateTwilioCredentialDTO", + "title": "TwilioCredential" + }, + { + "$ref": "#/components/schemas/CreateVonageCredentialDTO", + "title": "VonageCredential" + }, + { + "$ref": "#/components/schemas/CreateWebhookCredentialDTO", + "title": "WebhookCredential" + }, + { + "$ref": "#/components/schemas/CreateCustomCredentialDTO", + "title": "CustomCredential" + }, + { + "$ref": "#/components/schemas/CreateXAiCredentialDTO", + "title": "XAiCredential" + }, + { + "$ref": "#/components/schemas/CreateMicrosoftCredentialDTO", + "title": "MicrosoftCredential" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarOAuth2ClientCredentialDTO", + "title": "GoogleCalendarOAuth2ClientCredential" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarOAuth2AuthorizationCredentialDTO", + "title": "GoogleCalendarOAuth2AuthorizationCredential" + }, + { + "$ref": "#/components/schemas/CreateGoogleSheetsOAuth2AuthorizationCredentialDTO", + "title": "GoogleSheetsOAuth2AuthorizationCredential" + }, + { + "$ref": "#/components/schemas/CreateSlackOAuth2AuthorizationCredentialDTO", + "title": "SlackOAuth2AuthorizationCredential" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelMCPCredentialDTO", + "title": "GoHighLevelMCPCredential" + }, + { + "$ref": "#/components/schemas/CreateInworldCredentialDTO", + "title": "InworldCredential" + }, + { + "$ref": "#/components/schemas/CreateMinimaxCredentialDTO", + "title": "MinimaxCredential" + }, + { + "$ref": "#/components/schemas/CreateWellSaidCredentialDTO", + "title": "WellSaidCredential" + }, + { + "$ref": "#/components/schemas/CreateEmailCredentialDTO", + "title": "EmailCredential" + }, + { + "$ref": "#/components/schemas/CreateSlackWebhookCredentialDTO", + "title": "SlackWebhookCredential" + } + ], + "discriminator": { + "propertyName": "provider", + "mapping": { + "11labs": "#/components/schemas/CreateElevenLabsCredentialDTO", + "anthropic": "#/components/schemas/CreateAnthropicCredentialDTO", + "anthropic-bedrock": "#/components/schemas/CreateAnthropicBedrockCredentialDTO", + "anyscale": "#/components/schemas/CreateAnyscaleCredentialDTO", + "assembly-ai": "#/components/schemas/CreateAssemblyAICredentialDTO", + "azure-openai": "#/components/schemas/CreateAzureOpenAICredentialDTO", + "azure": "#/components/schemas/CreateAzureCredentialDTO", + "byo-sip-trunk": "#/components/schemas/CreateByoSipTrunkCredentialDTO", + "cartesia": "#/components/schemas/CreateCartesiaCredentialDTO", + "cerebras": "#/components/schemas/CreateCerebrasCredentialDTO", + "cloudflare": "#/components/schemas/CreateCloudflareCredentialDTO", + "custom-llm": "#/components/schemas/CreateCustomLLMCredentialDTO", + "deepgram": "#/components/schemas/CreateDeepgramCredentialDTO", + "deepinfra": "#/components/schemas/CreateDeepInfraCredentialDTO", + "deep-seek": "#/components/schemas/CreateDeepSeekCredentialDTO", + "gcp": "#/components/schemas/CreateGcpCredentialDTO", + "gladia": "#/components/schemas/CreateGladiaCredentialDTO", + "gohighlevel": "#/components/schemas/CreateGoHighLevelCredentialDTO", + "google": "#/components/schemas/CreateGoogleCredentialDTO", + "groq": "#/components/schemas/CreateGroqCredentialDTO", + "inflection-ai": "#/components/schemas/CreateInflectionAICredentialDTO", + "langfuse": "#/components/schemas/CreateLangfuseCredentialDTO", + "lmnt": "#/components/schemas/CreateLmntCredentialDTO", + "make": "#/components/schemas/CreateMakeCredentialDTO", + "openai": "#/components/schemas/CreateOpenAICredentialDTO", + "openrouter": "#/components/schemas/CreateOpenRouterCredentialDTO", + "perplexity-ai": "#/components/schemas/CreatePerplexityAICredentialDTO", + "playht": "#/components/schemas/CreatePlayHTCredentialDTO", + "rime-ai": "#/components/schemas/CreateRimeAICredentialDTO", + "runpod": "#/components/schemas/CreateRunpodCredentialDTO", + "s3": "#/components/schemas/CreateS3CredentialDTO", + "s3-compatible": "#/components/schemas/CreateS3CompatibleCredentialDTO", + "supabase": "#/components/schemas/CreateSupabaseCredentialDTO", + "smallest-ai": "#/components/schemas/CreateSmallestAICredentialDTO", + "tavus": "#/components/schemas/CreateTavusCredentialDTO", + "together-ai": "#/components/schemas/CreateTogetherAICredentialDTO", + "twilio": "#/components/schemas/CreateTwilioCredentialDTO", + "vonage": "#/components/schemas/CreateVonageCredentialDTO", + "webhook": "#/components/schemas/CreateWebhookCredentialDTO", + "custom-credential": "#/components/schemas/CreateCustomCredentialDTO", + "xai": "#/components/schemas/CreateXAiCredentialDTO", + "microsoft": "#/components/schemas/CreateMicrosoftCredentialDTO", + "neuphonic": "#/components/schemas/CreateNeuphonicCredentialDTO", + "hume": "#/components/schemas/CreateHumeCredentialDTO", + "mistral": "#/components/schemas/CreateMistralCredentialDTO", + "speechmatics": "#/components/schemas/CreateSpeechmaticsCredentialDTO", + "soniox": "#/components/schemas/CreateSonioxCredentialDTO", + "google.calendar.oauth2-client": "#/components/schemas/CreateGoogleCalendarOAuth2ClientCredentialDTO", + "google.calendar.oauth2-authorization": "#/components/schemas/CreateGoogleCalendarOAuth2AuthorizationCredentialDTO", + "google.sheets.oauth2-authorization": "#/components/schemas/CreateGoogleSheetsOAuth2AuthorizationCredentialDTO", + "slack.oauth2-authorization": "#/components/schemas/CreateSlackOAuth2AuthorizationCredentialDTO", + "ghl.oauth2-authorization": "#/components/schemas/CreateGoHighLevelMCPCredentialDTO", + "inworld": "#/components/schemas/CreateInworldCredentialDTO", + "minimax": "#/components/schemas/CreateMinimaxCredentialDTO", + "wellsaid": "#/components/schemas/CreateWellSaidCredentialDTO", + "email": "#/components/schemas/CreateEmailCredentialDTO", + "slack-webhook": "#/components/schemas/CreateSlackWebhookCredentialDTO" + } + } + } + }, + "voicemailDetection": { + "description": "This is the voicemail detection plan for the workflow.", + "oneOf": [ + { + "type": "string", + "enum": [ + "off" + ] + }, + { + "$ref": "#/components/schemas/GoogleVoicemailDetectionPlan", + "title": "Google" + }, + { + "$ref": "#/components/schemas/OpenAIVoicemailDetectionPlan", + "title": "OpenAI" + }, + { + "$ref": "#/components/schemas/TwilioVoicemailDetectionPlan", + "title": "Twilio" + }, + { + "$ref": "#/components/schemas/VapiVoicemailDetectionPlan", + "title": "Vapi" + } + ] + }, + "maxDurationSeconds": { + "type": "number", + "description": "This is the maximum duration of the call in seconds.\n\nAfter this duration, the call will automatically end.\n\nDefault is 1800 (30 minutes), max is 43200 (12 hours), and min is 10 seconds.", + "minimum": 10, + "maximum": 43200, + "example": 600 + }, + "id": { + "type": "string" + }, + "orgId": { + "type": "string" + }, + "createdAt": { + "format": "date-time", + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + }, + "name": { + "type": "string", + "maxLength": 80 + }, + "edges": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Edge" + } + }, + "globalPrompt": { + "type": "string", + "maxLength": 5000 + }, + "server": { + "description": "This is where Vapi will send webhooks. You can find all webhooks available along with their shape in ServerMessage schema.\n\nThe order of precedence is:\n\n1. tool.server\n2. workflow.server / assistant.server\n3. phoneNumber.server\n4. org.server", + "allOf": [ + { + "$ref": "#/components/schemas/Server" + } + ] + }, + "compliancePlan": { + "description": "This is the compliance plan for the workflow. It allows you to configure HIPAA and other compliance settings.", + "allOf": [ + { + "$ref": "#/components/schemas/CompliancePlan" + } + ] + }, + "analysisPlan": { + "description": "This is the plan for analysis of workflow's calls. Stored in `call.analysis`.", + "allOf": [ + { + "$ref": "#/components/schemas/AnalysisPlan" + } + ] + }, + "artifactPlan": { + "description": "This is the plan for artifacts generated during workflow's calls. Stored in `call.artifact`.", + "allOf": [ + { + "$ref": "#/components/schemas/ArtifactPlan" + } + ] + }, + "startSpeakingPlan": { + "description": "This is the plan for when the workflow nodes should start talking.\n\nYou should configure this if you're running into these issues:\n- The assistant is too slow to start talking after the customer is done speaking.\n- The assistant is too fast to start talking after the customer is done speaking.\n- The assistant is so fast that it's actually interrupting the customer.", + "allOf": [ + { + "$ref": "#/components/schemas/StartSpeakingPlan" + } + ] + }, + "stopSpeakingPlan": { + "description": "This is the plan for when workflow nodes should stop talking on customer interruption.\n\nYou should configure this if you're running into these issues:\n- The assistant is too slow to recognize customer's interruption.\n- The assistant is too fast to recognize customer's interruption.\n- The assistant is getting interrupted by phrases that are just acknowledgments.\n- The assistant is getting interrupted by background noises.\n- The assistant is not properly stopping -- it starts talking right after getting interrupted.", + "allOf": [ + { + "$ref": "#/components/schemas/StopSpeakingPlan" + } + ] + }, + "monitorPlan": { + "description": "This is the plan for real-time monitoring of the workflow's calls.\n\nUsage:\n- To enable live listening of the workflow's calls, set `monitorPlan.listenEnabled` to `true`.\n- To enable live control of the workflow's calls, set `monitorPlan.controlEnabled` to `true`.", + "allOf": [ + { + "$ref": "#/components/schemas/MonitorPlan" + } + ] + }, + "backgroundSpeechDenoisingPlan": { + "description": "This enables filtering of noise and background speech while the user is talking.\n\nFeatures:\n- Smart denoising using Krisp\n- Fourier denoising\n\nBoth can be used together. Order of precedence:\n- Smart denoising\n- Fourier denoising", + "allOf": [ + { + "$ref": "#/components/schemas/BackgroundSpeechDenoisingPlan" + } + ] + }, + "credentialIds": { + "description": "These are the credentials that will be used for the workflow calls. By default, all the credentials are available for use in the call but you can provide a subset using this.", + "type": "array", + "items": { + "type": "string" + } + }, + "keypadInputPlan": { + "description": "This is the plan for keypad input handling during workflow calls.", + "allOf": [ + { + "$ref": "#/components/schemas/KeypadInputPlan" + } + ] + }, + "voicemailMessage": { + "type": "string", + "description": "This is the message that the assistant will say if the call is forwarded to voicemail.\n\nIf unspecified, it will hang up.", + "maxLength": 1000 + } + }, + "required": [ + "nodes", + "id", + "orgId", + "createdAt", + "updatedAt", + "name", + "edges" + ] + }, + "CreateWorkflowDTO": { + "type": "object", + "properties": { + "nodes": { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/ConversationNode", + "title": "ConversationNode" + }, + { + "$ref": "#/components/schemas/ToolNode", + "title": "ToolNode" + } + ] + } + }, + "model": { + "description": "This is the model for the workflow.\n\nThis can be overridden at node level using `nodes[n].model`.", + "oneOf": [ + { + "$ref": "#/components/schemas/WorkflowOpenAIModel", + "title": "WorkflowOpenAIModel" + }, + { + "$ref": "#/components/schemas/WorkflowAnthropicModel", + "title": "WorkflowAnthropicModel" + }, + { + "$ref": "#/components/schemas/WorkflowAnthropicBedrockModel", + "title": "WorkflowAnthropicBedrockModel" + }, + { + "$ref": "#/components/schemas/WorkflowGoogleModel", + "title": "WorkflowGoogleModel" + }, + { + "$ref": "#/components/schemas/WorkflowCustomModel", + "title": "WorkflowCustomModel" + } + ] + }, + "transcriber": { + "description": "This is the transcriber for the workflow.\n\nThis can be overridden at node level using `nodes[n].transcriber`.", + "oneOf": [ + { + "$ref": "#/components/schemas/AssemblyAITranscriber", + "title": "AssemblyAITranscriber" + }, + { + "$ref": "#/components/schemas/AzureSpeechTranscriber", + "title": "AzureSpeechTranscriber" + }, + { + "$ref": "#/components/schemas/CustomTranscriber", + "title": "CustomTranscriber" + }, + { + "$ref": "#/components/schemas/DeepgramTranscriber", + "title": "DeepgramTranscriber" + }, + { + "$ref": "#/components/schemas/ElevenLabsTranscriber", + "title": "ElevenLabsTranscriber" + }, + { + "$ref": "#/components/schemas/GladiaTranscriber", + "title": "GladiaTranscriber" + }, + { + "$ref": "#/components/schemas/GoogleTranscriber", + "title": "GoogleTranscriber" + }, + { + "$ref": "#/components/schemas/SpeechmaticsTranscriber", + "title": "SpeechmaticsTranscriber" + }, + { + "$ref": "#/components/schemas/TalkscriberTranscriber", + "title": "TalkscriberTranscriber" + }, + { + "$ref": "#/components/schemas/OpenAITranscriber", + "title": "OpenAITranscriber" + }, + { + "$ref": "#/components/schemas/CartesiaTranscriber", + "title": "CartesiaTranscriber" + }, + { + "$ref": "#/components/schemas/SonioxTranscriber", + "title": "SonioxTranscriber" + }, + { + "$ref": "#/components/schemas/XaiTranscriber", + "title": "XaiTranscriber" + }, + { + "$ref": "#/components/schemas/VapiTranscriber", + "title": "VapiTranscriber" + } + ] + }, + "voice": { + "description": "This is the voice for the workflow.\n\nThis can be overridden at node level using `nodes[n].voice`.", + "oneOf": [ + { + "$ref": "#/components/schemas/AzureVoice", + "title": "AzureVoice" + }, + { + "$ref": "#/components/schemas/CartesiaVoice", + "title": "CartesiaVoice" + }, + { + "$ref": "#/components/schemas/CustomVoice", + "title": "CustomVoice" + }, + { + "$ref": "#/components/schemas/DeepgramVoice", + "title": "DeepgramVoice" + }, + { + "$ref": "#/components/schemas/ElevenLabsVoice", + "title": "ElevenLabsVoice" + }, + { + "$ref": "#/components/schemas/HumeVoice", + "title": "HumeVoice" + }, + { + "$ref": "#/components/schemas/LMNTVoice", + "title": "LMNTVoice" + }, + { + "$ref": "#/components/schemas/NeuphonicVoice", + "title": "NeuphonicVoice" + }, + { + "$ref": "#/components/schemas/OpenAIVoice", + "title": "OpenAIVoice" + }, + { + "$ref": "#/components/schemas/PlayHTVoice", + "title": "PlayHTVoice" + }, + { + "$ref": "#/components/schemas/WellSaidVoice", + "title": "WellSaidVoice" + }, + { + "$ref": "#/components/schemas/RimeAIVoice", + "title": "RimeAIVoice" + }, + { + "$ref": "#/components/schemas/SmallestAIVoice", + "title": "SmallestAIVoice" + }, + { + "$ref": "#/components/schemas/TavusVoice", + "title": "TavusVoice" + }, + { + "$ref": "#/components/schemas/VapiVoice", + "title": "VapiVoice" + }, + { + "$ref": "#/components/schemas/SesameVoice", + "title": "SesameVoice" + }, + { + "$ref": "#/components/schemas/InworldVoice", + "title": "InworldVoice" + }, + { + "$ref": "#/components/schemas/MinimaxVoice", + "title": "MinimaxVoice" + }, + { + "$ref": "#/components/schemas/XaiVoice", + "title": "XaiVoice" + }, + { + "$ref": "#/components/schemas/MicrosoftVoice", + "title": "MicrosoftVoice" + } + ] + }, + "observabilityPlan": { + "description": "This is the plan for observability of workflow's calls.\n\nCurrently, only Langfuse is supported.", + "oneOf": [ + { + "$ref": "#/components/schemas/LangfuseObservabilityPlan", + "title": "Langfuse" + } + ], + "allOf": [ + { + "$ref": "#/components/schemas/LangfuseObservabilityPlan" + } + ] + }, + "backgroundSound": { + "description": "This is the background sound in the call. Default for phone calls is 'office' and default for web calls is 'off'.\nYou can also provide a custom sound by providing a URL to an audio file.", + "oneOf": [ + { + "type": "string", + "enum": [ + "off", + "office" + ], + "example": "office" + }, + { + "type": "string", + "format": "uri", + "example": "https://www.soundjay.com/ambient/sounds/people-in-lounge-1.mp3" + } + ] + }, + "hooks": { + "type": "array", + "description": "This is a set of actions that will be performed on certain events.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/CallHookCallEnding", + "title": "CallHookCallEnding" + }, + { + "$ref": "#/components/schemas/CallHookAssistantSpeechInterrupted", + "title": "CallHookAssistantSpeechInterrupted" + }, + { + "$ref": "#/components/schemas/CallHookCustomerSpeechInterrupted", + "title": "CallHookCustomerSpeechInterrupted" + }, + { + "$ref": "#/components/schemas/CallHookCustomerSpeechTimeout", + "title": "CallHookCustomerSpeechTimeout" + }, + { + "$ref": "#/components/schemas/CallHookModelResponseTimeout", + "title": "CallHookModelResponseTimeout" + } + ] + } + }, + "credentials": { + "type": "array", + "description": "These are dynamic credentials that will be used for the workflow calls. By default, all the credentials are available for use in the call but you can supplement an additional credentials using this. Dynamic credentials override existing credentials.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/CreateAnthropicCredentialDTO", + "title": "AnthropicCredential" + }, + { + "$ref": "#/components/schemas/CreateAnthropicBedrockCredentialDTO", + "title": "AnthropicBedrockCredential" + }, + { + "$ref": "#/components/schemas/CreateAnyscaleCredentialDTO", + "title": "AnyscaleCredential" + }, + { + "$ref": "#/components/schemas/CreateAssemblyAICredentialDTO", + "title": "AssemblyAICredential" + }, + { + "$ref": "#/components/schemas/CreateAzureCredentialDTO", + "title": "AzureCredential" + }, + { + "$ref": "#/components/schemas/CreateAzureOpenAICredentialDTO", + "title": "AzureOpenAICredential" + }, + { + "$ref": "#/components/schemas/CreateByoSipTrunkCredentialDTO", + "title": "ByoSipTrunkCredential" + }, + { + "$ref": "#/components/schemas/CreateCartesiaCredentialDTO", + "title": "CartesiaCredential" + }, + { + "$ref": "#/components/schemas/CreateCerebrasCredentialDTO", + "title": "CerebrasCredential" + }, + { + "$ref": "#/components/schemas/CreateCloudflareCredentialDTO", + "title": "CloudflareCredential" + }, + { + "$ref": "#/components/schemas/CreateCustomLLMCredentialDTO", + "title": "CustomLLMCredential" + }, + { + "$ref": "#/components/schemas/CreateDeepgramCredentialDTO", + "title": "DeepgramCredential" + }, + { + "$ref": "#/components/schemas/CreateDeepInfraCredentialDTO", + "title": "DeepInfraCredential" + }, + { + "$ref": "#/components/schemas/CreateDeepSeekCredentialDTO", + "title": "DeepSeekCredential" + }, + { + "$ref": "#/components/schemas/CreateElevenLabsCredentialDTO", + "title": "ElevenLabsCredential" + }, + { + "$ref": "#/components/schemas/CreateGcpCredentialDTO", + "title": "GcpCredential" + }, + { + "$ref": "#/components/schemas/CreateGladiaCredentialDTO", + "title": "GladiaCredential" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelCredentialDTO", + "title": "GhlCredential" + }, + { + "$ref": "#/components/schemas/CreateGoogleCredentialDTO", + "title": "GoogleCredential" + }, + { + "$ref": "#/components/schemas/CreateGroqCredentialDTO", + "title": "GroqCredential" + }, + { + "$ref": "#/components/schemas/CreateHumeCredentialDTO", + "title": "HumeCredential" + }, + { + "$ref": "#/components/schemas/CreateInflectionAICredentialDTO", + "title": "InflectionAICredential" + }, + { + "$ref": "#/components/schemas/CreateLangfuseCredentialDTO", + "title": "LangfuseCredential" + }, + { + "$ref": "#/components/schemas/CreateLmntCredentialDTO", + "title": "LmntCredential" + }, + { + "$ref": "#/components/schemas/CreateMakeCredentialDTO", + "title": "MakeCredential" + }, + { + "$ref": "#/components/schemas/CreateMistralCredentialDTO", + "title": "MistralCredential" + }, + { + "$ref": "#/components/schemas/CreateNeuphonicCredentialDTO", + "title": "NeuphonicCredential" + }, + { + "$ref": "#/components/schemas/CreateOpenAICredentialDTO", + "title": "OpenAICredential" + }, + { + "$ref": "#/components/schemas/CreateOpenRouterCredentialDTO", + "title": "OpenRouterCredential" + }, + { + "$ref": "#/components/schemas/CreatePerplexityAICredentialDTO", + "title": "PerplexityAICredential" + }, + { + "$ref": "#/components/schemas/CreatePlayHTCredentialDTO", + "title": "PlayHTCredential" + }, + { + "$ref": "#/components/schemas/CreateRimeAICredentialDTO", + "title": "RimeAICredential" + }, + { + "$ref": "#/components/schemas/CreateRunpodCredentialDTO", + "title": "RunpodCredential" + }, + { + "$ref": "#/components/schemas/CreateS3CredentialDTO", + "title": "S3Credential" + }, + { + "$ref": "#/components/schemas/CreateS3CompatibleCredentialDTO", + "title": "S3CompatibleStorageCredential" + }, + { + "$ref": "#/components/schemas/CreateSmallestAICredentialDTO", + "title": "SmallestAICredential" + }, + { + "$ref": "#/components/schemas/CreateSpeechmaticsCredentialDTO", + "title": "SpeechmaticsCredential" + }, + { + "$ref": "#/components/schemas/CreateSonioxCredentialDTO", + "title": "SonioxCredential" + }, + { + "$ref": "#/components/schemas/CreateSupabaseCredentialDTO", + "title": "SupabaseCredential" + }, + { + "$ref": "#/components/schemas/CreateTavusCredentialDTO", + "title": "TavusCredential" + }, + { + "$ref": "#/components/schemas/CreateTogetherAICredentialDTO", + "title": "TogetherAICredential" + }, + { + "$ref": "#/components/schemas/CreateTwilioCredentialDTO", + "title": "TwilioCredential" + }, + { + "$ref": "#/components/schemas/CreateVonageCredentialDTO", + "title": "VonageCredential" + }, + { + "$ref": "#/components/schemas/CreateWebhookCredentialDTO", + "title": "WebhookCredential" + }, + { + "$ref": "#/components/schemas/CreateCustomCredentialDTO", + "title": "CustomCredential" + }, + { + "$ref": "#/components/schemas/CreateXAiCredentialDTO", + "title": "XAiCredential" + }, + { + "$ref": "#/components/schemas/CreateMicrosoftCredentialDTO", + "title": "MicrosoftCredential" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarOAuth2ClientCredentialDTO", + "title": "GoogleCalendarOAuth2ClientCredential" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarOAuth2AuthorizationCredentialDTO", + "title": "GoogleCalendarOAuth2AuthorizationCredential" + }, + { + "$ref": "#/components/schemas/CreateGoogleSheetsOAuth2AuthorizationCredentialDTO", + "title": "GoogleSheetsOAuth2AuthorizationCredential" + }, + { + "$ref": "#/components/schemas/CreateSlackOAuth2AuthorizationCredentialDTO", + "title": "SlackOAuth2AuthorizationCredential" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelMCPCredentialDTO", + "title": "GoHighLevelMCPCredential" + }, + { + "$ref": "#/components/schemas/CreateInworldCredentialDTO", + "title": "InworldCredential" + }, + { + "$ref": "#/components/schemas/CreateMinimaxCredentialDTO", + "title": "MinimaxCredential" + }, + { + "$ref": "#/components/schemas/CreateWellSaidCredentialDTO", + "title": "WellSaidCredential" + }, + { + "$ref": "#/components/schemas/CreateEmailCredentialDTO", + "title": "EmailCredential" + }, + { + "$ref": "#/components/schemas/CreateSlackWebhookCredentialDTO", + "title": "SlackWebhookCredential" + } + ], + "discriminator": { + "propertyName": "provider", + "mapping": { + "11labs": "#/components/schemas/CreateElevenLabsCredentialDTO", + "anthropic": "#/components/schemas/CreateAnthropicCredentialDTO", + "anthropic-bedrock": "#/components/schemas/CreateAnthropicBedrockCredentialDTO", + "anyscale": "#/components/schemas/CreateAnyscaleCredentialDTO", + "assembly-ai": "#/components/schemas/CreateAssemblyAICredentialDTO", + "azure-openai": "#/components/schemas/CreateAzureOpenAICredentialDTO", + "azure": "#/components/schemas/CreateAzureCredentialDTO", + "byo-sip-trunk": "#/components/schemas/CreateByoSipTrunkCredentialDTO", + "cartesia": "#/components/schemas/CreateCartesiaCredentialDTO", + "cerebras": "#/components/schemas/CreateCerebrasCredentialDTO", + "cloudflare": "#/components/schemas/CreateCloudflareCredentialDTO", + "custom-llm": "#/components/schemas/CreateCustomLLMCredentialDTO", + "deepgram": "#/components/schemas/CreateDeepgramCredentialDTO", + "deepinfra": "#/components/schemas/CreateDeepInfraCredentialDTO", + "deep-seek": "#/components/schemas/CreateDeepSeekCredentialDTO", + "gcp": "#/components/schemas/CreateGcpCredentialDTO", + "gladia": "#/components/schemas/CreateGladiaCredentialDTO", + "gohighlevel": "#/components/schemas/CreateGoHighLevelCredentialDTO", + "google": "#/components/schemas/CreateGoogleCredentialDTO", + "groq": "#/components/schemas/CreateGroqCredentialDTO", + "inflection-ai": "#/components/schemas/CreateInflectionAICredentialDTO", + "langfuse": "#/components/schemas/CreateLangfuseCredentialDTO", + "lmnt": "#/components/schemas/CreateLmntCredentialDTO", + "make": "#/components/schemas/CreateMakeCredentialDTO", + "openai": "#/components/schemas/CreateOpenAICredentialDTO", + "openrouter": "#/components/schemas/CreateOpenRouterCredentialDTO", + "perplexity-ai": "#/components/schemas/CreatePerplexityAICredentialDTO", + "playht": "#/components/schemas/CreatePlayHTCredentialDTO", + "rime-ai": "#/components/schemas/CreateRimeAICredentialDTO", + "runpod": "#/components/schemas/CreateRunpodCredentialDTO", + "s3": "#/components/schemas/CreateS3CredentialDTO", + "s3-compatible": "#/components/schemas/CreateS3CompatibleCredentialDTO", + "supabase": "#/components/schemas/CreateSupabaseCredentialDTO", + "smallest-ai": "#/components/schemas/CreateSmallestAICredentialDTO", + "tavus": "#/components/schemas/CreateTavusCredentialDTO", + "together-ai": "#/components/schemas/CreateTogetherAICredentialDTO", + "twilio": "#/components/schemas/CreateTwilioCredentialDTO", + "vonage": "#/components/schemas/CreateVonageCredentialDTO", + "webhook": "#/components/schemas/CreateWebhookCredentialDTO", + "custom-credential": "#/components/schemas/CreateCustomCredentialDTO", + "xai": "#/components/schemas/CreateXAiCredentialDTO", + "microsoft": "#/components/schemas/CreateMicrosoftCredentialDTO", + "neuphonic": "#/components/schemas/CreateNeuphonicCredentialDTO", + "hume": "#/components/schemas/CreateHumeCredentialDTO", + "mistral": "#/components/schemas/CreateMistralCredentialDTO", + "speechmatics": "#/components/schemas/CreateSpeechmaticsCredentialDTO", + "soniox": "#/components/schemas/CreateSonioxCredentialDTO", + "google.calendar.oauth2-client": "#/components/schemas/CreateGoogleCalendarOAuth2ClientCredentialDTO", + "google.calendar.oauth2-authorization": "#/components/schemas/CreateGoogleCalendarOAuth2AuthorizationCredentialDTO", + "google.sheets.oauth2-authorization": "#/components/schemas/CreateGoogleSheetsOAuth2AuthorizationCredentialDTO", + "slack.oauth2-authorization": "#/components/schemas/CreateSlackOAuth2AuthorizationCredentialDTO", + "ghl.oauth2-authorization": "#/components/schemas/CreateGoHighLevelMCPCredentialDTO", + "inworld": "#/components/schemas/CreateInworldCredentialDTO", + "minimax": "#/components/schemas/CreateMinimaxCredentialDTO", + "wellsaid": "#/components/schemas/CreateWellSaidCredentialDTO", + "email": "#/components/schemas/CreateEmailCredentialDTO", + "slack-webhook": "#/components/schemas/CreateSlackWebhookCredentialDTO" + } + } + } + }, + "voicemailDetection": { + "description": "This is the voicemail detection plan for the workflow.", + "oneOf": [ + { + "type": "string", + "enum": [ + "off" + ] + }, + { + "$ref": "#/components/schemas/GoogleVoicemailDetectionPlan", + "title": "Google" + }, + { + "$ref": "#/components/schemas/OpenAIVoicemailDetectionPlan", + "title": "OpenAI" + }, + { + "$ref": "#/components/schemas/TwilioVoicemailDetectionPlan", + "title": "Twilio" + }, + { + "$ref": "#/components/schemas/VapiVoicemailDetectionPlan", + "title": "Vapi" + } + ] + }, + "maxDurationSeconds": { + "type": "number", + "description": "This is the maximum duration of the call in seconds.\n\nAfter this duration, the call will automatically end.\n\nDefault is 1800 (30 minutes), max is 43200 (12 hours), and min is 10 seconds.", + "minimum": 10, + "maximum": 43200, + "example": 600 + }, + "name": { + "type": "string", + "maxLength": 80 + }, + "edges": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Edge" + } + }, + "globalPrompt": { + "type": "string", + "maxLength": 5000 + }, + "server": { + "description": "This is where Vapi will send webhooks. You can find all webhooks available along with their shape in ServerMessage schema.\n\nThe order of precedence is:\n\n1. tool.server\n2. workflow.server / assistant.server\n3. phoneNumber.server\n4. org.server", + "allOf": [ + { + "$ref": "#/components/schemas/Server" + } + ] + }, + "compliancePlan": { + "description": "This is the compliance plan for the workflow. It allows you to configure HIPAA and other compliance settings.", + "allOf": [ + { + "$ref": "#/components/schemas/CompliancePlan" + } + ] + }, + "analysisPlan": { + "description": "This is the plan for analysis of workflow's calls. Stored in `call.analysis`.", + "allOf": [ + { + "$ref": "#/components/schemas/AnalysisPlan" + } + ] + }, + "artifactPlan": { + "description": "This is the plan for artifacts generated during workflow's calls. Stored in `call.artifact`.", + "allOf": [ + { + "$ref": "#/components/schemas/ArtifactPlan" + } + ] + }, + "startSpeakingPlan": { + "description": "This is the plan for when the workflow nodes should start talking.\n\nYou should configure this if you're running into these issues:\n- The assistant is too slow to start talking after the customer is done speaking.\n- The assistant is too fast to start talking after the customer is done speaking.\n- The assistant is so fast that it's actually interrupting the customer.", + "allOf": [ + { + "$ref": "#/components/schemas/StartSpeakingPlan" + } + ] + }, + "stopSpeakingPlan": { + "description": "This is the plan for when workflow nodes should stop talking on customer interruption.\n\nYou should configure this if you're running into these issues:\n- The assistant is too slow to recognize customer's interruption.\n- The assistant is too fast to recognize customer's interruption.\n- The assistant is getting interrupted by phrases that are just acknowledgments.\n- The assistant is getting interrupted by background noises.\n- The assistant is not properly stopping -- it starts talking right after getting interrupted.", + "allOf": [ + { + "$ref": "#/components/schemas/StopSpeakingPlan" + } + ] + }, + "monitorPlan": { + "description": "This is the plan for real-time monitoring of the workflow's calls.\n\nUsage:\n- To enable live listening of the workflow's calls, set `monitorPlan.listenEnabled` to `true`.\n- To enable live control of the workflow's calls, set `monitorPlan.controlEnabled` to `true`.", + "allOf": [ + { + "$ref": "#/components/schemas/MonitorPlan" + } + ] + }, + "backgroundSpeechDenoisingPlan": { + "description": "This enables filtering of noise and background speech while the user is talking.\n\nFeatures:\n- Smart denoising using Krisp\n- Fourier denoising\n\nBoth can be used together. Order of precedence:\n- Smart denoising\n- Fourier denoising", + "allOf": [ + { + "$ref": "#/components/schemas/BackgroundSpeechDenoisingPlan" + } + ] + }, + "credentialIds": { + "description": "These are the credentials that will be used for the workflow calls. By default, all the credentials are available for use in the call but you can provide a subset using this.", + "type": "array", + "items": { + "type": "string" + } + }, + "keypadInputPlan": { + "description": "This is the plan for keypad input handling during workflow calls.", + "allOf": [ + { + "$ref": "#/components/schemas/KeypadInputPlan" + } + ] + }, + "voicemailMessage": { + "type": "string", + "description": "This is the message that the assistant will say if the call is forwarded to voicemail.\n\nIf unspecified, it will hang up.", + "maxLength": 1000 + } + }, + "required": [ + "nodes", + "name", + "edges" + ] + }, + "UpdateWorkflowDTO": { + "type": "object", + "properties": { + "nodes": { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/ConversationNode", + "title": "ConversationNode" + }, + { + "$ref": "#/components/schemas/ToolNode", + "title": "ToolNode" + } + ] + } + }, + "model": { + "description": "This is the model for the workflow.\n\nThis can be overridden at node level using `nodes[n].model`.", + "oneOf": [ + { + "$ref": "#/components/schemas/WorkflowOpenAIModel", + "title": "WorkflowOpenAIModel" + }, + { + "$ref": "#/components/schemas/WorkflowAnthropicModel", + "title": "WorkflowAnthropicModel" + }, + { + "$ref": "#/components/schemas/WorkflowAnthropicBedrockModel", + "title": "WorkflowAnthropicBedrockModel" + }, + { + "$ref": "#/components/schemas/WorkflowGoogleModel", + "title": "WorkflowGoogleModel" + }, + { + "$ref": "#/components/schemas/WorkflowCustomModel", + "title": "WorkflowCustomModel" + } + ] + }, + "transcriber": { + "description": "This is the transcriber for the workflow.\n\nThis can be overridden at node level using `nodes[n].transcriber`.", + "oneOf": [ + { + "$ref": "#/components/schemas/AssemblyAITranscriber", + "title": "AssemblyAITranscriber" + }, + { + "$ref": "#/components/schemas/AzureSpeechTranscriber", + "title": "AzureSpeechTranscriber" + }, + { + "$ref": "#/components/schemas/CustomTranscriber", + "title": "CustomTranscriber" + }, + { + "$ref": "#/components/schemas/DeepgramTranscriber", + "title": "DeepgramTranscriber" + }, + { + "$ref": "#/components/schemas/ElevenLabsTranscriber", + "title": "ElevenLabsTranscriber" + }, + { + "$ref": "#/components/schemas/GladiaTranscriber", + "title": "GladiaTranscriber" + }, + { + "$ref": "#/components/schemas/GoogleTranscriber", + "title": "GoogleTranscriber" + }, + { + "$ref": "#/components/schemas/SpeechmaticsTranscriber", + "title": "SpeechmaticsTranscriber" + }, + { + "$ref": "#/components/schemas/TalkscriberTranscriber", + "title": "TalkscriberTranscriber" + }, + { + "$ref": "#/components/schemas/OpenAITranscriber", + "title": "OpenAITranscriber" + }, + { + "$ref": "#/components/schemas/CartesiaTranscriber", + "title": "CartesiaTranscriber" + }, + { + "$ref": "#/components/schemas/SonioxTranscriber", + "title": "SonioxTranscriber" + }, + { + "$ref": "#/components/schemas/XaiTranscriber", + "title": "XaiTranscriber" + }, + { + "$ref": "#/components/schemas/VapiTranscriber", + "title": "VapiTranscriber" + } + ] + }, + "voice": { + "description": "This is the voice for the workflow.\n\nThis can be overridden at node level using `nodes[n].voice`.", + "oneOf": [ + { + "$ref": "#/components/schemas/AzureVoice", + "title": "AzureVoice" + }, + { + "$ref": "#/components/schemas/CartesiaVoice", + "title": "CartesiaVoice" + }, + { + "$ref": "#/components/schemas/CustomVoice", + "title": "CustomVoice" + }, + { + "$ref": "#/components/schemas/DeepgramVoice", + "title": "DeepgramVoice" + }, + { + "$ref": "#/components/schemas/ElevenLabsVoice", + "title": "ElevenLabsVoice" + }, + { + "$ref": "#/components/schemas/HumeVoice", + "title": "HumeVoice" + }, + { + "$ref": "#/components/schemas/LMNTVoice", + "title": "LMNTVoice" + }, + { + "$ref": "#/components/schemas/NeuphonicVoice", + "title": "NeuphonicVoice" + }, + { + "$ref": "#/components/schemas/OpenAIVoice", + "title": "OpenAIVoice" + }, + { + "$ref": "#/components/schemas/PlayHTVoice", + "title": "PlayHTVoice" + }, + { + "$ref": "#/components/schemas/WellSaidVoice", + "title": "WellSaidVoice" + }, + { + "$ref": "#/components/schemas/RimeAIVoice", + "title": "RimeAIVoice" + }, + { + "$ref": "#/components/schemas/SmallestAIVoice", + "title": "SmallestAIVoice" + }, + { + "$ref": "#/components/schemas/TavusVoice", + "title": "TavusVoice" + }, + { + "$ref": "#/components/schemas/VapiVoice", + "title": "VapiVoice" + }, + { + "$ref": "#/components/schemas/SesameVoice", + "title": "SesameVoice" + }, + { + "$ref": "#/components/schemas/InworldVoice", + "title": "InworldVoice" + }, + { + "$ref": "#/components/schemas/MinimaxVoice", + "title": "MinimaxVoice" + }, + { + "$ref": "#/components/schemas/XaiVoice", + "title": "XaiVoice" + }, + { + "$ref": "#/components/schemas/MicrosoftVoice", + "title": "MicrosoftVoice" + } + ] + }, + "observabilityPlan": { + "description": "This is the plan for observability of workflow's calls.\n\nCurrently, only Langfuse is supported.", + "oneOf": [ + { + "$ref": "#/components/schemas/LangfuseObservabilityPlan", + "title": "Langfuse" + } + ], + "allOf": [ + { + "$ref": "#/components/schemas/LangfuseObservabilityPlan" + } + ] + }, + "backgroundSound": { + "description": "This is the background sound in the call. Default for phone calls is 'office' and default for web calls is 'off'.\nYou can also provide a custom sound by providing a URL to an audio file.", + "oneOf": [ + { + "type": "string", + "enum": [ + "off", + "office" + ], + "example": "office" + }, + { + "type": "string", + "format": "uri", + "example": "https://www.soundjay.com/ambient/sounds/people-in-lounge-1.mp3" + } + ] + }, + "hooks": { + "type": "array", + "description": "This is a set of actions that will be performed on certain events.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/CallHookCallEnding", + "title": "CallHookCallEnding" + }, + { + "$ref": "#/components/schemas/CallHookAssistantSpeechInterrupted", + "title": "CallHookAssistantSpeechInterrupted" + }, + { + "$ref": "#/components/schemas/CallHookCustomerSpeechInterrupted", + "title": "CallHookCustomerSpeechInterrupted" + }, + { + "$ref": "#/components/schemas/CallHookCustomerSpeechTimeout", + "title": "CallHookCustomerSpeechTimeout" + }, + { + "$ref": "#/components/schemas/CallHookModelResponseTimeout", + "title": "CallHookModelResponseTimeout" + } + ] + } + }, + "credentials": { + "type": "array", + "description": "These are dynamic credentials that will be used for the workflow calls. By default, all the credentials are available for use in the call but you can supplement an additional credentials using this. Dynamic credentials override existing credentials.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/CreateAnthropicCredentialDTO", + "title": "AnthropicCredential" + }, + { + "$ref": "#/components/schemas/CreateAnthropicBedrockCredentialDTO", + "title": "AnthropicBedrockCredential" + }, + { + "$ref": "#/components/schemas/CreateAnyscaleCredentialDTO", + "title": "AnyscaleCredential" + }, + { + "$ref": "#/components/schemas/CreateAssemblyAICredentialDTO", + "title": "AssemblyAICredential" + }, + { + "$ref": "#/components/schemas/CreateAzureCredentialDTO", + "title": "AzureCredential" + }, + { + "$ref": "#/components/schemas/CreateAzureOpenAICredentialDTO", + "title": "AzureOpenAICredential" + }, + { + "$ref": "#/components/schemas/CreateByoSipTrunkCredentialDTO", + "title": "ByoSipTrunkCredential" + }, + { + "$ref": "#/components/schemas/CreateCartesiaCredentialDTO", + "title": "CartesiaCredential" + }, + { + "$ref": "#/components/schemas/CreateCerebrasCredentialDTO", + "title": "CerebrasCredential" + }, + { + "$ref": "#/components/schemas/CreateCloudflareCredentialDTO", + "title": "CloudflareCredential" + }, + { + "$ref": "#/components/schemas/CreateCustomLLMCredentialDTO", + "title": "CustomLLMCredential" + }, + { + "$ref": "#/components/schemas/CreateDeepgramCredentialDTO", + "title": "DeepgramCredential" + }, + { + "$ref": "#/components/schemas/CreateDeepInfraCredentialDTO", + "title": "DeepInfraCredential" + }, + { + "$ref": "#/components/schemas/CreateDeepSeekCredentialDTO", + "title": "DeepSeekCredential" + }, + { + "$ref": "#/components/schemas/CreateElevenLabsCredentialDTO", + "title": "ElevenLabsCredential" + }, + { + "$ref": "#/components/schemas/CreateGcpCredentialDTO", + "title": "GcpCredential" + }, + { + "$ref": "#/components/schemas/CreateGladiaCredentialDTO", + "title": "GladiaCredential" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelCredentialDTO", + "title": "GhlCredential" + }, + { + "$ref": "#/components/schemas/CreateGoogleCredentialDTO", + "title": "GoogleCredential" + }, + { + "$ref": "#/components/schemas/CreateGroqCredentialDTO", + "title": "GroqCredential" + }, + { + "$ref": "#/components/schemas/CreateHumeCredentialDTO", + "title": "HumeCredential" + }, + { + "$ref": "#/components/schemas/CreateInflectionAICredentialDTO", + "title": "InflectionAICredential" + }, + { + "$ref": "#/components/schemas/CreateLangfuseCredentialDTO", + "title": "LangfuseCredential" + }, + { + "$ref": "#/components/schemas/CreateLmntCredentialDTO", + "title": "LmntCredential" + }, + { + "$ref": "#/components/schemas/CreateMakeCredentialDTO", + "title": "MakeCredential" + }, + { + "$ref": "#/components/schemas/CreateMistralCredentialDTO", + "title": "MistralCredential" + }, + { + "$ref": "#/components/schemas/CreateNeuphonicCredentialDTO", + "title": "NeuphonicCredential" + }, + { + "$ref": "#/components/schemas/CreateOpenAICredentialDTO", + "title": "OpenAICredential" + }, + { + "$ref": "#/components/schemas/CreateOpenRouterCredentialDTO", + "title": "OpenRouterCredential" + }, + { + "$ref": "#/components/schemas/CreatePerplexityAICredentialDTO", + "title": "PerplexityAICredential" + }, + { + "$ref": "#/components/schemas/CreatePlayHTCredentialDTO", + "title": "PlayHTCredential" + }, + { + "$ref": "#/components/schemas/CreateRimeAICredentialDTO", + "title": "RimeAICredential" + }, + { + "$ref": "#/components/schemas/CreateRunpodCredentialDTO", + "title": "RunpodCredential" + }, + { + "$ref": "#/components/schemas/CreateS3CredentialDTO", + "title": "S3Credential" + }, + { + "$ref": "#/components/schemas/CreateS3CompatibleCredentialDTO", + "title": "S3CompatibleStorageCredential" + }, + { + "$ref": "#/components/schemas/CreateSmallestAICredentialDTO", + "title": "SmallestAICredential" + }, + { + "$ref": "#/components/schemas/CreateSpeechmaticsCredentialDTO", + "title": "SpeechmaticsCredential" + }, + { + "$ref": "#/components/schemas/CreateSonioxCredentialDTO", + "title": "SonioxCredential" + }, + { + "$ref": "#/components/schemas/CreateSupabaseCredentialDTO", + "title": "SupabaseCredential" + }, + { + "$ref": "#/components/schemas/CreateTavusCredentialDTO", + "title": "TavusCredential" + }, + { + "$ref": "#/components/schemas/CreateTogetherAICredentialDTO", + "title": "TogetherAICredential" + }, + { + "$ref": "#/components/schemas/CreateTwilioCredentialDTO", + "title": "TwilioCredential" + }, + { + "$ref": "#/components/schemas/CreateVonageCredentialDTO", + "title": "VonageCredential" + }, + { + "$ref": "#/components/schemas/CreateWebhookCredentialDTO", + "title": "WebhookCredential" + }, + { + "$ref": "#/components/schemas/CreateCustomCredentialDTO", + "title": "CustomCredential" + }, + { + "$ref": "#/components/schemas/CreateXAiCredentialDTO", + "title": "XAiCredential" + }, + { + "$ref": "#/components/schemas/CreateMicrosoftCredentialDTO", + "title": "MicrosoftCredential" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarOAuth2ClientCredentialDTO", + "title": "GoogleCalendarOAuth2ClientCredential" + }, + { + "$ref": "#/components/schemas/CreateGoogleCalendarOAuth2AuthorizationCredentialDTO", + "title": "GoogleCalendarOAuth2AuthorizationCredential" + }, + { + "$ref": "#/components/schemas/CreateGoogleSheetsOAuth2AuthorizationCredentialDTO", + "title": "GoogleSheetsOAuth2AuthorizationCredential" + }, + { + "$ref": "#/components/schemas/CreateSlackOAuth2AuthorizationCredentialDTO", + "title": "SlackOAuth2AuthorizationCredential" + }, + { + "$ref": "#/components/schemas/CreateGoHighLevelMCPCredentialDTO", + "title": "GoHighLevelMCPCredential" + }, + { + "$ref": "#/components/schemas/CreateInworldCredentialDTO", + "title": "InworldCredential" + }, + { + "$ref": "#/components/schemas/CreateMinimaxCredentialDTO", + "title": "MinimaxCredential" + }, + { + "$ref": "#/components/schemas/CreateWellSaidCredentialDTO", + "title": "WellSaidCredential" + }, + { + "$ref": "#/components/schemas/CreateEmailCredentialDTO", + "title": "EmailCredential" + }, + { + "$ref": "#/components/schemas/CreateSlackWebhookCredentialDTO", + "title": "SlackWebhookCredential" + } + ], + "discriminator": { + "propertyName": "provider", + "mapping": { + "11labs": "#/components/schemas/CreateElevenLabsCredentialDTO", + "anthropic": "#/components/schemas/CreateAnthropicCredentialDTO", + "anthropic-bedrock": "#/components/schemas/CreateAnthropicBedrockCredentialDTO", + "anyscale": "#/components/schemas/CreateAnyscaleCredentialDTO", + "assembly-ai": "#/components/schemas/CreateAssemblyAICredentialDTO", + "azure-openai": "#/components/schemas/CreateAzureOpenAICredentialDTO", + "azure": "#/components/schemas/CreateAzureCredentialDTO", + "byo-sip-trunk": "#/components/schemas/CreateByoSipTrunkCredentialDTO", + "cartesia": "#/components/schemas/CreateCartesiaCredentialDTO", + "cerebras": "#/components/schemas/CreateCerebrasCredentialDTO", + "cloudflare": "#/components/schemas/CreateCloudflareCredentialDTO", + "custom-llm": "#/components/schemas/CreateCustomLLMCredentialDTO", + "deepgram": "#/components/schemas/CreateDeepgramCredentialDTO", + "deepinfra": "#/components/schemas/CreateDeepInfraCredentialDTO", + "deep-seek": "#/components/schemas/CreateDeepSeekCredentialDTO", + "gcp": "#/components/schemas/CreateGcpCredentialDTO", + "gladia": "#/components/schemas/CreateGladiaCredentialDTO", + "gohighlevel": "#/components/schemas/CreateGoHighLevelCredentialDTO", + "google": "#/components/schemas/CreateGoogleCredentialDTO", + "groq": "#/components/schemas/CreateGroqCredentialDTO", + "inflection-ai": "#/components/schemas/CreateInflectionAICredentialDTO", + "langfuse": "#/components/schemas/CreateLangfuseCredentialDTO", + "lmnt": "#/components/schemas/CreateLmntCredentialDTO", + "make": "#/components/schemas/CreateMakeCredentialDTO", + "openai": "#/components/schemas/CreateOpenAICredentialDTO", + "openrouter": "#/components/schemas/CreateOpenRouterCredentialDTO", + "perplexity-ai": "#/components/schemas/CreatePerplexityAICredentialDTO", + "playht": "#/components/schemas/CreatePlayHTCredentialDTO", + "rime-ai": "#/components/schemas/CreateRimeAICredentialDTO", + "runpod": "#/components/schemas/CreateRunpodCredentialDTO", + "s3": "#/components/schemas/CreateS3CredentialDTO", + "s3-compatible": "#/components/schemas/CreateS3CompatibleCredentialDTO", + "supabase": "#/components/schemas/CreateSupabaseCredentialDTO", + "smallest-ai": "#/components/schemas/CreateSmallestAICredentialDTO", + "tavus": "#/components/schemas/CreateTavusCredentialDTO", + "together-ai": "#/components/schemas/CreateTogetherAICredentialDTO", + "twilio": "#/components/schemas/CreateTwilioCredentialDTO", + "vonage": "#/components/schemas/CreateVonageCredentialDTO", + "webhook": "#/components/schemas/CreateWebhookCredentialDTO", + "custom-credential": "#/components/schemas/CreateCustomCredentialDTO", + "xai": "#/components/schemas/CreateXAiCredentialDTO", + "microsoft": "#/components/schemas/CreateMicrosoftCredentialDTO", + "neuphonic": "#/components/schemas/CreateNeuphonicCredentialDTO", + "hume": "#/components/schemas/CreateHumeCredentialDTO", + "mistral": "#/components/schemas/CreateMistralCredentialDTO", + "speechmatics": "#/components/schemas/CreateSpeechmaticsCredentialDTO", + "soniox": "#/components/schemas/CreateSonioxCredentialDTO", + "google.calendar.oauth2-client": "#/components/schemas/CreateGoogleCalendarOAuth2ClientCredentialDTO", + "google.calendar.oauth2-authorization": "#/components/schemas/CreateGoogleCalendarOAuth2AuthorizationCredentialDTO", + "google.sheets.oauth2-authorization": "#/components/schemas/CreateGoogleSheetsOAuth2AuthorizationCredentialDTO", + "slack.oauth2-authorization": "#/components/schemas/CreateSlackOAuth2AuthorizationCredentialDTO", + "ghl.oauth2-authorization": "#/components/schemas/CreateGoHighLevelMCPCredentialDTO", + "inworld": "#/components/schemas/CreateInworldCredentialDTO", + "minimax": "#/components/schemas/CreateMinimaxCredentialDTO", + "wellsaid": "#/components/schemas/CreateWellSaidCredentialDTO", + "email": "#/components/schemas/CreateEmailCredentialDTO", + "slack-webhook": "#/components/schemas/CreateSlackWebhookCredentialDTO" + } + } + } + }, + "voicemailDetection": { + "description": "This is the voicemail detection plan for the workflow.", + "oneOf": [ + { + "type": "string", + "enum": [ + "off" + ] + }, + { + "$ref": "#/components/schemas/GoogleVoicemailDetectionPlan", + "title": "Google" + }, + { + "$ref": "#/components/schemas/OpenAIVoicemailDetectionPlan", + "title": "OpenAI" + }, + { + "$ref": "#/components/schemas/TwilioVoicemailDetectionPlan", + "title": "Twilio" + }, + { + "$ref": "#/components/schemas/VapiVoicemailDetectionPlan", + "title": "Vapi" + } + ] + }, + "maxDurationSeconds": { + "type": "number", + "description": "This is the maximum duration of the call in seconds.\n\nAfter this duration, the call will automatically end.\n\nDefault is 1800 (30 minutes), max is 43200 (12 hours), and min is 10 seconds.", + "minimum": 10, + "maximum": 43200, + "example": 600 + }, + "name": { + "type": "string", + "maxLength": 80 + }, + "edges": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Edge" + } + }, + "globalPrompt": { + "type": "string", + "maxLength": 5000 + }, + "server": { + "description": "This is where Vapi will send webhooks. You can find all webhooks available along with their shape in ServerMessage schema.\n\nThe order of precedence is:\n\n1. tool.server\n2. workflow.server / assistant.server\n3. phoneNumber.server\n4. org.server", + "allOf": [ + { + "$ref": "#/components/schemas/Server" + } + ] + }, + "compliancePlan": { + "description": "This is the compliance plan for the workflow. It allows you to configure HIPAA and other compliance settings.", + "allOf": [ + { + "$ref": "#/components/schemas/CompliancePlan" + } + ] + }, + "analysisPlan": { + "description": "This is the plan for analysis of workflow's calls. Stored in `call.analysis`.", + "allOf": [ + { + "$ref": "#/components/schemas/AnalysisPlan" + } + ] + }, + "artifactPlan": { + "description": "This is the plan for artifacts generated during workflow's calls. Stored in `call.artifact`.", + "allOf": [ + { + "$ref": "#/components/schemas/ArtifactPlan" + } + ] + }, + "startSpeakingPlan": { + "description": "This is the plan for when the workflow nodes should start talking.\n\nYou should configure this if you're running into these issues:\n- The assistant is too slow to start talking after the customer is done speaking.\n- The assistant is too fast to start talking after the customer is done speaking.\n- The assistant is so fast that it's actually interrupting the customer.", + "allOf": [ + { + "$ref": "#/components/schemas/StartSpeakingPlan" + } + ] + }, + "stopSpeakingPlan": { + "description": "This is the plan for when workflow nodes should stop talking on customer interruption.\n\nYou should configure this if you're running into these issues:\n- The assistant is too slow to recognize customer's interruption.\n- The assistant is too fast to recognize customer's interruption.\n- The assistant is getting interrupted by phrases that are just acknowledgments.\n- The assistant is getting interrupted by background noises.\n- The assistant is not properly stopping -- it starts talking right after getting interrupted.", + "allOf": [ + { + "$ref": "#/components/schemas/StopSpeakingPlan" + } + ] + }, + "monitorPlan": { + "description": "This is the plan for real-time monitoring of the workflow's calls.\n\nUsage:\n- To enable live listening of the workflow's calls, set `monitorPlan.listenEnabled` to `true`.\n- To enable live control of the workflow's calls, set `monitorPlan.controlEnabled` to `true`.", + "allOf": [ + { + "$ref": "#/components/schemas/MonitorPlan" + } + ] + }, + "backgroundSpeechDenoisingPlan": { + "description": "This enables filtering of noise and background speech while the user is talking.\n\nFeatures:\n- Smart denoising using Krisp\n- Fourier denoising\n\nBoth can be used together. Order of precedence:\n- Smart denoising\n- Fourier denoising", + "allOf": [ + { + "$ref": "#/components/schemas/BackgroundSpeechDenoisingPlan" + } + ] + }, + "credentialIds": { + "description": "These are the credentials that will be used for the workflow calls. By default, all the credentials are available for use in the call but you can provide a subset using this.", + "type": "array", + "items": { + "type": "string" + } + }, + "keypadInputPlan": { + "description": "This is the plan for keypad input handling during workflow calls.", + "allOf": [ + { + "$ref": "#/components/schemas/KeypadInputPlan" + } + ] + }, + "voicemailMessage": { + "type": "string", + "description": "This is the message that the assistant will say if the call is forwarded to voicemail.\n\nIf unspecified, it will hang up.", + "maxLength": 1000 + } + } + }, + "SubscriptionLimits": { + "type": "object", + "properties": { + "concurrencyBlocked": { + "type": "boolean", + "description": "True if this call was blocked by the Call Concurrency limit", + "default": false + }, + "concurrencyLimit": { + "type": "number", + "description": "Account Call Concurrency limit" + }, + "remainingConcurrentCalls": { + "type": "number", + "description": "Incremental number of concurrent calls that will be allowed, including this call" + } + } + }, + "UserMessage": { + "type": "object", + "properties": { + "role": { + "type": "string", + "description": "The role of the user in the conversation." + }, + "message": { + "type": "string", + "description": "The message content from the user." + }, + "time": { + "type": "number", + "description": "The timestamp when the message was sent." + }, + "endTime": { + "type": "number", + "description": "The timestamp when the message ended." + }, + "secondsFromStart": { + "type": "number", + "description": "The number of seconds from the start of the conversation." + }, + "duration": { + "type": "number", + "description": "The duration of the message in seconds." + }, + "isFiltered": { + "type": "boolean", + "description": "Indicates if the message was filtered for security reasons." + }, + "detectedThreats": { + "description": "List of detected security threats if the message was filtered.", + "type": "array", + "items": { + "type": "string" + } + }, + "originalMessage": { + "type": "string", + "description": "The original message before filtering (only included if content was filtered)." + }, + "metadata": { + "type": "object", + "description": "The metadata associated with the message. Currently used to store the transcriber's word level confidence." + }, + "speakerLabel": { + "type": "string", + "description": "Stable speaker label for diarized user speakers (e.g., \"Speaker 1\")." + } + }, + "required": [ + "role", + "message", + "time", + "endTime", + "secondsFromStart" + ] + }, + "SystemMessage": { + "type": "object", + "properties": { + "role": { + "type": "string", + "description": "The role of the system in the conversation." + }, + "message": { + "type": "string", + "description": "The message content from the system." + }, + "time": { + "type": "number", + "description": "The timestamp when the message was sent." + }, + "secondsFromStart": { + "type": "number", + "description": "The number of seconds from the start of the conversation." + } + }, + "required": [ + "role", + "message", + "time", + "secondsFromStart" + ] + }, + "BotMessage": { + "type": "object", + "properties": { + "role": { + "type": "string", + "description": "The role of the bot in the conversation." + }, + "message": { + "type": "string", + "description": "The message content from the bot." + }, + "time": { + "type": "number", + "description": "The timestamp when the message was sent." + }, + "endTime": { + "type": "number", + "description": "The timestamp when the message ended." + }, + "secondsFromStart": { + "type": "number", + "description": "The number of seconds from the start of the conversation." + }, + "source": { + "type": "string", + "description": "The source of the message." + }, + "duration": { + "type": "number", + "description": "The duration of the message in seconds." + }, + "assistantName": { + "type": "string", + "description": "The name of the assistant that produced this message. In a squad or\nhandoff call this is the specific sub-agent active when the message was\nspoken, letting the transcript label each message by speaker." + }, + "assistantId": { + "type": "string", + "description": "The ID of the assistant that produced this message. Stable reference for\nthe assistant named in `assistantName`." + } + }, + "required": [ + "role", + "message", + "time", + "endTime", + "secondsFromStart" + ] + }, + "ToolCallMessage": { + "type": "object", + "properties": { + "role": { + "type": "string", + "description": "The role of the tool call in the conversation." + }, + "toolCalls": { + "description": "The list of tool calls made during the conversation.", + "type": "array", + "items": { + "type": "object" + } + }, + "message": { + "type": "string", + "description": "The message content for the tool call." + }, + "time": { + "type": "number", + "description": "The timestamp when the message was sent." + }, + "secondsFromStart": { + "type": "number", + "description": "The number of seconds from the start of the conversation." + } + }, + "required": [ + "role", + "toolCalls", + "message", + "time", + "secondsFromStart" + ] + }, + "ToolCallResultMessageWarning": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The kind of warning. Currently:\n- `oversized-tool-response`: the tool's serialized response exceeded the\n recommended size and is likely to bloat the model context, increasing\n latency and risking truncation of earlier instructions.", + "enum": [ + "oversized-tool-response" + ] + }, + "tokenCount": { + "type": "number", + "description": "The estimated number of tokens in the serialized tool response." + }, + "threshold": { + "type": "number", + "description": "The threshold (in tokens) above which the warning is raised." + } + }, + "required": [ + "type", + "tokenCount", + "threshold" + ] + }, + "ToolCallResultMessage": { + "type": "object", + "properties": { + "role": { + "type": "string", + "description": "The role of the tool call result in the conversation." + }, + "toolCallId": { + "type": "string", + "description": "The ID of the tool call." + }, + "name": { + "type": "string", + "description": "The name of the tool that returned the result." + }, + "result": { + "type": "string", + "description": "The result of the tool call in JSON format." + }, + "time": { + "type": "number", + "description": "The timestamp when the message was sent." + }, + "secondsFromStart": { + "type": "number", + "description": "The number of seconds from the start of the conversation." + }, + "metadata": { + "type": "object", + "description": "The metadata for the tool call result." + }, + "warnings": { + "description": "Warnings raised for this tool call result, e.g. when the response is\nlarger than recommended for voice AI context windows.", + "type": "array", + "items": { + "$ref": "#/components/schemas/ToolCallResultMessageWarning" + } + } + }, + "required": [ + "role", + "toolCallId", + "name", + "result", + "time", + "secondsFromStart" + ] + }, + "TransportCost": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "This is the type of cost, always 'transport' for this class.", + "enum": [ + "transport" + ] + }, + "provider": { + "type": "string", + "enum": [ + "daily", + "vapi.websocket", + "twilio", + "vonage", + "telnyx", + "vapi.sip" + ] + }, + "minutes": { + "type": "number", + "description": "This is the minutes of `transport` usage. This should match `call.endedAt` - `call.startedAt`." + }, + "cost": { + "type": "number", + "description": "This is the cost of the component in USD." + } + }, + "required": [ + "type", + "minutes", + "cost" + ] + }, + "TranscriberCost": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "This is the type of cost, always 'transcriber' for this class.", + "enum": [ + "transcriber" + ] + }, + "transcriber": { + "type": "object", + "description": "This is the transcriber that was used during the call.\n\nThis matches one of the below:\n- `call.assistant.transcriber`,\n- `call.assistantId->transcriber`,\n- `call.squad[n].assistant.transcriber`,\n- `call.squad[n].assistantId->transcriber`,\n- `call.squadId->[n].assistant.transcriber`,\n- `call.squadId->[n].assistantId->transcriber`." + }, + "minutes": { + "type": "number", + "description": "This is the minutes of `transcriber` usage. This should match `call.endedAt` - `call.startedAt` for single assistant calls, while squad calls will have multiple transcriber costs one for each assistant that was used." + }, + "cost": { + "type": "number", + "description": "This is the cost of the component in USD." + } + }, + "required": [ + "type", + "transcriber", + "minutes", + "cost" + ] + }, + "ModelCost": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "This is the type of cost, always 'model' for this class.", + "enum": [ + "model" + ] + }, + "model": { + "type": "object", + "description": "This is the model that was used during the call.\n\nThis matches one of the following:\n- `call.assistant.model`,\n- `call.assistantId->model`,\n- `call.squad[n].assistant.model`,\n- `call.squad[n].assistantId->model`,\n- `call.squadId->[n].assistant.model`,\n- `call.squadId->[n].assistantId->model`." + }, + "promptTokens": { + "type": "number", + "description": "This is the number of prompt tokens used in the call. These should be total prompt tokens used in the call for single assistant calls, while squad calls will have multiple model costs one for each assistant that was used." + }, + "completionTokens": { + "type": "number", + "description": "This is the number of completion tokens generated in the call. These should be total completion tokens used in the call for single assistant calls, while squad calls will have multiple model costs one for each assistant that was used." + }, + "cachedPromptTokens": { + "type": "number", + "description": "This is the number of cached prompt tokens used in the call. This is only applicable to certain providers (e.g., OpenAI, Azure OpenAI) that support prompt caching. Cached tokens are billed at a discounted rate." + }, + "reasoningTokens": { + "type": "number", + "description": "This is the number of reasoning tokens generated in the call. This is only applicable to reasoning models (e.g., OpenAI o-series, GPT-5) on providers that report them.\n\nThis is a **subset of `completionTokens`**, not an addition to it: reasoning tokens are already counted in `completionTokens` and are already billed at the output-token rate. It is reported separately for visibility only and does not affect `cost`." + }, + "cost": { + "type": "number", + "description": "This is the cost of the component in USD." + } + }, + "required": [ + "type", + "model", + "promptTokens", + "completionTokens", + "cost" + ] + }, + "VoiceCost": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "This is the type of cost, always 'voice' for this class.", + "enum": [ + "voice" + ] + }, + "voice": { + "type": "object", + "description": "This is the voice that was used during the call.\n\nThis matches one of the following:\n- `call.assistant.voice`,\n- `call.assistantId->voice`,\n- `call.squad[n].assistant.voice`,\n- `call.squad[n].assistantId->voice`,\n- `call.squadId->[n].assistant.voice`,\n- `call.squadId->[n].assistantId->voice`." + }, + "characters": { + "type": "number", + "description": "This is the number of characters that were generated during the call. These should be total characters used in the call for single assistant calls, while squad calls will have multiple voice costs one for each assistant that was used." + }, + "cost": { + "type": "number", + "description": "This is the cost of the component in USD." + } + }, + "required": [ + "type", + "voice", + "characters", + "cost" + ] + }, + "ChatCost": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "This is the type of cost, always 'chat' for this class.", + "enum": [ + "chat" + ] + }, + "cost": { + "type": "number", + "description": "This is the cost of the component in USD." + } + }, + "required": [ + "type", + "cost" + ] + }, + "VapiCost": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "This is the type of cost, always 'vapi' for this class.", + "enum": [ + "vapi" + ] + }, + "subType": { + "type": "string", + "description": "This is the sub type of the cost.", + "enum": [ + "normal", + "overage" + ] + }, + "minutes": { + "type": "number", + "description": "This is the minutes of Vapi usage. This should match `call.endedAt` - `call.startedAt`." + }, + "cost": { + "type": "number", + "description": "This is the cost of the component in USD." + } + }, + "required": [ + "type", + "subType", + "minutes", + "cost" + ] + }, + "VoicemailDetectionCost": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "This is the type of cost, always 'voicemail-detection' for this class.", + "enum": [ + "voicemail-detection" + ] + }, + "model": { + "type": "object", + "description": "This is the model that was used to perform the analysis." + }, + "provider": { + "type": "string", + "description": "This is the provider that was used to detect the voicemail.", + "enum": [ + "twilio", + "google", + "openai", + "vapi" + ] + }, + "promptTextTokens": { + "type": "number", + "description": "This is the number of prompt text tokens used in the voicemail detection." + }, + "promptAudioTokens": { + "type": "number", + "description": "This is the number of prompt audio tokens used in the voicemail detection." + }, + "completionTextTokens": { + "type": "number", + "description": "This is the number of completion text tokens used in the voicemail detection." + }, + "completionAudioTokens": { + "type": "number", + "description": "This is the number of completion audio tokens used in the voicemail detection." + }, + "cost": { + "type": "number", + "description": "This is the cost of the component in USD." + } + }, + "required": [ + "type", + "model", + "provider", + "promptTextTokens", + "promptAudioTokens", + "completionTextTokens", + "completionAudioTokens", + "cost" + ] + }, + "StructuredOutputCostBreakdown": { + "type": "object", + "properties": { + "structuredOutputId": { + "type": "string", + "description": "This is the unique identifier of the structured output that produced this cost." + }, + "name": { + "type": "string", + "description": "This is the name of the structured output, so this breakdown is readable without looking the id up." + }, + "cost": { + "type": "number", + "description": "This is the cost in USD of evaluating this structured output." + }, + "promptTokens": { + "type": "number", + "description": "This is the number of prompt tokens used to evaluate this structured output." + }, + "completionTokens": { + "type": "number", + "description": "This is the number of completion tokens generated for this structured output." + }, + "cachedPromptTokens": { + "type": "number", + "description": "This is the number of cached prompt tokens used to evaluate this structured output. This is a subset of `promptTokens`, not an addition to it." + } + }, + "required": [ + "structuredOutputId", + "name", + "cost", + "promptTokens", + "completionTokens" + ] + }, + "AnalysisCost": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "This is the type of cost, always 'analysis' for this class.", + "enum": [ + "analysis" + ] + }, + "analysisType": { + "type": "string", + "description": "This is the type of analysis performed.", + "enum": [ + "summary", + "structuredData", + "successEvaluation", + "structuredOutput" + ] + }, + "model": { + "type": "object", + "description": "This is the model that was used to perform the analysis." + }, + "promptTokens": { + "type": "number", + "description": "This is the number of prompt tokens used in the analysis." + }, + "completionTokens": { + "type": "number", + "description": "This is the number of completion tokens generated in the analysis." + }, + "cachedPromptTokens": { + "type": "number", + "description": "This is the number of cached prompt tokens used in the analysis. This is only applicable to certain providers (e.g., OpenAI, Azure OpenAI) that support prompt caching. Cached tokens are billed at a discounted rate." + }, + "structuredOutputBreakdown": { + "description": "This is the per-structured-output breakdown of this cost. The `cost`, `promptTokens`, `completionTokens` and `cachedPromptTokens` above are the sums of these rows.\n\nThis is only set when `analysisType` is `structuredOutput`, and it is omitted entirely rather than partially populated, so when it is present the rows always reconcile to the totals above.\n\nA structured output that was skipped, or that extracts via regex, makes no LLM call and so has no row here — this is not a complete list of the call's configured structured outputs. There is one row per evaluation, so a `structuredOutputId` can appear more than once if it was evaluated more than once; sum the rows rather than indexing them by id.", + "type": "array", + "items": { + "$ref": "#/components/schemas/StructuredOutputCostBreakdown" + } + }, + "cost": { + "type": "number", + "description": "This is the cost of the component in USD." + } + }, + "required": [ + "type", + "analysisType", + "model", + "promptTokens", + "completionTokens", + "cost" + ] + }, + "AudioFormat": { + "type": "object", + "properties": { + "sampleRate": { + "type": "number", + "description": "This is the sample rate of the call.\n\n@default 16000", + "minimum": 0, + "maximum": 192000 + }, + "format": { + "type": "object", + "description": "This is the audio format of the call.\n\n@default 'pcm_s16le'", + "enum": [ + "pcm_s16le", + "mulaw" + ] + }, + "container": { + "type": "string", + "description": "This is the container format of the call.\n\n@default 'raw'", + "enum": [ + "raw" + ] + } + }, + "required": [ + "sampleRate", + "format" + ] + }, + "VapiWebsocketTransport": { + "type": "object", + "properties": { + "conversationType": { + "type": "string", + "description": "This is the conversation type of the call (ie, voice or chat).", + "default": "voice", + "enum": [ + "voice" + ] + }, + "provider": { + "type": "string", + "description": "Vapi websocket transport provider", + "enum": [ + "vapi.websocket" + ] + }, + "audioFormat": { + "description": "This is the audio format of the call. Defaults to 16KHz raw pcm_s16le", + "allOf": [ + { + "$ref": "#/components/schemas/AudioFormat" + } + ] + } + }, + "required": [ + "provider" + ] + }, + "VapiWebCallTransport": { + "type": "object", + "properties": { + "conversationType": { + "type": "string", + "description": "This is the conversation type of the call (ie, voice or chat).", + "default": "voice", + "enum": [ + "voice" + ] + }, + "provider": { + "type": "string", + "description": "Vapi web call transport provider", + "enum": [ + "daily" + ] + }, + "roomDeleteOnUserLeaveEnabled": { + "type": "boolean", + "description": "This determines whether the daily room will be deleted and all participants will be kicked once the user leaves the room.\nIf set to `false`, the room will be kept alive even after the user leaves, allowing clients to reconnect to the same room.\nIf set to `true`, the room will be deleted and reconnection will not be allowed.\n\nDefaults to `true`.", + "example": true, + "default": true + }, + "callToken": { + "type": "string", + "description": "This is the meeting token the web client should join the call with.\nWhen video recording is enabled, joining with this token starts the cloud\nrecording automatically server-side, which is more reliable than the\nclient starting it after joining. Set by the server; only present when\nvideo recording is enabled." + }, + "callUrl": { + "type": "string", + "description": "This is the URL of the web call." + }, + "callSipUri": { + "type": "string", + "description": "This is the SIP URI of the web call." + } + }, + "required": [ + "provider" + ] + }, + "TwilioTransport": { + "type": "object", + "properties": { + "conversationType": { + "type": "string", + "description": "This is the conversation type of the call (ie, voice or chat).", + "default": "voice", + "enum": [ + "voice" + ] + }, + "provider": { + "type": "string", + "description": "Twilio transport provider", + "enum": [ + "twilio" + ] + }, + "accountSid": { + "type": "string", + "description": "This is the account SID of the Twilio account." + }, + "callSid": { + "type": "string", + "description": "This is the call SID of the Twilio call." + }, + "callToken": { + "type": "string", + "description": "This is the call token of the Twilio call." + }, + "forwardedFrom": { + "type": "string", + "description": "This is the phone number from which the call was forwarded.\nUndefined if the call was not forwarded." + } + }, + "required": [ + "provider" + ] + }, + "TelnyxTransport": { + "type": "object", + "properties": { + "conversationType": { + "type": "string", + "description": "This is the conversation type of the call (ie, voice or chat).", + "default": "voice", + "enum": [ + "voice" + ] + }, + "provider": { + "type": "string", + "description": "Telnyx transport provider", + "enum": [ + "telnyx" + ] + }, + "callControlId": { + "type": "string", + "description": "This is the call control ID of the Telnyx call." + }, + "callLegId": { + "type": "string", + "description": "This is the call leg ID of the Telnyx call." + }, + "callSessionId": { + "type": "string", + "description": "This is the call session ID of the Telnyx call." + } + }, + "required": [ + "provider" + ] + }, + "VapiSipTransport": { + "type": "object", + "properties": { + "conversationType": { + "type": "string", + "description": "This is the conversation type of the call (ie, voice or chat).", + "default": "voice", + "enum": [ + "voice" + ] + }, + "provider": { + "type": "string", + "description": "Vapi SIP transport provider", + "enum": [ + "vapi.sip" + ] + }, + "dialTimeout": { + "type": "number", + "description": "This sets the timeout for outbound dial operations in seconds. This is the duration the call will ring before timing out.\n\n@default 60", + "minimum": 1, + "maximum": 600, + "default": 60 + }, + "sbcCallSid": { + "type": "string", + "description": "This is the call SID of the Vapi SIP call." + }, + "callSid": { + "type": "string", + "description": "This is the call ID of the Vapi SIP call." + } + }, + "required": [ + "provider" + ] + }, + "VonageTransport": { + "type": "object", + "properties": { + "conversationType": { + "type": "string", + "description": "This is the conversation type of the call (ie, voice or chat).", + "default": "voice", + "enum": [ + "voice" + ] + }, + "provider": { + "type": "string", + "description": "Vonage transport provider", + "enum": [ + "vonage" + ] + }, + "conversationUUID": { + "type": "string", + "description": "This is the conversation UUID of the Vonage call." + }, + "callUUID": { + "type": "string", + "description": "This is the call ID of the Vonage call." + } + }, + "required": [ + "provider" + ] + }, + "AnalysisCostBreakdown": { + "type": "object", + "properties": { + "summary": { + "type": "number", + "description": "This is the cost to summarize the call." + }, + "summaryPromptTokens": { + "type": "number", + "description": "This is the number of prompt tokens used to summarize the call." + }, + "summaryCompletionTokens": { + "type": "number", + "description": "This is the number of completion tokens used to summarize the call." + }, + "summaryCachedPromptTokens": { + "type": "number", + "description": "This is the number of cached prompt tokens used to summarize the call." + }, + "structuredData": { + "type": "number", + "description": "This is the cost to extract structured data from the call." + }, + "structuredDataPromptTokens": { + "type": "number", + "description": "This is the number of prompt tokens used to extract structured data from the call." + }, + "structuredDataCompletionTokens": { + "type": "number", + "description": "This is the number of completion tokens used to extract structured data from the call." + }, + "structuredDataCachedPromptTokens": { + "type": "number", + "description": "This is the number of cached prompt tokens used to extract structured data from the call." + }, + "successEvaluation": { + "type": "number", + "description": "This is the cost to evaluate if the call was successful." + }, + "successEvaluationPromptTokens": { + "type": "number", + "description": "This is the number of prompt tokens used to evaluate if the call was successful." + }, + "successEvaluationCompletionTokens": { + "type": "number", + "description": "This is the number of completion tokens used to evaluate if the call was successful." + }, + "successEvaluationCachedPromptTokens": { + "type": "number", + "description": "This is the number of cached prompt tokens used to evaluate if the call was successful." + }, + "structuredOutput": { + "type": "number", + "description": "This is the cost to evaluate structuredOutputs from the call." + }, + "structuredOutputPromptTokens": { + "type": "number", + "description": "This is the number of prompt tokens used to evaluate structuredOutputs from the call." + }, + "structuredOutputCompletionTokens": { + "type": "number", + "description": "This is the number of completion tokens used to evaluate structuredOutputs from the call." + }, + "structuredOutputCachedPromptTokens": { + "type": "number", + "description": "This is the number of cached prompt tokens used to evaluate structuredOutputs from the call." + } + } + }, + "CostBreakdown": { + "type": "object", + "properties": { + "transport": { + "type": "number", + "description": "This is the cost of the transport provider, like Twilio or Vonage." + }, + "stt": { + "type": "number", + "description": "This is the cost of the speech-to-text service." + }, + "llm": { + "type": "number", + "description": "This is the cost of the language model." + }, + "tts": { + "type": "number", + "description": "This is the cost of the text-to-speech service." + }, + "vapi": { + "type": "number", + "description": "This is the cost of Vapi." + }, + "chat": { + "type": "number", + "description": "This is the cost of chat interactions." + }, + "total": { + "type": "number", + "description": "This is the total cost of the call." + }, + "llmPromptTokens": { + "type": "number", + "description": "This is the LLM prompt tokens used for the call." + }, + "llmCompletionTokens": { + "type": "number", + "description": "This is the LLM completion tokens used for the call." + }, + "llmCachedPromptTokens": { + "type": "number", + "description": "This is the LLM cached prompt tokens used for the call." + }, + "ttsCharacters": { + "type": "number", + "description": "This is the TTS characters used for the call." + }, + "analysisCostBreakdown": { + "description": "This is the cost of the analysis.", + "allOf": [ + { + "$ref": "#/components/schemas/AnalysisCostBreakdown" + } + ] + } + } + }, + "Analysis": { + "type": "object", + "properties": { + "summary": { + "type": "string", + "description": "This is the summary of the call. Customize by setting `assistant.analysisPlan.summaryPrompt`." + }, + "structuredData": { + "type": "object", + "description": "This is the structured data extracted from the call. Customize by setting `assistant.analysisPlan.structuredDataPrompt` and/or `assistant.analysisPlan.structuredDataSchema`." + }, + "structuredDataMulti": { + "description": "This is the structured data catalog of the call. Customize by setting `assistant.analysisPlan.structuredDataMultiPlan`.", + "type": "array", + "items": { + "type": "object" + } + }, + "successEvaluation": { + "type": "string", + "description": "This is the evaluation of the call. Customize by setting `assistant.analysisPlan.successEvaluationPrompt` and/or `assistant.analysisPlan.successEvaluationRubric`." + } + } + }, + "MonitorResult": { + "type": "object", + "properties": { + "monitorId": { + "type": "string" + }, + "filterPassed": { + "type": "boolean" + } + }, + "required": [ + "monitorId", + "filterPassed" + ] + }, + "Monitor": { + "type": "object", + "properties": { + "monitors": { + "type": "array", + "items": { + "$ref": "#/components/schemas/MonitorResult" + } + }, + "listenUrl": { + "type": "string", + "description": "This is the URL where the assistant's calls can be listened to in real-time. To enable, set `assistant.monitorPlan.listenEnabled` to `true`." + }, + "controlUrl": { + "type": "string", + "description": "This is the URL where the assistant's calls can be controlled in real-time. To enable, set `assistant.monitorPlan.controlEnabled` to `true`." + } + } + }, + "SkippedStructuredOutput": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "This is the name of the structured output that was skipped." + }, + "unmetCondition": { + "description": "This is the first condition that was not met. Conditions use AND semantics, so\nevaluation stops as soon as one condition does not pass.", + "oneOf": [ + { + "$ref": "#/components/schemas/MinMessagesCondition", + "title": "MinMessagesCondition" + }, + { + "$ref": "#/components/schemas/MinCallDurationCondition", + "title": "MinCallDurationCondition" + }, + { + "$ref": "#/components/schemas/EndedReasonCondition", + "title": "EndedReasonCondition" + } + ] + } + }, + "required": [ + "name", + "unmetCondition" + ] + }, + "TransferArtifact": { + "type": "object", + "properties": { + "destination": { + "description": "The transfer destination (phone number or SIP URI).", + "oneOf": [ + { + "$ref": "#/components/schemas/TransferDestinationNumber", + "title": "Number" + }, + { + "$ref": "#/components/schemas/TransferDestinationSip", + "title": "Sip" + } + ] + }, + "mode": { + "type": "string", + "description": "The transfer mode (e.g. warm-transfer-experimental, blind-transfer).", + "enum": [ + "blind-transfer", + "blind-transfer-add-summary-to-sip-header", + "warm-transfer-say-message", + "warm-transfer-say-summary", + "warm-transfer-twiml", + "warm-transfer-wait-for-operator-to-speak-first-and-then-say-message", + "warm-transfer-wait-for-operator-to-speak-first-and-then-say-summary", + "warm-transfer-experimental" + ] + }, + "transcript": { + "type": "string", + "description": "Flat-text transcript / announcement preview of the transfer." + }, + "status": { + "type": "string", + "description": "The terminal status of the transfer, rendered as the status line.", + "enum": [ + "connected", + "no-answer", + "busy", + "voicemail", + "failed", + "completed", + "cancelled" + ] + }, + "messages": { + "type": "array", + "description": "The agent↔operator conversation captured during a\nwarm-transfer-experimental, rendered as bubbles.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/UserMessage", + "title": "UserMessage" + }, + { + "$ref": "#/components/schemas/SystemMessage", + "title": "SystemMessage" + }, + { + "$ref": "#/components/schemas/BotMessage", + "title": "BotMessage" + }, + { + "$ref": "#/components/schemas/ToolCallMessage", + "title": "ToolCallMessage" + }, + { + "$ref": "#/components/schemas/ToolCallResultMessage", + "title": "ToolCallResultMessage" + } + ] + } + } + }, + "required": [ + "destination" + ] + }, + "Mono": { + "type": "object", + "properties": { + "combinedUrl": { + "type": "string", + "description": "This is the combined recording url for the call. To enable, set `assistant.artifactPlan.recordingEnabled`." + }, + "assistantUrl": { + "type": "string", + "description": "This is the mono recording url for the assistant. To enable, set `assistant.artifactPlan.recordingEnabled`." + }, + "customerUrl": { + "type": "string", + "description": "This is the mono recording url for the customer. To enable, set `assistant.artifactPlan.recordingEnabled`." + } + } + }, + "Recording": { + "type": "object", + "properties": { + "stereoUrl": { + "type": "string", + "description": "This is the stereo recording url for the call. To enable, set `assistant.artifactPlan.recordingEnabled`." + }, + "videoUrl": { + "type": "string", + "description": "This is the video recording url for the call. To enable, set `assistant.artifactPlan.videoRecordingEnabled`." + }, + "videoRecordingStartDelaySeconds": { + "type": "number", + "description": "This is video recording start delay in ms. To enable, set `assistant.artifactPlan.videoRecordingEnabled`. This can be used to align the playback of the recording with artifact.messages timestamps." + }, + "mono": { + "description": "This is the mono recording url for the call. To enable, set `assistant.artifactPlan.recordingEnabled`.", + "allOf": [ + { + "$ref": "#/components/schemas/Mono" + } + ] + } + } + }, + "NodeArtifact": { + "type": "object", + "properties": { + "messages": { + "type": "array", + "description": "These are the messages that were spoken during the node.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/UserMessage", + "title": "UserMessage" + }, + { + "$ref": "#/components/schemas/SystemMessage", + "title": "SystemMessage" + }, + { + "$ref": "#/components/schemas/BotMessage", + "title": "BotMessage" + }, + { + "$ref": "#/components/schemas/ToolCallMessage", + "title": "ToolCallMessage" + }, + { + "$ref": "#/components/schemas/ToolCallResultMessage", + "title": "ToolCallResultMessage" + } + ] + } + }, + "nodeName": { + "type": "string", + "description": "This is the node name." + }, + "variableValues": { + "type": "object", + "description": "These are the variable values that were extracted from the node." + } + } + }, + "AssistantActivation": { + "type": "object", + "properties": { + "assistantVersion": { + "type": "string", + "nullable": true, + "description": "This is the version label (e.g. `v3`) of the assistant active when\nthe activation row was recorded. `null` for inline assistants,\norgs not on assistant versioning, and parent assistants that have\nnot yet been published under it." + }, + "assistantName": { + "type": "string", + "description": "This is the name of the assistant that was active during the call." + }, + "assistantId": { + "type": "string", + "description": "This is the ID of the assistant that was active during the call." + } + }, + "required": [ + "assistantName" + ] + }, + "TurnLatency": { + "type": "object", + "properties": { + "modelLatency": { + "type": "number", + "description": "This is the model latency for the first token." + }, + "voiceLatency": { + "type": "number", + "description": "This is the voice latency from the model output." + }, + "transcriberLatency": { + "type": "number", + "description": "This is the transcriber latency from the user speech." + }, + "endpointingLatency": { + "type": "number", + "description": "This is the endpointing latency." + }, + "turnLatency": { + "type": "number", + "description": "This is the latency for the whole turn." + } + } + }, + "PerformanceMetrics": { + "type": "object", + "properties": { + "turnLatencies": { + "description": "These are the individual latencies for each turn.", + "type": "array", + "items": { + "$ref": "#/components/schemas/TurnLatency" + } + }, + "modelLatencyAverage": { + "type": "number", + "description": "This is the average latency for the model to output the first token." + }, + "voiceLatencyAverage": { + "type": "number", + "description": "This is the average latency for the text to speech." + }, + "transcriberLatencyAverage": { + "type": "number", + "description": "This is the average latency for the transcriber." + }, + "endpointingLatencyAverage": { + "type": "number", + "description": "This is the average latency for the endpointing." + }, + "turnLatencyAverage": { + "type": "number", + "description": "This is the average latency for complete turns." + }, + "fromTransportLatencyAverage": { + "type": "number", + "description": "This is the average latency for packets received from the transport provider in milliseconds." + }, + "toTransportLatencyAverage": { + "type": "number", + "description": "This is the average latency for packets sent to the transport provider in milliseconds." + }, + "numUserInterrupted": { + "type": "number", + "description": "This is the number of times the user was interrupted by the assistant during the call." + }, + "numAssistantInterrupted": { + "type": "number", + "description": "This is the number of times the assistant was interrupted by the user during the call." + } + } + }, + "Artifact": { + "type": "object", + "properties": { + "messages": { + "type": "array", + "description": "These are the messages that were spoken during the call.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/UserMessage", + "title": "UserMessage" + }, + { + "$ref": "#/components/schemas/SystemMessage", + "title": "SystemMessage" + }, + { + "$ref": "#/components/schemas/BotMessage", + "title": "BotMessage" + }, + { + "$ref": "#/components/schemas/ToolCallMessage", + "title": "ToolCallMessage" + }, + { + "$ref": "#/components/schemas/ToolCallResultMessage", + "title": "ToolCallResultMessage" + } + ] + } + }, + "messagesOpenAIFormatted": { + "description": "These are the messages that were spoken during the call, formatted for OpenAI.", + "type": "array", + "items": { + "$ref": "#/components/schemas/OpenAIMessage" + } + }, + "skippedStructuredOutputs": { + "type": "object", + "description": "Structured outputs skipped because their conditions were not met, keyed by saved or runtime output ID.", + "additionalProperties": { + "$ref": "#/components/schemas/SkippedStructuredOutput" + } + }, + "transfers": { + "description": "These are the transfer records for the call's transfer attempts (warm and blind), including\ndestination, mode, and status. Warm transfer records also include transcripts and messages.", + "type": "array", + "items": { + "$ref": "#/components/schemas/TransferArtifact" + } + }, + "recordingUrl": { + "type": "string", + "description": "This is the recording url for the call. To enable, set `assistant.artifactPlan.recordingEnabled`.", + "deprecated": true + }, + "stereoRecordingUrl": { + "type": "string", + "description": "This is the stereo recording url for the call. To enable, set `assistant.artifactPlan.recordingEnabled`.", + "deprecated": true + }, + "videoRecordingUrl": { + "type": "string", + "description": "This is video recording url for the call. To enable, set `assistant.artifactPlan.videoRecordingEnabled`.", + "deprecated": true + }, + "videoRecordingStartDelaySeconds": { + "type": "number", + "description": "This is video recording start delay in ms. To enable, set `assistant.artifactPlan.videoRecordingEnabled`. This can be used to align the playback of the recording with artifact.messages timestamps.", + "deprecated": true + }, + "recording": { + "description": "This is the recording url for the call. To enable, set `assistant.artifactPlan.recordingEnabled`.", + "allOf": [ + { + "$ref": "#/components/schemas/Recording" + } + ] + }, + "transcript": { + "type": "string", + "description": "This is the transcript of the call. This is derived from `artifact.messages` but provided for convenience." + }, + "pcapUrl": { + "type": "string", + "description": "This is the packet capture url for the call. This is only available for `phone` type calls where phone number's provider is `vapi` or `byo-phone-number`." + }, + "logUrl": { + "type": "string", + "description": "This is the url for the call logs. This includes all logging output during the call for debugging purposes." + }, + "nodes": { + "description": "This is the history of workflow nodes that were executed during the call.", + "type": "array", + "items": { + "$ref": "#/components/schemas/NodeArtifact" + } + }, + "assistantActivations": { + "description": "Ordered list of assistants that were active during the call, including after transfers and handoffs.", + "type": "array", + "items": { + "$ref": "#/components/schemas/AssistantActivation" + } + }, + "variableValues": { + "type": "object", + "description": "These are the variable values at the end of the workflow execution." + }, + "performanceMetrics": { + "description": "This is the performance metrics for the call. It contains the turn latency, broken down by component.", + "allOf": [ + { + "$ref": "#/components/schemas/PerformanceMetrics" + } + ] + }, + "structuredOutputs": { + "type": "object", + "description": "These are the structured outputs that will be extracted from the call.\nTo enable, set `assistant.artifactPlan.structuredOutputIds` with the IDs of the structured outputs you want to extract." + }, + "scorecards": { + "type": "object", + "description": "These are the scorecards that have been evaluated based on the structured outputs extracted during the call.\nTo enable, set `assistant.artifactPlan.scorecardIds` or `assistant.artifactPlan.scorecards` with the IDs or objects of the scorecards you want to evaluate." + }, + "structuredOutputsLastUpdatedAt": { + "format": "date-time", + "type": "string", + "description": "This is when the structured outputs were last updated" + }, + "presignedMonoUrl": { + "type": "string", + "description": "This is a presigned URL to download the mono recording without\nauthentication. Populated on API responses and server messages; never\nstored. Expires at `presignedUrlsExpiresAt` — after that, use\n`GET /call/{id}/mono-recording`." + }, + "presignedStereoUrl": { + "type": "string", + "description": "This is a presigned URL to download the stereo recording without\nauthentication. Expires at `presignedUrlsExpiresAt` — after that, use\n`GET /call/{id}/stereo-recording`." + }, + "presignedVideoUrl": { + "type": "string", + "description": "This is a presigned URL to download the video recording without\nauthentication. Expires at `presignedUrlsExpiresAt` — after that, use\n`GET /call/{id}/video-recording`." + }, + "presignedAssistantUrl": { + "type": "string", + "description": "This is a presigned URL to download the assistant-channel mono recording\nwithout authentication. Expires at `presignedUrlsExpiresAt`." + }, + "presignedCustomerUrl": { + "type": "string", + "description": "This is a presigned URL to download the customer-channel mono recording\nwithout authentication. Expires at `presignedUrlsExpiresAt`." + }, + "presignedPcapUrl": { + "type": "string", + "description": "This is a presigned URL to download the packet capture without\nauthentication. Expires at `presignedUrlsExpiresAt`." + }, + "presignedLogUrl": { + "type": "string", + "description": "This is a presigned URL to download the call logs without\nauthentication. Expires at `presignedUrlsExpiresAt`." + }, + "presignedUrlsExpiresAt": { + "type": "string", + "description": "This is when the presigned URLs above expire, as an ISO 8601 timestamp.\nThe raw `*Url` fields remain the stable identifiers and do not expire.\nPresigned URLs are regenerated per response and per webhook delivery, so\nvalues differ across retries." + } + } + }, + "RecordingConsent": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "This is the type of recording consent.", + "enum": [ + "stay-on-line", + "verbal" + ] + }, + "grantedAt": { + "format": "date-time", + "type": "string", + "description": "This is the date and time the recording consent was granted.\nIf not specified, it means the recording consent was not granted." + } + }, + "required": [ + "type" + ] + }, + "Compliance": { + "type": "object", + "properties": { + "recordingConsent": { + "description": "This is the recording consent of the call. Configure in `assistant.compliancePlan.recordingConsentPlan`.", + "allOf": [ + { + "$ref": "#/components/schemas/RecordingConsent" + } + ] + } + } + }, + "WorkflowOverrides": { + "type": "object", + "properties": { + "variableValues": { + "type": "object", + "description": "These are values that will be used to replace the template variables in the workflow messages and other text-based fields.\nThis uses LiquidJS syntax. https://liquidjs.com/tutorials/intro-to-liquid.html\n\nSo for example, `{{ name }}` will be replaced with the value of `name` in `variableValues`.\n`{{\"now\" | date: \"%b %d, %Y, %I:%M %p\", \"America/New_York\"}}` will be replaced with the current date and time in New York.\n Some VAPI reserved defaults:\n - *customer* - the customer object" + } + } + }, + "TransferPhoneNumberHookAction": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "This is the type of action - must be \"transfer\"", + "enum": [ + "transfer" + ] + }, + "destination": { + "description": "This is the destination details for the transfer - can be a phone number or SIP URI", + "oneOf": [ + { + "$ref": "#/components/schemas/TransferDestinationNumber", + "title": "NumberTransferDestination" + }, + { + "$ref": "#/components/schemas/TransferDestinationSip", + "title": "SipTransferDestination" + } + ] + } + }, + "required": [ + "type" + ] + }, + "SayPhoneNumberHookAction": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "This is the type of action - must be \"say\"", + "enum": [ + "say" + ] + }, + "exact": { + "type": "string", + "description": "This is the message to say", + "maxLength": 4000 + } + }, + "required": [ + "type", + "exact" + ] + }, + "PhoneNumberCallRingingHookFilter": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "This is the type of filter - matches when the specified field starts with any of the given prefixes", + "enum": [ + "startsWith" + ], + "maxLength": 1000 + }, + "key": { + "type": "string", + "description": "The field to check. Currently only \"number\" (the caller's phone number) is supported.", + "enum": [ + "number" + ], + "maxLength": 1000 + }, + "startsWith": { + "type": "array", + "description": "Array of prefixes to match. Do not include the + prefix. Inbound calls from numbers starting with any of these prefixes will trigger the hook actions.", + "maxLength": 20, + "items": { + "type": "string", + "maxLength": 20 + }, + "example": [ + "91", + "86", + "7" + ] + } + }, + "required": [ + "type", + "key", + "startsWith" + ] + }, + "PhoneNumberHookCallRinging": { + "type": "object", + "properties": { + "on": { + "type": "string", + "description": "This is the event to trigger the hook on", + "enum": [ + "call.ringing" + ], + "maxLength": 1000 + }, + "filters": { + "type": "array", + "description": "Optional filters to decide when to trigger the hook. Currently supports filtering by caller country code.", + "items": { + "$ref": "#/components/schemas/PhoneNumberCallRingingHookFilter" + } + }, + "do": { + "type": "array", + "description": "Only the first action will be executed. Additional actions will be ignored.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/TransferPhoneNumberHookAction", + "title": "TransferPhoneNumberHookAction" + }, + { + "$ref": "#/components/schemas/SayPhoneNumberHookAction", + "title": "SayPhoneNumberHookAction" + } + ] + } + } + }, + "required": [ + "on", + "do" + ] + }, + "PhoneNumberCallEndingHookFilter": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "This is the type of filter - currently only \"oneOf\" is supported", + "enum": [ + "oneOf" + ], + "maxLength": 1000 + }, + "key": { + "type": "string", + "description": "This is the key to filter on - only \"call.endedReason\" is allowed for phone number call ending hooks", + "enum": [ + "call.endedReason" + ], + "maxLength": 1000 + }, + "oneOf": { + "type": "array", + "description": "This is the array of assistant-request related ended reasons to match against", + "enum": [ + "assistant-request-failed", + "assistant-request-returned-error", + "assistant-request-returned-unspeakable-error", + "assistant-request-returned-invalid-assistant", + "assistant-request-returned-no-assistant", + "assistant-request-returned-forwarding-phone-number" + ], + "items": { + "type": "string", + "enum": [ + "assistant-request-failed", + "assistant-request-returned-error", + "assistant-request-returned-unspeakable-error", + "assistant-request-returned-invalid-assistant", + "assistant-request-returned-no-assistant", + "assistant-request-returned-forwarding-phone-number" + ] + } + } + }, + "required": [ + "type", + "key", + "oneOf" + ] + }, + "PhoneNumberHookCallEnding": { + "type": "object", + "properties": { + "on": { + "type": "string", + "description": "This is the event to trigger the hook on", + "enum": [ + "call.ending" + ], + "maxLength": 1000 + }, + "filters": { + "type": "array", + "description": "Optional filters to decide when to trigger - restricted to assistant-request related ended reasons", + "items": { + "$ref": "#/components/schemas/PhoneNumberCallEndingHookFilter" + } + }, + "do": { + "description": "This is the action to perform when the hook triggers", + "oneOf": [ + { + "$ref": "#/components/schemas/TransferPhoneNumberHookAction", + "title": "TransferPhoneNumberHookAction" + }, + { + "$ref": "#/components/schemas/SayPhoneNumberHookAction", + "title": "SayPhoneNumberHookAction" + } + ] + } + }, + "required": [ + "on" + ] + }, + "ImportTwilioPhoneNumberDTO": { + "type": "object", + "properties": { + "fallbackDestination": { + "description": "This is the fallback destination an inbound call will be transferred to if:\n1. `assistantId` is not set\n2. `squadId` is not set\n3. and, `assistant-request` message to the `serverUrl` fails\n\nIf this is not set and above conditions are met, the inbound call is hung up with an error message.", + "oneOf": [ + { + "$ref": "#/components/schemas/TransferDestinationNumber", + "title": "NumberTransferDestination" + }, + { + "$ref": "#/components/schemas/TransferDestinationSip", + "title": "SipTransferDestination" + } + ] + }, + "hooks": { + "type": "array", + "description": "This is the hooks that will be used for incoming calls to this phone number.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/PhoneNumberHookCallRinging", + "title": "PhoneNumberHookCallRinging" + }, + { + "$ref": "#/components/schemas/PhoneNumberHookCallEnding", + "title": "PhoneNumberHookCallEnding" + } + ] + } + }, + "smsEnabled": { + "type": "boolean", + "description": "Controls whether Vapi sets the messaging webhook URL on the Twilio number during import.\n\nIf set to `false`, Vapi will not update the Twilio messaging URL, leaving it as is.\nIf `true` or omitted (default), Vapi will configure both the voice and messaging URLs.\n\n@default true", + "default": true + }, + "twilioPhoneNumber": { + "type": "string", + "description": "These are the digits of the phone number you own on your Twilio.", + "deprecated": true + }, + "twilioAccountSid": { + "type": "string", + "description": "This is your Twilio Account SID that will be used to handle this phone number." + }, + "twilioAuthToken": { + "type": "string", + "description": "This is the Twilio Auth Token that will be used to handle this phone number." + }, + "twilioApiKey": { + "type": "string", + "description": "This is the Twilio API Key that will be used to handle this phone number. If AuthToken is provided, this will be ignored." + }, + "twilioApiSecret": { + "type": "string", + "description": "This is the Twilio API Secret that will be used to handle this phone number. If AuthToken is provided, this will be ignored." + }, + "name": { + "type": "string", + "description": "This is the name of the phone number. This is just for your own reference.", + "maxLength": 40 + }, + "assistantId": { + "type": "string", + "description": "This is the assistant that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId` nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + }, + "workflowId": { + "type": "string", + "description": "This is the workflow that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + }, + "squadId": { + "type": "string", + "description": "This is the squad that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + }, + "server": { + "description": "This is where Vapi will send webhooks. You can find all webhooks available along with their shape in ServerMessage schema.\n\nThe order of precedence is:\n\n1. assistant.server\n2. phoneNumber.server\n3. org.server", + "allOf": [ + { + "$ref": "#/components/schemas/Server" + } + ] + } + }, + "required": [ + "twilioPhoneNumber", + "twilioAccountSid" + ] + }, + "CreateCustomerDTO": { + "type": "object", + "properties": { + "numberE164CheckEnabled": { + "type": "boolean", + "description": "This is the flag to toggle the E164 check for the `number` field. This is an advanced property which should be used if you know your use case requires it.\n\nUse cases:\n- `false`: To allow non-E164 numbers like `+001234567890`, `1234`, or `abc`. This is useful for dialing out to non-E164 numbers on your SIP trunks.\n- `true` (default): To allow only E164 numbers like `+14155551234`. This is standard for PSTN calls.\n\nIf `false`, the `number` is still required to only contain alphanumeric characters (regex: `/^\\+?[a-zA-Z0-9]+$/`).\n\n@default true (E164 check is enabled)", + "default": true + }, + "extension": { + "type": "string", + "description": "This is the extension that will be dialed after the call is answered.", + "maxLength": 10, + "example": null + }, + "assistantOverrides": { + "description": "These are the overrides for the assistant's settings and template variables specific to this customer.\nThis allows customization of the assistant's behavior for individual customers in batch calls.", + "allOf": [ + { + "$ref": "#/components/schemas/AssistantOverrides" + } + ] + }, + "squadOverrides": { + "description": "These are the overrides applied when the call targets a `squadId`. Mirrors\nthe call-level `squadOverrides` — use this instead of `assistantOverrides`\nwhen the campaign or call is squad-based.", + "allOf": [ + { + "$ref": "#/components/schemas/AssistantOverrides" + } + ] + }, + "number": { + "type": "string", + "description": "This is the number of the customer.", + "minLength": 3, + "maxLength": 40 + }, + "sipUri": { + "type": "string", + "description": "This is the SIP URI of the customer." + }, + "name": { + "type": "string", + "description": "This is the name of the customer. This is just for your own reference.\n\nFor SIP inbound calls, this is extracted from the `From` SIP header with format `\"Display Name\" `.", + "maxLength": 40 + }, + "email": { + "type": "string", + "description": "This is the email of the customer.", + "maxLength": 40 + }, + "externalId": { + "type": "string", + "description": "This is the external ID of the customer.", + "maxLength": 40 + } + } + }, + "SchedulePlan": { + "type": "object", + "properties": { + "earliestAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of the earliest time the call can be scheduled." + }, + "latestAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of the latest time the call can be scheduled." + } + }, + "required": [ + "earliestAt" + ] + }, + "Call": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "This is the type of call.", + "enum": [ + "inboundPhoneCall", + "outboundPhoneCall", + "webCall", + "vapi.websocketCall" + ] + }, + "costs": { + "type": "array", + "description": "These are the costs of individual components of the call in USD.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/TransportCost", + "title": "TransportCost" + }, + { + "$ref": "#/components/schemas/TranscriberCost", + "title": "TranscriberCost" + }, + { + "$ref": "#/components/schemas/ModelCost", + "title": "ModelCost" + }, + { + "$ref": "#/components/schemas/VoiceCost", + "title": "VoiceCost" + }, + { + "$ref": "#/components/schemas/VapiCost", + "title": "VapiCost" + }, + { + "$ref": "#/components/schemas/VoicemailDetectionCost", + "title": "VoicemailDetectionCost" + }, + { + "$ref": "#/components/schemas/AnalysisCost", + "title": "AnalysisCost" + }, + { + "$ref": "#/components/schemas/KnowledgeBaseCost", + "title": "KnowledgeBaseCost" + } + ] + } + }, + "messages": { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/UserMessage", + "title": "UserMessage" + }, + { + "$ref": "#/components/schemas/SystemMessage", + "title": "SystemMessage" + }, + { + "$ref": "#/components/schemas/BotMessage", + "title": "BotMessage" + }, + { + "$ref": "#/components/schemas/ToolCallMessage", + "title": "ToolCallMessage" + }, + { + "$ref": "#/components/schemas/ToolCallResultMessage", + "title": "ToolCallResultMessage" + } + ] + } + }, + "phoneCallProvider": { + "type": "string", + "description": "This is the provider of the call.\n\nOnly relevant for `outboundPhoneCall` and `inboundPhoneCall` type.", + "deprecated": true, + "enum": [ + "twilio", + "vonage", + "vapi", + "telnyx" + ] + }, + "phoneCallTransport": { + "type": "string", + "description": "This is the transport of the phone call.\n\nOnly relevant for `outboundPhoneCall` and `inboundPhoneCall` type.", + "enum": [ + "sip", + "pstn" + ] + }, + "status": { + "type": "string", + "description": "This is the status of the call.", + "enum": [ + "scheduled", + "queued", + "ringing", + "in-progress", + "forwarding", + "ended", + "not-found", + "deletion-failed" + ] + }, + "endedReason": { + "type": "string", + "description": "This is the explanation for how the call ended.", + "enum": [ + "call-start-error-neither-assistant-nor-server-set", + "assistant-request-failed", + "assistant-request-returned-error", + "assistant-request-returned-unspeakable-error", + "assistant-request-returned-invalid-assistant", + "assistant-request-returned-no-assistant", + "assistant-request-returned-forwarding-phone-number", + "scheduled-call-deleted", + "call.start.error-vapifault-get-org", + "call.start.error-vapifault-get-subscription", + "call.start.error-get-assistant", + "call.start.error-get-phone-number", + "call.start.error-get-customer", + "call.start.error-get-resources-validation", + "call.start.error-vapi-number-international", + "call.start.error-vapi-number-outbound-daily-limit", + "call.start.error-get-transport", + "call.start.error-subscription-wallet-does-not-exist", + "call.start.error-fraud-check-failed", + "call.start.error-subscription-frozen", + "call.start.error-subscription-insufficient-credits", + "call.start.error-subscription-upgrade-failed", + "call.start.error-subscription-concurrency-limit-reached", + "call.start.error-enterprise-feature-not-available-recording-consent", + "call.start.assistant-version-error-validation", + "assistant-not-valid", + "call.start.error-vapifault-database-error", + "assistant-not-found", + "pipeline-error-openai-voice-failed", + "pipeline-error-cartesia-voice-failed", + "pipeline-error-deepgram-voice-failed", + "pipeline-error-eleven-labs-voice-failed", + "pipeline-error-playht-voice-failed", + "pipeline-error-lmnt-voice-failed", + "pipeline-error-azure-voice-failed", + "pipeline-error-rime-ai-voice-failed", + "pipeline-error-smallest-ai-voice-failed", + "pipeline-error-vapi-voice-failed", + "pipeline-error-neuphonic-voice-failed", + "pipeline-error-hume-voice-failed", + "pipeline-error-sesame-voice-failed", + "pipeline-error-inworld-voice-failed", + "pipeline-error-minimax-voice-failed", + "pipeline-error-wellsaid-voice-failed", + "pipeline-error-xai-voice-failed", + "pipeline-error-microsoft-voice-failed", + "pipeline-error-microsoft-voice-request-canceled", + "pipeline-error-tavus-video-failed", + "call.in-progress.error-vapifault-openai-voice-failed", + "call.in-progress.error-vapifault-cartesia-voice-failed", + "call.in-progress.error-vapifault-deepgram-voice-failed", + "call.in-progress.error-vapifault-eleven-labs-voice-failed", + "call.in-progress.error-vapifault-playht-voice-failed", + "call.in-progress.error-vapifault-lmnt-voice-failed", + "call.in-progress.error-vapifault-azure-voice-failed", + "call.in-progress.error-vapifault-rime-ai-voice-failed", + "call.in-progress.error-vapifault-smallest-ai-voice-failed", + "call.in-progress.error-vapifault-vapi-voice-failed", + "call.in-progress.error-vapifault-neuphonic-voice-failed", + "call.in-progress.error-vapifault-hume-voice-failed", + "call.in-progress.error-vapifault-sesame-voice-failed", + "call.in-progress.error-vapifault-inworld-voice-failed", + "call.in-progress.error-vapifault-minimax-voice-failed", + "call.in-progress.error-vapifault-wellsaid-voice-failed", + "call.in-progress.error-vapifault-xai-voice-failed", + "call.in-progress.error-vapifault-microsoft-voice-failed", + "call.in-progress.error-vapifault-tavus-video-failed", + "pipeline-error-vapi-llm-failed", + "pipeline-error-vapi-400-bad-request-validation-failed", + "pipeline-error-vapi-401-unauthorized", + "pipeline-error-vapi-403-model-access-denied", + "pipeline-error-vapi-429-exceeded-quota", + "pipeline-error-vapi-500-server-error", + "pipeline-error-vapi-503-server-overloaded-error", + "call.in-progress.error-providerfault-vapi-llm-failed", + "call.in-progress.error-vapifault-vapi-llm-failed", + "call.in-progress.error-vapifault-vapi-400-bad-request-validation-failed", + "call.in-progress.error-vapifault-vapi-401-unauthorized", + "call.in-progress.error-vapifault-vapi-403-model-access-denied", + "call.in-progress.error-vapifault-vapi-429-exceeded-quota", + "call.in-progress.error-providerfault-vapi-500-server-error", + "call.in-progress.error-providerfault-vapi-503-server-overloaded-error", + "pipeline-error-vapi-transcriber-failed", + "call.in-progress.error-vapifault-vapi-transcriber-failed", + "call.in-progress.error-providerfault-vapi-transcriber-failed", + "call.in-progress.error-providerfault-vapi-voice-failed", + "pipeline-error-deepgram-transcriber-failed", + "pipeline-error-deepgram-transcriber-api-key-missing", + "call.in-progress.error-vapifault-deepgram-transcriber-failed", + "pipeline-error-gladia-transcriber-failed", + "call.in-progress.error-vapifault-gladia-transcriber-failed", + "pipeline-error-speechmatics-transcriber-failed", + "call.in-progress.error-vapifault-speechmatics-transcriber-failed", + "pipeline-error-assembly-ai-transcriber-failed", + "pipeline-error-assembly-ai-returning-400-insufficent-funds", + "pipeline-error-assembly-ai-returning-400-paid-only-feature", + "pipeline-error-assembly-ai-returning-401-invalid-credentials", + "pipeline-error-assembly-ai-returning-500-invalid-schema", + "pipeline-error-assembly-ai-returning-500-word-boost-parsing-failed", + "call.in-progress.error-vapifault-assembly-ai-transcriber-failed", + "call.in-progress.error-vapifault-assembly-ai-returning-400-insufficent-funds", + "call.in-progress.error-vapifault-assembly-ai-returning-400-paid-only-feature", + "call.in-progress.error-vapifault-assembly-ai-returning-401-invalid-credentials", + "call.in-progress.error-vapifault-assembly-ai-returning-500-invalid-schema", + "call.in-progress.error-vapifault-assembly-ai-returning-500-word-boost-parsing-failed", + "pipeline-error-talkscriber-transcriber-failed", + "call.in-progress.error-vapifault-talkscriber-transcriber-failed", + "pipeline-error-azure-speech-transcriber-failed", + "call.in-progress.error-vapifault-azure-speech-transcriber-failed", + "pipeline-error-eleven-labs-transcriber-failed", + "call.in-progress.error-vapifault-eleven-labs-transcriber-failed", + "pipeline-error-google-transcriber-failed", + "call.in-progress.error-vapifault-google-transcriber-failed", + "pipeline-error-openai-transcriber-failed", + "call.in-progress.error-vapifault-openai-transcriber-failed", + "pipeline-error-soniox-transcriber-auth-failed", + "pipeline-error-soniox-transcriber-rate-limited", + "pipeline-error-soniox-transcriber-invalid-config", + "pipeline-error-soniox-transcriber-server-error", + "pipeline-error-soniox-transcriber-failed", + "call.in-progress.error-vapifault-soniox-transcriber-auth-failed", + "call.in-progress.error-vapifault-soniox-transcriber-rate-limited", + "call.in-progress.error-vapifault-soniox-transcriber-invalid-config", + "call.in-progress.error-vapifault-soniox-transcriber-server-error", + "call.in-progress.error-vapifault-soniox-transcriber-failed", + "pipeline-error-xai-transcriber-auth-failed", + "pipeline-error-xai-transcriber-rate-limited", + "pipeline-error-xai-transcriber-invalid-config", + "pipeline-error-xai-transcriber-server-error", + "pipeline-error-xai-transcriber-failed", + "call.in-progress.error-vapifault-xai-transcriber-auth-failed", + "call.in-progress.error-vapifault-xai-transcriber-rate-limited", + "call.in-progress.error-vapifault-xai-transcriber-invalid-config", + "call.in-progress.error-vapifault-xai-transcriber-server-error", + "call.in-progress.error-vapifault-xai-transcriber-failed", + "pipeline-error-cartesia-transcriber-failed", + "call.in-progress.error-vapifault-cartesia-transcriber-failed", + "call.in-progress.error-pipeline-no-available-llm-model", + "worker-shutdown", + "vonage-disconnected", + "vonage-failed-to-connect-call", + "vonage-completed", + "phone-call-provider-bypass-enabled-but-no-call-received", + "call.in-progress.error-providerfault-transport-never-connected", + "call.in-progress.error-vapifault-worker-not-available", + "call.in-progress.error-vapifault-transport-never-connected", + "call.in-progress.error-vapifault-transport-connected-but-call-not-active", + "call.in-progress.error-vapifault-call-started-but-connection-to-transport-missing", + "call.in-progress.error-vapifault-worker-died", + "call.in-progress.twilio-completed-call", + "call.in-progress.sip-completed-call", + "call.in-progress.error-sip-inbound-call-failed-to-connect", + "call.in-progress.error-providerfault-outbound-sip-503-service-unavailable", + "call.in-progress.error-sip-outbound-call-failed-to-connect", + "call.ringing.error-sip-inbound-call-failed-to-connect", + "call.in-progress.error-providerfault-openai-llm-failed", + "call.in-progress.error-providerfault-azure-openai-llm-failed", + "call.in-progress.error-providerfault-groq-llm-failed", + "call.in-progress.error-providerfault-google-llm-failed", + "call.in-progress.error-providerfault-xai-llm-failed", + "call.in-progress.error-providerfault-mistral-llm-failed", + "call.in-progress.error-providerfault-minimax-llm-failed", + "call.in-progress.error-providerfault-inflection-ai-llm-failed", + "call.in-progress.error-providerfault-cerebras-llm-failed", + "call.in-progress.error-providerfault-deep-seek-llm-failed", + "call.in-progress.error-providerfault-baseten-llm-failed", + "call.in-progress.error-vapifault-chat-pipeline-failed-to-start", + "pipeline-error-openai-400-bad-request-validation-failed", + "pipeline-error-openai-401-unauthorized", + "pipeline-error-openai-401-incorrect-api-key", + "pipeline-error-openai-401-account-not-in-organization", + "pipeline-error-openai-403-model-access-denied", + "pipeline-error-openai-429-exceeded-quota", + "pipeline-error-openai-429-rate-limit-reached", + "pipeline-error-openai-500-server-error", + "pipeline-error-openai-503-server-overloaded-error", + "pipeline-error-openai-llm-failed", + "call.in-progress.error-vapifault-openai-400-bad-request-validation-failed", + "call.in-progress.error-vapifault-openai-401-unauthorized", + "call.in-progress.error-vapifault-openai-401-incorrect-api-key", + "call.in-progress.error-vapifault-openai-401-account-not-in-organization", + "call.in-progress.error-vapifault-openai-403-model-access-denied", + "call.in-progress.error-vapifault-openai-429-exceeded-quota", + "call.in-progress.error-vapifault-openai-429-rate-limit-reached", + "call.in-progress.error-providerfault-openai-500-server-error", + "call.in-progress.error-providerfault-openai-503-server-overloaded-error", + "pipeline-error-azure-openai-400-bad-request-validation-failed", + "pipeline-error-azure-openai-401-unauthorized", + "pipeline-error-azure-openai-403-model-access-denied", + "pipeline-error-azure-openai-429-exceeded-quota", + "pipeline-error-azure-openai-500-server-error", + "pipeline-error-azure-openai-503-server-overloaded-error", + "pipeline-error-azure-openai-llm-failed", + "call.in-progress.error-vapifault-azure-openai-400-bad-request-validation-failed", + "call.in-progress.error-vapifault-azure-openai-401-unauthorized", + "call.in-progress.error-vapifault-azure-openai-403-model-access-denied", + "call.in-progress.error-vapifault-azure-openai-429-exceeded-quota", + "call.in-progress.error-providerfault-azure-openai-500-server-error", + "call.in-progress.error-providerfault-azure-openai-503-server-overloaded-error", + "pipeline-error-google-400-bad-request-validation-failed", + "pipeline-error-google-401-unauthorized", + "pipeline-error-google-403-model-access-denied", + "pipeline-error-google-429-exceeded-quota", + "pipeline-error-google-500-server-error", + "pipeline-error-google-503-server-overloaded-error", + "pipeline-error-google-llm-failed", + "call.in-progress.error-vapifault-google-400-bad-request-validation-failed", + "call.in-progress.error-vapifault-google-401-unauthorized", + "call.in-progress.error-vapifault-google-403-model-access-denied", + "call.in-progress.error-vapifault-google-429-exceeded-quota", + "call.in-progress.error-providerfault-google-500-server-error", + "call.in-progress.error-providerfault-google-503-server-overloaded-error", + "pipeline-error-xai-400-bad-request-validation-failed", + "pipeline-error-xai-401-unauthorized", + "pipeline-error-xai-403-model-access-denied", + "pipeline-error-xai-429-exceeded-quota", + "pipeline-error-xai-500-server-error", + "pipeline-error-xai-503-server-overloaded-error", + "pipeline-error-xai-llm-failed", + "call.in-progress.error-vapifault-xai-400-bad-request-validation-failed", + "call.in-progress.error-vapifault-xai-401-unauthorized", + "call.in-progress.error-vapifault-xai-403-model-access-denied", + "call.in-progress.error-vapifault-xai-429-exceeded-quota", + "call.in-progress.error-providerfault-xai-500-server-error", + "call.in-progress.error-providerfault-xai-503-server-overloaded-error", + "pipeline-error-baseten-400-bad-request-validation-failed", + "pipeline-error-baseten-401-unauthorized", + "pipeline-error-baseten-403-model-access-denied", + "pipeline-error-baseten-429-exceeded-quota", + "pipeline-error-baseten-500-server-error", + "pipeline-error-baseten-503-server-overloaded-error", + "pipeline-error-baseten-llm-failed", + "call.in-progress.error-vapifault-baseten-400-bad-request-validation-failed", + "call.in-progress.error-vapifault-baseten-401-unauthorized", + "call.in-progress.error-vapifault-baseten-403-model-access-denied", + "call.in-progress.error-vapifault-baseten-429-exceeded-quota", + "call.in-progress.error-providerfault-baseten-500-server-error", + "call.in-progress.error-providerfault-baseten-503-server-overloaded-error", + "pipeline-error-mistral-400-bad-request-validation-failed", + "pipeline-error-mistral-401-unauthorized", + "pipeline-error-mistral-403-model-access-denied", + "pipeline-error-mistral-429-exceeded-quota", + "pipeline-error-mistral-500-server-error", + "pipeline-error-mistral-503-server-overloaded-error", + "pipeline-error-mistral-llm-failed", + "call.in-progress.error-vapifault-mistral-400-bad-request-validation-failed", + "call.in-progress.error-vapifault-mistral-401-unauthorized", + "call.in-progress.error-vapifault-mistral-403-model-access-denied", + "call.in-progress.error-vapifault-mistral-429-exceeded-quota", + "call.in-progress.error-providerfault-mistral-500-server-error", + "call.in-progress.error-providerfault-mistral-503-server-overloaded-error", + "pipeline-error-minimax-400-bad-request-validation-failed", + "pipeline-error-minimax-401-unauthorized", + "pipeline-error-minimax-403-model-access-denied", + "pipeline-error-minimax-429-exceeded-quota", + "pipeline-error-minimax-500-server-error", + "pipeline-error-minimax-503-server-overloaded-error", + "pipeline-error-minimax-llm-failed", + "call.in-progress.error-vapifault-minimax-400-bad-request-validation-failed", + "call.in-progress.error-vapifault-minimax-401-unauthorized", + "call.in-progress.error-vapifault-minimax-403-model-access-denied", + "call.in-progress.error-vapifault-minimax-429-exceeded-quota", + "call.in-progress.error-providerfault-minimax-500-server-error", + "call.in-progress.error-providerfault-minimax-503-server-overloaded-error", + "pipeline-error-inflection-ai-400-bad-request-validation-failed", + "pipeline-error-inflection-ai-401-unauthorized", + "pipeline-error-inflection-ai-403-model-access-denied", + "pipeline-error-inflection-ai-429-exceeded-quota", + "pipeline-error-inflection-ai-500-server-error", + "pipeline-error-inflection-ai-503-server-overloaded-error", + "pipeline-error-inflection-ai-llm-failed", + "call.in-progress.error-vapifault-inflection-ai-400-bad-request-validation-failed", + "call.in-progress.error-vapifault-inflection-ai-401-unauthorized", + "call.in-progress.error-vapifault-inflection-ai-403-model-access-denied", + "call.in-progress.error-vapifault-inflection-ai-429-exceeded-quota", + "call.in-progress.error-providerfault-inflection-ai-500-server-error", + "call.in-progress.error-providerfault-inflection-ai-503-server-overloaded-error", + "pipeline-error-deep-seek-400-bad-request-validation-failed", + "pipeline-error-deep-seek-401-unauthorized", + "pipeline-error-deep-seek-403-model-access-denied", + "pipeline-error-deep-seek-429-exceeded-quota", + "pipeline-error-deep-seek-500-server-error", + "pipeline-error-deep-seek-503-server-overloaded-error", + "pipeline-error-deep-seek-llm-failed", + "call.in-progress.error-vapifault-deep-seek-400-bad-request-validation-failed", + "call.in-progress.error-vapifault-deep-seek-401-unauthorized", + "call.in-progress.error-vapifault-deep-seek-403-model-access-denied", + "call.in-progress.error-vapifault-deep-seek-429-exceeded-quota", + "call.in-progress.error-providerfault-deep-seek-500-server-error", + "call.in-progress.error-providerfault-deep-seek-503-server-overloaded-error", + "pipeline-error-groq-400-bad-request-validation-failed", + "pipeline-error-groq-401-unauthorized", + "pipeline-error-groq-403-model-access-denied", + "pipeline-error-groq-429-exceeded-quota", + "pipeline-error-groq-500-server-error", + "pipeline-error-groq-503-server-overloaded-error", + "pipeline-error-groq-llm-failed", + "call.in-progress.error-vapifault-groq-400-bad-request-validation-failed", + "call.in-progress.error-vapifault-groq-401-unauthorized", + "call.in-progress.error-vapifault-groq-403-model-access-denied", + "call.in-progress.error-vapifault-groq-429-exceeded-quota", + "call.in-progress.error-providerfault-groq-500-server-error", + "call.in-progress.error-providerfault-groq-503-server-overloaded-error", + "pipeline-error-cerebras-400-bad-request-validation-failed", + "pipeline-error-cerebras-401-unauthorized", + "pipeline-error-cerebras-403-model-access-denied", + "pipeline-error-cerebras-429-exceeded-quota", + "pipeline-error-cerebras-500-server-error", + "pipeline-error-cerebras-503-server-overloaded-error", + "pipeline-error-cerebras-llm-failed", + "call.in-progress.error-vapifault-cerebras-400-bad-request-validation-failed", + "call.in-progress.error-vapifault-cerebras-401-unauthorized", + "call.in-progress.error-vapifault-cerebras-403-model-access-denied", + "call.in-progress.error-vapifault-cerebras-429-exceeded-quota", + "call.in-progress.error-providerfault-cerebras-500-server-error", + "call.in-progress.error-providerfault-cerebras-503-server-overloaded-error", + "pipeline-error-anthropic-400-bad-request-validation-failed", + "pipeline-error-anthropic-401-unauthorized", + "pipeline-error-anthropic-403-model-access-denied", + "pipeline-error-anthropic-429-exceeded-quota", + "pipeline-error-anthropic-500-server-error", + "pipeline-error-anthropic-503-server-overloaded-error", + "pipeline-error-anthropic-llm-failed", + "call.in-progress.error-providerfault-anthropic-llm-failed", + "call.in-progress.error-vapifault-anthropic-400-bad-request-validation-failed", + "call.in-progress.error-vapifault-anthropic-401-unauthorized", + "call.in-progress.error-vapifault-anthropic-403-model-access-denied", + "call.in-progress.error-vapifault-anthropic-429-exceeded-quota", + "call.in-progress.error-providerfault-anthropic-500-server-error", + "call.in-progress.error-providerfault-anthropic-503-server-overloaded-error", + "pipeline-error-anthropic-bedrock-400-bad-request-validation-failed", + "pipeline-error-anthropic-bedrock-401-unauthorized", + "pipeline-error-anthropic-bedrock-403-model-access-denied", + "pipeline-error-anthropic-bedrock-429-exceeded-quota", + "pipeline-error-anthropic-bedrock-500-server-error", + "pipeline-error-anthropic-bedrock-503-server-overloaded-error", + "pipeline-error-anthropic-bedrock-llm-failed", + "call.in-progress.error-providerfault-anthropic-bedrock-llm-failed", + "call.in-progress.error-vapifault-anthropic-bedrock-400-bad-request-validation-failed", + "call.in-progress.error-vapifault-anthropic-bedrock-401-unauthorized", "call.in-progress.error-vapifault-anthropic-bedrock-403-model-access-denied", "call.in-progress.error-vapifault-anthropic-bedrock-429-exceeded-quota", "call.in-progress.error-providerfault-anthropic-bedrock-500-server-error", @@ -27240,7 +45963,7 @@ "pipeline-error-anthropic-vertex-500-server-error", "pipeline-error-anthropic-vertex-503-server-overloaded-error", "pipeline-error-anthropic-vertex-llm-failed", - "call.in-progress.error-vapifault-anthropic-vertex-llm-failed", + "call.in-progress.error-providerfault-anthropic-vertex-llm-failed", "call.in-progress.error-vapifault-anthropic-vertex-400-bad-request-validation-failed", "call.in-progress.error-vapifault-anthropic-vertex-401-unauthorized", "call.in-progress.error-vapifault-anthropic-vertex-403-model-access-denied", @@ -27254,7 +45977,7 @@ "pipeline-error-together-ai-500-server-error", "pipeline-error-together-ai-503-server-overloaded-error", "pipeline-error-together-ai-llm-failed", - "call.in-progress.error-vapifault-together-ai-llm-failed", + "call.in-progress.error-providerfault-together-ai-llm-failed", "call.in-progress.error-vapifault-together-ai-400-bad-request-validation-failed", "call.in-progress.error-vapifault-together-ai-401-unauthorized", "call.in-progress.error-vapifault-together-ai-403-model-access-denied", @@ -27268,7 +45991,7 @@ "pipeline-error-anyscale-500-server-error", "pipeline-error-anyscale-503-server-overloaded-error", "pipeline-error-anyscale-llm-failed", - "call.in-progress.error-vapifault-anyscale-llm-failed", + "call.in-progress.error-providerfault-anyscale-llm-failed", "call.in-progress.error-vapifault-anyscale-400-bad-request-validation-failed", "call.in-progress.error-vapifault-anyscale-401-unauthorized", "call.in-progress.error-vapifault-anyscale-403-model-access-denied", @@ -27282,7 +46005,7 @@ "pipeline-error-openrouter-500-server-error", "pipeline-error-openrouter-503-server-overloaded-error", "pipeline-error-openrouter-llm-failed", - "call.in-progress.error-vapifault-openrouter-llm-failed", + "call.in-progress.error-providerfault-openrouter-llm-failed", "call.in-progress.error-vapifault-openrouter-400-bad-request-validation-failed", "call.in-progress.error-vapifault-openrouter-401-unauthorized", "call.in-progress.error-vapifault-openrouter-403-model-access-denied", @@ -27296,7 +46019,7 @@ "pipeline-error-perplexity-ai-500-server-error", "pipeline-error-perplexity-ai-503-server-overloaded-error", "pipeline-error-perplexity-ai-llm-failed", - "call.in-progress.error-vapifault-perplexity-ai-llm-failed", + "call.in-progress.error-providerfault-perplexity-ai-llm-failed", "call.in-progress.error-vapifault-perplexity-ai-400-bad-request-validation-failed", "call.in-progress.error-vapifault-perplexity-ai-401-unauthorized", "call.in-progress.error-vapifault-perplexity-ai-403-model-access-denied", @@ -27310,7 +46033,7 @@ "pipeline-error-deepinfra-500-server-error", "pipeline-error-deepinfra-503-server-overloaded-error", "pipeline-error-deepinfra-llm-failed", - "call.in-progress.error-vapifault-deepinfra-llm-failed", + "call.in-progress.error-providerfault-deepinfra-llm-failed", "call.in-progress.error-vapifault-deepinfra-400-bad-request-validation-failed", "call.in-progress.error-vapifault-deepinfra-401-unauthorized", "call.in-progress.error-vapifault-deepinfra-403-model-access-denied", @@ -27324,7 +46047,7 @@ "pipeline-error-runpod-500-server-error", "pipeline-error-runpod-503-server-overloaded-error", "pipeline-error-runpod-llm-failed", - "call.in-progress.error-vapifault-runpod-llm-failed", + "call.in-progress.error-providerfault-runpod-llm-failed", "call.in-progress.error-vapifault-runpod-400-bad-request-validation-failed", "call.in-progress.error-vapifault-runpod-401-unauthorized", "call.in-progress.error-vapifault-runpod-403-model-access-denied", @@ -27338,13 +46061,14 @@ "pipeline-error-custom-llm-500-server-error", "pipeline-error-custom-llm-503-server-overloaded-error", "pipeline-error-custom-llm-llm-failed", - "call.in-progress.error-vapifault-custom-llm-llm-failed", + "call.in-progress.error-providerfault-custom-llm-llm-failed", "call.in-progress.error-vapifault-custom-llm-400-bad-request-validation-failed", "call.in-progress.error-vapifault-custom-llm-401-unauthorized", "call.in-progress.error-vapifault-custom-llm-403-model-access-denied", "call.in-progress.error-vapifault-custom-llm-429-exceeded-quota", "call.in-progress.error-providerfault-custom-llm-500-server-error", "call.in-progress.error-providerfault-custom-llm-503-server-overloaded-error", + "call.in-progress.error-pipeline-ws-model-connection-failed", "pipeline-error-custom-voice-failed", "pipeline-error-cartesia-socket-hang-up", "pipeline-error-cartesia-requested-payment", @@ -27400,6 +46124,7 @@ "call.in-progress.error-vapifault-eleven-labs-voice-not-allowed-for-free-users", "call.in-progress.error-vapifault-eleven-labs-max-character-limit-exceeded", "call.in-progress.error-vapifault-eleven-labs-blocked-voice-potentially-against-terms-of-service-and-awaiting-verification", + "call.in-progress.error-providerfault-eleven-labs-system-busy-and-requested-upgrade", "call.in-progress.error-providerfault-eleven-labs-500-server-error", "call.in-progress.error-providerfault-eleven-labs-503-server-error", "pipeline-error-playht-request-timed-out", @@ -27449,12 +46174,32 @@ "call.in-progress.error-vapifault-google-transcriber-failed", "pipeline-error-openai-transcriber-failed", "call.in-progress.error-vapifault-openai-transcriber-failed", + "pipeline-error-soniox-transcriber-auth-failed", + "pipeline-error-soniox-transcriber-rate-limited", + "pipeline-error-soniox-transcriber-invalid-config", + "pipeline-error-soniox-transcriber-server-error", + "pipeline-error-soniox-transcriber-failed", + "call.in-progress.error-vapifault-soniox-transcriber-auth-failed", + "call.in-progress.error-vapifault-soniox-transcriber-rate-limited", + "call.in-progress.error-vapifault-soniox-transcriber-invalid-config", + "call.in-progress.error-vapifault-soniox-transcriber-server-error", + "call.in-progress.error-vapifault-soniox-transcriber-failed", + "pipeline-error-xai-transcriber-auth-failed", + "pipeline-error-xai-transcriber-rate-limited", + "pipeline-error-xai-transcriber-invalid-config", + "pipeline-error-xai-transcriber-server-error", + "pipeline-error-xai-transcriber-failed", + "call.in-progress.error-vapifault-xai-transcriber-auth-failed", + "call.in-progress.error-vapifault-xai-transcriber-rate-limited", + "call.in-progress.error-vapifault-xai-transcriber-invalid-config", + "call.in-progress.error-vapifault-xai-transcriber-server-error", + "call.in-progress.error-vapifault-xai-transcriber-failed", + "pipeline-error-cartesia-transcriber-failed", + "call.in-progress.error-vapifault-cartesia-transcriber-failed", "call.in-progress.error-warm-transfer-max-duration", "call.in-progress.error-warm-transfer-assistant-cancelled", "call.in-progress.error-warm-transfer-silence-timeout", "call.in-progress.error-warm-transfer-microphone-timeout", - "call.in-progress.error-warm-transfer-hang-timeout", - "call.in-progress.error-warm-transfer-idle-timeout", "assistant-ended-call", "assistant-said-end-call-phrase", "assistant-ended-call-with-hangup-task", @@ -27465,17 +46210,21 @@ "call.in-progress.error-transfer-failed", "customer-busy", "customer-ended-call", + "customer-ended-call-before-warm-transfer", "customer-ended-call-after-warm-transfer-attempt", + "customer-ended-call-during-transfer", "customer-did-not-answer", "customer-did-not-give-microphone-permission", "exceeded-max-duration", "manually-canceled", "phone-call-provider-closed-websocket", "call.forwarding.operator-busy", + "call.forwarding.no-answer", "silence-timed-out", "call.in-progress.error-sip-inbound-call-failed-to-connect", "call.in-progress.error-providerfault-outbound-sip-403-forbidden", "call.in-progress.error-providerfault-outbound-sip-407-proxy-authentication-required", + "call.in-progress.error-providerfault-outbound-sip-408-request-timeout", "call.in-progress.error-providerfault-outbound-sip-503-service-unavailable", "call.in-progress.error-providerfault-outbound-sip-480-temporarily-unavailable", "call.in-progress.error-sip-outbound-call-failed-to-connect", @@ -27488,11 +46237,4683 @@ "twilio-failed-to-connect-call", "twilio-reported-customer-misdialed", "vonage-rejected", - "voicemail" + "voicemail", + "call-deleted" + ] + }, + "endedMessage": { + "type": "string", + "description": "This is the message that adds more context to the ended reason. It can be used to provide potential error messages or warnings." + }, + "destination": { + "description": "This is the destination where the call ended up being transferred to. If the call was not transferred, this will be empty.", + "oneOf": [ + { + "$ref": "#/components/schemas/TransferDestinationNumber", + "title": "NumberTransferDestination" + }, + { + "$ref": "#/components/schemas/TransferDestinationSip", + "title": "SipTransferDestination" + } + ] + }, + "assistantVersion": { + "type": "string", + "nullable": true, + "description": "This is the assistant version to use for this call. Supported only with\ndirect `assistantId`. Omit to follow the latest version." + }, + "transport": { + "description": "This is the transport of the call.", + "oneOf": [ + { + "$ref": "#/components/schemas/VapiWebsocketTransport", + "title": "VapiWebsocketTransport" + }, + { + "$ref": "#/components/schemas/VonageTransport", + "title": "VonageTransport" + }, + { + "$ref": "#/components/schemas/TwilioTransport", + "title": "TwilioTransport" + }, + { + "$ref": "#/components/schemas/VapiSipTransport", + "title": "VapiSipTransport" + }, + { + "$ref": "#/components/schemas/TelnyxTransport", + "title": "TelnyxTransport" + }, + { + "$ref": "#/components/schemas/VapiWebCallTransport", + "title": "VapiWebCallTransport" + } + ] + }, + "id": { + "type": "string", + "description": "This is the unique identifier for the call." + }, + "orgId": { + "type": "string", + "description": "This is the unique identifier for the org that this call belongs to." + }, + "createdAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the call was created." + }, + "updatedAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the call was last updated." + }, + "startedAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the call was started." + }, + "endedAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the call was ended." + }, + "cost": { + "type": "number", + "description": "This is the cost of the call in USD." + }, + "costBreakdown": { + "description": "This is the cost of the call in USD.", + "allOf": [ + { + "$ref": "#/components/schemas/CostBreakdown" + } + ] + }, + "artifactPlan": { + "description": "This is a copy of assistant artifact plan. This isn't actually stored on the call but rather just returned in POST /call/web to enable artifact creation client side.", + "allOf": [ + { + "$ref": "#/components/schemas/ArtifactPlan" + } + ] + }, + "analysis": { + "description": "This is the analysis of the call. Configure in `assistant.analysisPlan`.", + "allOf": [ + { + "$ref": "#/components/schemas/Analysis" + } + ] + }, + "monitor": { + "description": "This is to real-time monitor the call. Configure in `assistant.monitorPlan`.", + "allOf": [ + { + "$ref": "#/components/schemas/Monitor" + } + ] + }, + "artifact": { + "description": "These are the artifacts created from the call. Configure in `assistant.artifactPlan`.", + "allOf": [ + { + "$ref": "#/components/schemas/Artifact" + } + ] + }, + "compliance": { + "description": "This is the compliance of the call. Configure in `assistant.compliancePlan`.", + "allOf": [ + { + "$ref": "#/components/schemas/Compliance" + } + ] + }, + "phoneCallProviderId": { + "type": "string", + "description": "The ID of the call as provided by the phone number service. callSid in Twilio. conversationUuid in Vonage. callControlId in Telnyx.\n\nOnly relevant for `outboundPhoneCall` and `inboundPhoneCall` type.", + "deprecated": true + }, + "campaignId": { + "type": "string", + "description": "This is the campaign ID that the call belongs to." + }, + "assistantId": { + "type": "string", + "description": "This is the assistant ID that will be used for the call. To use a transient assistant, use `assistant` instead.\n\nTo start a call with:\n- Assistant, use `assistantId` or `assistant`\n- Squad, use `squadId` or `squad`\n- Workflow, use `workflowId` or `workflow`" + }, + "assistant": { + "description": "This is the assistant that will be used for the call. To use an existing assistant, use `assistantId` instead.\n\nTo start a call with:\n- Assistant, use `assistant`\n- Squad, use `squad`\n- Workflow, use `workflow`", + "allOf": [ + { + "$ref": "#/components/schemas/CreateAssistantDTO" + } + ] + }, + "assistantOverrides": { + "description": "These are the overrides for the `assistant` or `assistantId`'s settings and template variables.", + "allOf": [ + { + "$ref": "#/components/schemas/AssistantOverrides" + } + ] + }, + "squadId": { + "type": "string", + "description": "This is the squad that will be used for the call. To use a transient squad, use `squad` instead.\n\nTo start a call with:\n- Assistant, use `assistant` or `assistantId`\n- Squad, use `squad` or `squadId`\n- Workflow, use `workflow` or `workflowId`" + }, + "squad": { + "description": "This is a squad that will be used for the call. To use an existing squad, use `squadId` instead.\n\nTo start a call with:\n- Assistant, use `assistant` or `assistantId`\n- Squad, use `squad` or `squadId`\n- Workflow, use `workflow` or `workflowId`", + "allOf": [ + { + "$ref": "#/components/schemas/CreateSquadDTO" + } + ] + }, + "squadOverrides": { + "description": "These are the overrides for the `squad` or `squadId`'s member settings and template variables.\nThis will apply to all members of the squad.", + "allOf": [ + { + "$ref": "#/components/schemas/AssistantOverrides" + } + ] + }, + "workflowId": { + "type": "string", + "description": "This is the workflow that will be used for the call. To use a transient workflow, use `workflow` instead.\n\nTo start a call with:\n- Assistant, use `assistant` or `assistantId`\n- Squad, use `squad` or `squadId`\n- Workflow, use `workflow` or `workflowId`" + }, + "workflow": { + "description": "This is a workflow that will be used for the call. To use an existing workflow, use `workflowId` instead.\n\nTo start a call with:\n- Assistant, use `assistant` or `assistantId`\n- Squad, use `squad` or `squadId`\n- Workflow, use `workflow` or `workflowId`", + "allOf": [ + { + "$ref": "#/components/schemas/CreateWorkflowDTO" + } + ] + }, + "workflowOverrides": { + "description": "These are the overrides for the `workflow` or `workflowId`'s settings and template variables.", + "allOf": [ + { + "$ref": "#/components/schemas/WorkflowOverrides" + } + ] + }, + "phoneNumberId": { + "type": "string", + "description": "This is the phone number that will be used for the call. To use a transient number, use `phoneNumber` instead.\n\nOnly relevant for `outboundPhoneCall` and `inboundPhoneCall` type." + }, + "phoneNumber": { + "description": "This is the phone number that will be used for the call. To use an existing number, use `phoneNumberId` instead.\n\nOnly relevant for `outboundPhoneCall` and `inboundPhoneCall` type.", + "allOf": [ + { + "$ref": "#/components/schemas/ImportTwilioPhoneNumberDTO" + } + ] + }, + "customerId": { + "type": "string", + "description": "This is the customer that will be called. To call a transient customer , use `customer` instead.\n\nOnly relevant for `outboundPhoneCall` and `inboundPhoneCall` type." + }, + "customer": { + "description": "This is the customer that will be called. To call an existing customer, use `customerId` instead.\n\nOnly relevant for `outboundPhoneCall` and `inboundPhoneCall` type.", + "allOf": [ + { + "$ref": "#/components/schemas/CreateCustomerDTO" + } + ] + }, + "name": { + "type": "string", + "description": "This is the name of the call. This is just for your own reference.", + "maxLength": 40 + }, + "schedulePlan": { + "description": "This is the schedule plan of the call.", + "allOf": [ + { + "$ref": "#/components/schemas/SchedulePlan" + } + ] + } + }, + "required": [ + "id", + "orgId", + "createdAt", + "updatedAt" + ] + }, + "CallBatchError": { + "type": "object", + "properties": { + "customer": { + "$ref": "#/components/schemas/CreateCustomerDTO" + }, + "error": { + "type": "string" + } + }, + "required": [ + "customer", + "error" + ] + }, + "CallBatchResponse": { + "type": "object", + "properties": { + "subscriptionLimits": { + "description": "Subscription limits at the end of this batch", + "allOf": [ + { + "$ref": "#/components/schemas/SubscriptionLimits" + } + ] + }, + "results": { + "description": "This is the list of calls that were created.", + "type": "array", + "items": { + "$ref": "#/components/schemas/Call" + } + }, + "errors": { + "description": "This is the list of calls that failed to be created.", + "type": "array", + "items": { + "$ref": "#/components/schemas/CallBatchError" + } + } + }, + "required": [ + "results", + "errors" + ] + }, + "AssistantSpeechWordAlignmentTiming": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Discriminator for exact per-word timing (e.g. ElevenLabs alignment).", + "enum": [ + "word-alignment" + ] + }, + "words": { + "description": "The individual words in this audio segment.", + "type": "array", + "items": { + "type": "string" + } + }, + "wordsStartTimesMs": { + "description": "Start time in milliseconds for each word (parallel to `words`).", + "type": "array", + "items": { + "type": "number" + } + }, + "wordsEndTimesMs": { + "description": "End time in milliseconds for each word (parallel to `words`).", + "type": "array", + "items": { + "type": "number" + } + } + }, + "required": [ + "type", + "words", + "wordsStartTimesMs", + "wordsEndTimesMs" + ] + }, + "AssistantSpeechWordTimestamp": { + "type": "object", + "properties": { + "word": { + "type": "string", + "description": "The full word text (syllables aggregated into complete words)." + }, + "startMs": { + "type": "number", + "description": "Start time in milliseconds relative to the segment start." + }, + "endMs": { + "type": "number", + "description": "End time in milliseconds relative to the segment start." + } + }, + "required": [ + "word", + "startMs", + "endMs" + ] + }, + "AssistantSpeechWordProgressTiming": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Discriminator for cursor-based word progress (e.g. Minimax subtitle data).", + "enum": [ + "word-progress" + ] + }, + "wordsSpoken": { + "type": "number", + "description": "Number of words spoken so far in this turn." + }, + "totalWords": { + "type": "number", + "description": "Total number of words sent to the TTS provider for this turn.\n\n**Important**: this value grows across events within a single turn because\nMinimax synthesizes audio incrementally as the LLM streams tokens. Treat\nit as \"best known total so far\" — it will stabilize once synthesis is\ncomplete.\n\nA value of `0` is a valid sentinel meaning \"not yet known\". This can occur\non the very first `assistant-speech` event of a turn if audio begins\nplaying before the TTS provider has confirmed word-count data. Clients\n**must** guard against divide-by-zero when computing a progress fraction:\n\n```ts\nconst pct = totalWords > 0 ? wordsSpoken / totalWords : 0;\n```" + }, + "segment": { + "type": "string", + "description": "The text of the latest spoken segment (sentence or clause). Use this\nfor caption display — it corresponds to the chunk just confirmed by\nthe TTS provider, unlike `text` on the parent message which carries\nthe full turn text." + }, + "segmentDurationMs": { + "type": "number", + "description": "Audio duration in milliseconds for the latest spoken segment. Pair\nwith `segment` to animate karaoke-style word reveals — divide the\nsegment text across this duration for approximate per-word timing." + }, + "words": { + "description": "Per-word timestamps for the latest spoken segment. Available when the\nTTS provider supports word-level timing (e.g. Minimax with\nsubtitle_type: \"word\"). Syllables from the provider are aggregated\ninto whole words with start/end times relative to the segment start.\n\nUse these for precise karaoke-style highlighting instead of\ninterpolating from segmentDurationMs.", + "type": "array", + "items": { + "$ref": "#/components/schemas/AssistantSpeechWordTimestamp" + } + } + }, + "required": [ + "type", + "wordsSpoken", + "totalWords" + ] + }, + "CreateCallDTO": { + "type": "object", + "properties": { + "assistantVersion": { + "type": "string", + "nullable": true, + "description": "This is the assistant version to use for this call. Supported only with\ndirect `assistantId`. Omit to follow the latest version." + }, + "transport": { + "description": "This is the transport of the call.", + "oneOf": [ + { + "$ref": "#/components/schemas/VapiWebsocketTransport", + "title": "VapiWebsocketTransport" + }, + { + "$ref": "#/components/schemas/VonageTransport", + "title": "VonageTransport" + }, + { + "$ref": "#/components/schemas/TwilioTransport", + "title": "TwilioTransport" + }, + { + "$ref": "#/components/schemas/VapiSipTransport", + "title": "VapiSipTransport" + }, + { + "$ref": "#/components/schemas/TelnyxTransport", + "title": "TelnyxTransport" + }, + { + "$ref": "#/components/schemas/VapiWebCallTransport", + "title": "VapiWebCallTransport" + } + ] + }, + "customers": { + "description": "This is used to issue batch calls to multiple customers.\n\nOnly relevant for `outboundPhoneCall`. To call a single customer, use `customer` instead.", + "type": "array", + "items": { + "$ref": "#/components/schemas/CreateCustomerDTO" + } + }, + "name": { + "type": "string", + "description": "This is the name of the call. This is just for your own reference.", + "maxLength": 40 + }, + "schedulePlan": { + "description": "This is the schedule plan of the call.", + "allOf": [ + { + "$ref": "#/components/schemas/SchedulePlan" + } + ] + }, + "assistantId": { + "type": "string", + "description": "This is the assistant ID that will be used for the call. To use a transient assistant, use `assistant` instead.\n\nTo start a call with:\n- Assistant, use `assistantId` or `assistant`\n- Squad, use `squadId` or `squad`\n- Workflow, use `workflowId` or `workflow`" + }, + "assistant": { + "description": "This is the assistant that will be used for the call. To use an existing assistant, use `assistantId` instead.\n\nTo start a call with:\n- Assistant, use `assistant`\n- Squad, use `squad`\n- Workflow, use `workflow`", + "allOf": [ + { + "$ref": "#/components/schemas/CreateAssistantDTO" + } + ] + }, + "assistantOverrides": { + "description": "These are the overrides for the `assistant` or `assistantId`'s settings and template variables.", + "allOf": [ + { + "$ref": "#/components/schemas/AssistantOverrides" + } + ] + }, + "squadId": { + "type": "string", + "description": "This is the squad that will be used for the call. To use a transient squad, use `squad` instead.\n\nTo start a call with:\n- Assistant, use `assistant` or `assistantId`\n- Squad, use `squad` or `squadId`\n- Workflow, use `workflow` or `workflowId`" + }, + "squad": { + "description": "This is a squad that will be used for the call. To use an existing squad, use `squadId` instead.\n\nTo start a call with:\n- Assistant, use `assistant` or `assistantId`\n- Squad, use `squad` or `squadId`\n- Workflow, use `workflow` or `workflowId`", + "allOf": [ + { + "$ref": "#/components/schemas/CreateSquadDTO" + } + ] + }, + "squadOverrides": { + "description": "These are the overrides for the `squad` or `squadId`'s member settings and template variables.\nThis will apply to all members of the squad.", + "allOf": [ + { + "$ref": "#/components/schemas/AssistantOverrides" + } + ] + }, + "workflowId": { + "type": "string", + "description": "This is the workflow that will be used for the call. To use a transient workflow, use `workflow` instead.\n\nTo start a call with:\n- Assistant, use `assistant` or `assistantId`\n- Squad, use `squad` or `squadId`\n- Workflow, use `workflow` or `workflowId`" + }, + "workflow": { + "description": "This is a workflow that will be used for the call. To use an existing workflow, use `workflowId` instead.\n\nTo start a call with:\n- Assistant, use `assistant` or `assistantId`\n- Squad, use `squad` or `squadId`\n- Workflow, use `workflow` or `workflowId`", + "allOf": [ + { + "$ref": "#/components/schemas/CreateWorkflowDTO" + } + ] + }, + "workflowOverrides": { + "description": "These are the overrides for the `workflow` or `workflowId`'s settings and template variables.", + "allOf": [ + { + "$ref": "#/components/schemas/WorkflowOverrides" + } + ] + }, + "phoneNumberId": { + "type": "string", + "description": "This is the phone number that will be used for the call. To use a transient number, use `phoneNumber` instead.\n\nOnly relevant for `outboundPhoneCall` and `inboundPhoneCall` type." + }, + "phoneNumber": { + "description": "This is the phone number that will be used for the call. To use an existing number, use `phoneNumberId` instead.\n\nOnly relevant for `outboundPhoneCall` and `inboundPhoneCall` type.", + "allOf": [ + { + "$ref": "#/components/schemas/ImportTwilioPhoneNumberDTO" + } + ] + }, + "customerId": { + "type": "string", + "description": "This is the customer that will be called. To call a transient customer , use `customer` instead.\n\nOnly relevant for `outboundPhoneCall` and `inboundPhoneCall` type." + }, + "customer": { + "description": "This is the customer that will be called. To call an existing customer, use `customerId` instead.\n\nOnly relevant for `outboundPhoneCall` and `inboundPhoneCall` type.", + "allOf": [ + { + "$ref": "#/components/schemas/CreateCustomerDTO" + } + ] + } + } + }, + "StructuredOutputFilterDTO": { + "type": "object", + "properties": { + "eq": { + "type": "string", + "description": "Equal to" + }, + "neq": { + "type": "string", + "description": "Not equal to" + }, + "gt": { + "type": "string", + "description": "Greater than" + }, + "gte": { + "type": "string", + "description": "Greater than or equal to" + }, + "lt": { + "type": "string", + "description": "Less than" + }, + "lte": { + "type": "string", + "description": "Less than or equal to" + }, + "contains": { + "type": "string", + "description": "Contains" + }, + "notContains": { + "type": "string", + "description": "Not contains" + } + } + }, + "CallPaginatedResponse": { + "type": "object", + "properties": { + "results": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Call" + } + }, + "metadata": { + "$ref": "#/components/schemas/PaginationMeta" + } + }, + "required": [ + "results", + "metadata" + ] + }, + "CreateOutboundCallDTO": { + "type": "object", + "properties": { + "assistantVersion": { + "type": "string", + "nullable": true, + "description": "This is the assistant version to use for this call. Supported only with\ndirect `assistantId`. Omit to follow the latest version." + }, + "transport": { + "description": "This is the transport of the call.", + "oneOf": [ + { + "$ref": "#/components/schemas/VapiWebsocketTransport", + "title": "VapiWebsocketTransport" + }, + { + "$ref": "#/components/schemas/VonageTransport", + "title": "VonageTransport" + }, + { + "$ref": "#/components/schemas/TwilioTransport", + "title": "TwilioTransport" + }, + { + "$ref": "#/components/schemas/VapiSipTransport", + "title": "VapiSipTransport" + }, + { + "$ref": "#/components/schemas/TelnyxTransport", + "title": "TelnyxTransport" + }, + { + "$ref": "#/components/schemas/VapiWebCallTransport", + "title": "VapiWebCallTransport" + } + ] + }, + "customers": { + "description": "This is used to issue batch calls to multiple customers.\n\nOnly relevant for `outboundPhoneCall`. To call a single customer, use `customer` instead.", + "type": "array", + "items": { + "$ref": "#/components/schemas/CreateCustomerDTO" + } + }, + "name": { + "type": "string", + "description": "This is the name of the call. This is just for your own reference.", + "maxLength": 40 + }, + "schedulePlan": { + "description": "This is the schedule plan of the call.", + "allOf": [ + { + "$ref": "#/components/schemas/SchedulePlan" + } + ] + }, + "assistantId": { + "type": "string", + "description": "This is the assistant ID that will be used for the call. To use a transient assistant, use `assistant` instead.\n\nTo start a call with:\n- Assistant, use `assistantId` or `assistant`\n- Squad, use `squadId` or `squad`\n- Workflow, use `workflowId` or `workflow`" + }, + "assistant": { + "description": "This is the assistant that will be used for the call. To use an existing assistant, use `assistantId` instead.\n\nTo start a call with:\n- Assistant, use `assistant`\n- Squad, use `squad`\n- Workflow, use `workflow`", + "allOf": [ + { + "$ref": "#/components/schemas/CreateAssistantDTO" + } + ] + }, + "assistantOverrides": { + "description": "These are the overrides for the `assistant` or `assistantId`'s settings and template variables.", + "allOf": [ + { + "$ref": "#/components/schemas/AssistantOverrides" + } + ] + }, + "squadId": { + "type": "string", + "description": "This is the squad that will be used for the call. To use a transient squad, use `squad` instead.\n\nTo start a call with:\n- Assistant, use `assistant` or `assistantId`\n- Squad, use `squad` or `squadId`\n- Workflow, use `workflow` or `workflowId`" + }, + "squad": { + "description": "This is a squad that will be used for the call. To use an existing squad, use `squadId` instead.\n\nTo start a call with:\n- Assistant, use `assistant` or `assistantId`\n- Squad, use `squad` or `squadId`\n- Workflow, use `workflow` or `workflowId`", + "allOf": [ + { + "$ref": "#/components/schemas/CreateSquadDTO" + } + ] + }, + "squadOverrides": { + "description": "These are the overrides for the `squad` or `squadId`'s member settings and template variables.\nThis will apply to all members of the squad.", + "allOf": [ + { + "$ref": "#/components/schemas/AssistantOverrides" + } + ] + }, + "workflowId": { + "type": "string", + "description": "This is the workflow that will be used for the call. To use a transient workflow, use `workflow` instead.\n\nTo start a call with:\n- Assistant, use `assistant` or `assistantId`\n- Squad, use `squad` or `squadId`\n- Workflow, use `workflow` or `workflowId`" + }, + "workflow": { + "description": "This is a workflow that will be used for the call. To use an existing workflow, use `workflowId` instead.\n\nTo start a call with:\n- Assistant, use `assistant` or `assistantId`\n- Squad, use `squad` or `squadId`\n- Workflow, use `workflow` or `workflowId`", + "allOf": [ + { + "$ref": "#/components/schemas/CreateWorkflowDTO" + } + ] + }, + "workflowOverrides": { + "description": "These are the overrides for the `workflow` or `workflowId`'s settings and template variables.", + "allOf": [ + { + "$ref": "#/components/schemas/WorkflowOverrides" + } + ] + }, + "phoneNumberId": { + "type": "string", + "description": "This is the phone number that will be used for the call. To use a transient number, use `phoneNumber` instead.\n\nOnly relevant for `outboundPhoneCall` and `inboundPhoneCall` type." + }, + "phoneNumber": { + "description": "This is the phone number that will be used for the call. To use an existing number, use `phoneNumberId` instead.\n\nOnly relevant for `outboundPhoneCall` and `inboundPhoneCall` type.", + "allOf": [ + { + "$ref": "#/components/schemas/ImportTwilioPhoneNumberDTO" + } + ] + }, + "customerId": { + "type": "string", + "description": "This is the customer that will be called. To call a transient customer , use `customer` instead.\n\nOnly relevant for `outboundPhoneCall` and `inboundPhoneCall` type." + }, + "customer": { + "description": "This is the customer that will be called. To call an existing customer, use `customerId` instead.\n\nOnly relevant for `outboundPhoneCall` and `inboundPhoneCall` type.", + "allOf": [ + { + "$ref": "#/components/schemas/CreateCustomerDTO" + } + ] + } + } + }, + "CreateWebCallDTO": { + "type": "object", + "properties": { + "assistantVersion": { + "type": "string", + "nullable": true, + "description": "This is the assistant version to use for this call. Supported only with\ndirect `assistantId`. Omit to follow the latest version." + }, + "roomDeleteOnUserLeaveEnabled": { + "type": "boolean", + "default": true + }, + "assistantId": { + "type": "string", + "description": "This is the assistant ID that will be used for the call. To use a transient assistant, use `assistant` instead.\n\nTo start a call with:\n- Assistant, use `assistantId` or `assistant`\n- Squad, use `squadId` or `squad`\n- Workflow, use `workflowId` or `workflow`" + }, + "assistant": { + "description": "This is the assistant that will be used for the call. To use an existing assistant, use `assistantId` instead.\n\nTo start a call with:\n- Assistant, use `assistant`\n- Squad, use `squad`\n- Workflow, use `workflow`", + "allOf": [ + { + "$ref": "#/components/schemas/CreateAssistantDTO" + } + ] + }, + "assistantOverrides": { + "description": "These are the overrides for the `assistant` or `assistantId`'s settings and template variables.", + "allOf": [ + { + "$ref": "#/components/schemas/AssistantOverrides" + } + ] + }, + "squadId": { + "type": "string", + "description": "This is the squad that will be used for the call. To use a transient squad, use `squad` instead.\n\nTo start a call with:\n- Assistant, use `assistant` or `assistantId`\n- Squad, use `squad` or `squadId`\n- Workflow, use `workflow` or `workflowId`" + }, + "squad": { + "description": "This is a squad that will be used for the call. To use an existing squad, use `squadId` instead.\n\nTo start a call with:\n- Assistant, use `assistant` or `assistantId`\n- Squad, use `squad` or `squadId`\n- Workflow, use `workflow` or `workflowId`", + "allOf": [ + { + "$ref": "#/components/schemas/CreateSquadDTO" + } + ] + }, + "squadOverrides": { + "description": "These are the overrides for the `squad` or `squadId`'s member settings and template variables.\nThis will apply to all members of the squad.", + "allOf": [ + { + "$ref": "#/components/schemas/AssistantOverrides" + } + ] + }, + "workflowId": { + "type": "string", + "description": "This is the workflow that will be used for the call. To use a transient workflow, use `workflow` instead.\n\nTo start a call with:\n- Assistant, use `assistant` or `assistantId`\n- Squad, use `squad` or `squadId`\n- Workflow, use `workflow` or `workflowId`" + }, + "workflow": { + "description": "This is a workflow that will be used for the call. To use an existing workflow, use `workflowId` instead.\n\nTo start a call with:\n- Assistant, use `assistant` or `assistantId`\n- Squad, use `squad` or `squadId`\n- Workflow, use `workflow` or `workflowId`", + "allOf": [ + { + "$ref": "#/components/schemas/CreateWorkflowDTO" + } + ] + }, + "workflowOverrides": { + "description": "These are the overrides for the `workflow` or `workflowId`'s settings and template variables.", + "allOf": [ + { + "$ref": "#/components/schemas/WorkflowOverrides" + } + ] + } + } + }, + "UpdateCallDTO": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "This is the name of the call. This is just for your own reference.", + "maxLength": 40 + } + } + }, + "DeleteCallDTO": { + "type": "object", + "properties": { + "ids": { + "description": "These are the Call IDs to be bulk deleted.\nIf provided, the call ID if any in the request query will be ignored\nWhen requesting a bulk delete, updates when a call is deleted will be sent as a webhook to the server URL configured in the Org settings.\nIt may take up to a few hours to complete the bulk delete, and will be asynchronous.", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "DeveloperMessage": { + "type": "object", + "properties": { + "role": { + "type": "string", + "description": "This is the role of the message author", + "default": "developer", + "enum": [ + "developer" + ] + }, + "content": { + "type": "string", + "description": "This is the content of the developer message", + "maxLength": 10000 + }, + "name": { + "type": "string", + "description": "This is an optional name for the participant", + "maxLength": 40 + }, + "metadata": { + "type": "object", + "description": "This is an optional metadata for the message" + } + }, + "required": [ + "role", + "content" + ] + }, + "ToolCallFunction": { + "type": "object", + "properties": { + "arguments": { + "type": "string", + "description": "This is the arguments to call the function with" + }, + "name": { + "type": "string", + "description": "This is the name of the function to call", + "maxLength": 80 + } + }, + "required": [ + "arguments", + "name" + ] + }, + "ToolCall": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "This is the ID of the tool call" + }, + "type": { + "type": "string", + "description": "This is the type of tool" + }, + "function": { + "description": "This is the function that was called", + "allOf": [ + { + "$ref": "#/components/schemas/ToolCallFunction" + } + ] + } + }, + "required": [ + "id", + "type", + "function" + ] + }, + "AssistantMessage": { + "type": "object", + "properties": { + "role": { + "type": "string", + "description": "This is the role of the message author", + "default": "assistant", + "enum": [ + "assistant" + ] + }, + "content": { + "type": "string", + "description": "This is the content of the assistant message", + "maxLength": 10000 + }, + "refusal": { + "type": "string", + "description": "This is the refusal message generated by the model", + "maxLength": 10000 + }, + "tool_calls": { + "description": "This is the tool calls generated by the model", + "type": "array", + "items": { + "$ref": "#/components/schemas/ToolCall" + } + }, + "name": { + "type": "string", + "description": "This is an optional name for the participant", + "maxLength": 40 + }, + "metadata": { + "type": "object", + "description": "This is an optional metadata for the message" + } + }, + "required": [ + "role" + ] + }, + "ToolMessage": { + "type": "object", + "properties": { + "role": { + "type": "string", + "description": "This is the role of the message author", + "default": "tool", + "enum": [ + "tool" + ] + }, + "content": { + "type": "string", + "description": "This is the content of the tool message", + "maxLength": 10000 + }, + "tool_call_id": { + "type": "string", + "description": "This is the ID of the tool call this message is responding to" + }, + "name": { + "type": "string", + "description": "This is an optional name for the participant", + "maxLength": 40 + }, + "metadata": { + "type": "object", + "description": "This is an optional metadata for the message" + } + }, + "required": [ + "role", + "content", + "tool_call_id" + ] + }, + "FunctionCall": { + "type": "object", + "properties": { + "arguments": { + "type": "string", + "description": "This is the arguments to call the function with" + }, + "name": { + "type": "string", + "description": "This is the name of the function to call", + "maxLength": 40 + } + }, + "required": [ + "arguments", + "name" + ] + }, + "Chat": { + "type": "object", + "properties": { + "assistantId": { + "type": "string", + "description": "This is the assistant that will be used for the chat. To use an existing assistant, use `assistantId` instead." + }, + "assistant": { + "description": "This is the assistant that will be used for the chat. To use an existing assistant, use `assistantId` instead.", + "allOf": [ + { + "$ref": "#/components/schemas/CreateAssistantDTO" + } + ] + }, + "assistantOverrides": { + "description": "These are the variable values that will be used to replace template variables in the assistant messages.\nOnly variable substitution is supported in chat contexts - other assistant properties cannot be overridden.", + "allOf": [ + { + "$ref": "#/components/schemas/AssistantOverrides" + } + ] + }, + "squadId": { + "type": "string", + "description": "This is the squad that will be used for the chat. To use a transient squad, use `squad` instead." + }, + "squad": { + "description": "This is the squad that will be used for the chat. To use an existing squad, use `squadId` instead.", + "allOf": [ + { + "$ref": "#/components/schemas/CreateSquadDTO" + } + ] + }, + "name": { + "type": "string", + "description": "This is the name of the chat. This is just for your own reference.", + "maxLength": 40 + }, + "sessionId": { + "type": "string", + "description": "This is the ID of the session that will be used for the chat.\nMutually exclusive with previousChatId." + }, + "input": { + "description": "This is the input text for the chat.\nCan be a string or an array of chat messages.", + "oneOf": [ + { + "type": "string", + "title": "String" + }, + { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/SystemMessage", + "title": "SystemMessage" + }, + { + "$ref": "#/components/schemas/UserMessage", + "title": "UserMessage" + }, + { + "$ref": "#/components/schemas/AssistantMessage", + "title": "AssistantMessage" + }, + { + "$ref": "#/components/schemas/ToolMessage", + "title": "ToolMessage" + }, + { + "$ref": "#/components/schemas/DeveloperMessage", + "title": "DeveloperMessage" + } + ] + }, + "title": "MessageArray" + } + ], + "examples": [ + "Hello, how can you help me?", + [ + { + "role": "user", + "content": "Hello, how can you help me?" + } + ] + ] + }, + "stream": { + "type": "boolean", + "description": "This is a flag that determines whether the response should be streamed.\nWhen true, the response will be sent as chunks of text.", + "default": false + }, + "previousChatId": { + "type": "string", + "description": "This is the ID of the chat that will be used as context for the new chat.\nThe messages from the previous chat will be used as context.\nMutually exclusive with sessionId." + }, + "id": { + "type": "string", + "description": "This is the unique identifier for the chat." + }, + "orgId": { + "type": "string", + "description": "This is the unique identifier for the org that this chat belongs to." + }, + "messages": { + "type": "array", + "description": "This is an array of messages used as context for the chat.\nUsed to provide message history for multi-turn conversations.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/SystemMessage", + "title": "SystemMessage" + }, + { + "$ref": "#/components/schemas/UserMessage", + "title": "UserMessage" + }, + { + "$ref": "#/components/schemas/AssistantMessage", + "title": "AssistantMessage" + }, + { + "$ref": "#/components/schemas/ToolMessage", + "title": "ToolMessage" + }, + { + "$ref": "#/components/schemas/DeveloperMessage", + "title": "DeveloperMessage" + } + ] + } + }, + "output": { + "type": "array", + "description": "This is the output messages generated by the system in response to the input.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/SystemMessage", + "title": "SystemMessage" + }, + { + "$ref": "#/components/schemas/UserMessage", + "title": "UserMessage" + }, + { + "$ref": "#/components/schemas/AssistantMessage", + "title": "AssistantMessage" + }, + { + "$ref": "#/components/schemas/ToolMessage", + "title": "ToolMessage" + }, + { + "$ref": "#/components/schemas/DeveloperMessage", + "title": "DeveloperMessage" + } + ] + } + }, + "createdAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the chat was created." + }, + "updatedAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the chat was last updated." + }, + "costs": { + "type": "array", + "description": "These are the costs of individual components of the chat in USD.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/ModelCost", + "title": "ModelCost" + }, + { + "$ref": "#/components/schemas/ChatCost", + "title": "ChatCost" + } + ] + } + }, + "cost": { + "type": "number", + "description": "This is the cost of the chat in USD." + } + }, + "required": [ + "id", + "orgId", + "createdAt", + "updatedAt" + ] + }, + "TwilioSMSChatTransport": { + "type": "object", + "properties": { + "conversationType": { + "type": "string", + "description": "This is the conversation type of the call (ie, voice or chat).", + "default": "chat", + "enum": [ + "chat" + ] + }, + "phoneNumberId": { + "type": "string", + "description": "This is the phone number that will be used to send the SMS.\nIf provided, will create a new session. If not provided, uses existing session's phoneNumberId.\nThe phone number must have SMS enabled and belong to your organization." + }, + "customer": { + "description": "This is the customer who will receive the SMS.\nIf provided, will create a new session. If not provided, uses existing session's customer.", + "allOf": [ + { + "$ref": "#/components/schemas/CreateCustomerDTO" + } + ] + }, + "customerId": { + "type": "string", + "description": "This is the customerId of the customer who will receive the SMS." + }, + "useLLMGeneratedMessageForOutbound": { + "type": "boolean", + "description": "Whether to use LLM-generated messages for outbound SMS.\nWhen true (default), input is processed by the assistant for a response.\nWhen false, the input text is forwarded directly as the SMS message without LLM processing.\nUseful for sending pre-defined messages or notifications.", + "default": true + }, + "type": { + "type": "string", + "description": "The type of transport to use for sending the chat response.\nCurrently supports 'twilio.sms' for SMS delivery via Twilio.", + "enum": [ + "twilio.sms" + ] + } + }, + "required": [ + "type" + ] + }, + "CreateChatDTO": { + "type": "object", + "properties": { + "assistantId": { + "type": "string", + "description": "This is the assistant that will be used for the chat. To use an existing assistant, use `assistantId` instead." + }, + "assistant": { + "description": "This is the assistant that will be used for the chat. To use an existing assistant, use `assistantId` instead.", + "allOf": [ + { + "$ref": "#/components/schemas/CreateAssistantDTO" + } + ] + }, + "assistantOverrides": { + "description": "These are the variable values that will be used to replace template variables in the assistant messages.\nOnly variable substitution is supported in chat contexts - other assistant properties cannot be overridden.", + "allOf": [ + { + "$ref": "#/components/schemas/AssistantOverrides" + } + ] + }, + "squadId": { + "type": "string", + "description": "This is the squad that will be used for the chat. To use a transient squad, use `squad` instead." + }, + "squad": { + "description": "This is the squad that will be used for the chat. To use an existing squad, use `squadId` instead.", + "allOf": [ + { + "$ref": "#/components/schemas/CreateSquadDTO" + } + ] + }, + "name": { + "type": "string", + "description": "This is the name of the chat. This is just for your own reference.", + "maxLength": 40 + }, + "sessionId": { + "type": "string", + "description": "This is the ID of the session that will be used for the chat.\nMutually exclusive with previousChatId." + }, + "input": { + "description": "This is the input text for the chat.\nCan be a string or an array of chat messages.\nThis field is REQUIRED for chat creation.", + "oneOf": [ + { + "type": "string", + "title": "String" + }, + { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/SystemMessage", + "title": "SystemMessage" + }, + { + "$ref": "#/components/schemas/UserMessage", + "title": "UserMessage" + }, + { + "$ref": "#/components/schemas/AssistantMessage", + "title": "AssistantMessage" + }, + { + "$ref": "#/components/schemas/ToolMessage", + "title": "ToolMessage" + }, + { + "$ref": "#/components/schemas/DeveloperMessage", + "title": "DeveloperMessage" + } + ] + }, + "title": "MessageArray" + } + ], + "examples": [ + "Hello, how can you help me?", + [ + { + "role": "user", + "content": "Hello, how can you help me?" + } + ] + ] + }, + "stream": { + "type": "boolean", + "description": "This is a flag that determines whether the response should be streamed.\nWhen true, the response will be sent as chunks of text.", + "default": false + }, + "previousChatId": { + "type": "string", + "description": "This is the ID of the chat that will be used as context for the new chat.\nThe messages from the previous chat will be used as context.\nMutually exclusive with sessionId." + }, + "transport": { + "description": "This is used to send the chat through a transport like SMS.\nIf transport.phoneNumberId and transport.customer are provided, creates a new session.\nIf sessionId is provided without transport fields, uses existing session data.\nCannot specify both sessionId and transport fields (phoneNumberId/customer) together.", + "allOf": [ + { + "$ref": "#/components/schemas/TwilioSMSChatTransport" + } + ] + } + }, + "required": [ + "input" + ] + }, + "GetChatPaginatedDTO": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "This is the unique identifier for the chat to filter by." + }, + "assistantId": { + "type": "string", + "description": "This is the unique identifier for the assistant that will be used for the chat." + }, + "assistantIdAny": { + "type": "string", + "description": "Filter by multiple assistant IDs. Provide as comma-separated values.", + "example": "assistant-1,assistant-2,assistant-3" + }, + "squadId": { + "type": "string", + "description": "This is the unique identifier for the squad that will be used for the chat." + }, + "sessionId": { + "type": "string", + "description": "This is the unique identifier for the session that will be used for the chat." + }, + "previousChatId": { + "type": "string", + "description": "This is the unique identifier for the previous chat to filter by." + }, + "idAny": { + "type": "string", + "description": "Filter by multiple chat IDs. Provide as comma-separated values." + }, + "page": { + "type": "number", + "description": "This is the page number to return. Defaults to 1.", + "minimum": 1 + }, + "sortOrder": { + "type": "string", + "description": "This is the sort order for pagination. Defaults to 'DESC'.", + "enum": [ + "ASC", + "DESC" + ] + }, + "sortBy": { + "type": "string", + "description": "This is the column to sort by. Defaults to 'createdAt'.", + "enum": [ + "createdAt", + "duration", + "cost" + ] + }, + "limit": { + "type": "number", + "description": "This is the maximum number of items to return. Defaults to 100.", + "minimum": 0, + "maximum": 1000 + }, + "createdAtGt": { + "format": "date-time", + "type": "string", + "description": "This will return items where the createdAt is greater than the specified value." + }, + "createdAtLt": { + "format": "date-time", + "type": "string", + "description": "This will return items where the createdAt is less than the specified value." + }, + "createdAtGe": { + "format": "date-time", + "type": "string", + "description": "This will return items where the createdAt is greater than or equal to the specified value." + }, + "createdAtLe": { + "format": "date-time", + "type": "string", + "description": "This will return items where the createdAt is less than or equal to the specified value." + }, + "updatedAtGt": { + "format": "date-time", + "type": "string", + "description": "This will return items where the updatedAt is greater than the specified value." + }, + "updatedAtLt": { + "format": "date-time", + "type": "string", + "description": "This will return items where the updatedAt is less than the specified value." + }, + "updatedAtGe": { + "format": "date-time", + "type": "string", + "description": "This will return items where the updatedAt is greater than or equal to the specified value." + }, + "updatedAtLe": { + "format": "date-time", + "type": "string", + "description": "This will return items where the updatedAt is less than or equal to the specified value." + } + } + }, + "ChatPaginatedResponse": { + "type": "object", + "properties": { + "results": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Chat" + } + }, + "metadata": { + "$ref": "#/components/schemas/PaginationMeta" + } + }, + "required": [ + "results", + "metadata" + ] + }, + "CreateChatStreamResponse": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "This is the unique identifier for the streaming response." + }, + "sessionId": { + "type": "string", + "description": "This is the ID of the session that will be used for the chat.\nHelps track conversation context across multiple messages." + }, + "path": { + "type": "string", + "description": "This is the path to the content being updated.\nFormat: `chat.output[{contentIndex}].content` where contentIndex identifies the specific content item.", + "example": "chat.output[0].content" + }, + "delta": { + "type": "string", + "description": "This is the incremental content chunk being streamed." + } + }, + "required": [ + "id", + "path", + "delta" + ] + }, + "OpenAIResponsesRequest": { + "type": "object", + "properties": { + "assistantId": { + "type": "string", + "description": "This is the assistant that will be used for the chat. To use an existing assistant, use `assistantId` instead." + }, + "assistant": { + "description": "This is the assistant that will be used for the chat. To use an existing assistant, use `assistantId` instead.", + "allOf": [ + { + "$ref": "#/components/schemas/CreateAssistantDTO" + } + ] + }, + "assistantOverrides": { + "description": "These are the variable values that will be used to replace template variables in the assistant messages.\nOnly variable substitution is supported in chat contexts - other assistant properties cannot be overridden.", + "allOf": [ + { + "$ref": "#/components/schemas/AssistantOverrides" + } + ] + }, + "squadId": { + "type": "string", + "description": "This is the squad that will be used for the chat. To use a transient squad, use `squad` instead." + }, + "squad": { + "description": "This is the squad that will be used for the chat. To use an existing squad, use `squadId` instead.", + "allOf": [ + { + "$ref": "#/components/schemas/CreateSquadDTO" + } + ] + }, + "name": { + "type": "string", + "description": "This is the name of the chat. This is just for your own reference.", + "maxLength": 40 + }, + "sessionId": { + "type": "string", + "description": "This is the ID of the session that will be used for the chat.\nMutually exclusive with previousChatId." + }, + "input": { + "description": "This is the input text for the chat.\nCan be a string or an array of chat messages.\nThis field is REQUIRED for chat creation.", + "oneOf": [ + { + "type": "string", + "title": "String" + }, + { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/SystemMessage", + "title": "SystemMessage" + }, + { + "$ref": "#/components/schemas/UserMessage", + "title": "UserMessage" + }, + { + "$ref": "#/components/schemas/AssistantMessage", + "title": "AssistantMessage" + }, + { + "$ref": "#/components/schemas/ToolMessage", + "title": "ToolMessage" + }, + { + "$ref": "#/components/schemas/DeveloperMessage", + "title": "DeveloperMessage" + } + ] + }, + "title": "MessageArray" + } + ], + "examples": [ + "Hello, how can you help me?", + [ + { + "role": "user", + "content": "Hello, how can you help me?" + } + ] + ] + }, + "stream": { + "type": "boolean", + "description": "Whether to stream the response or not.", + "default": true + }, + "previousChatId": { + "type": "string", + "description": "This is the ID of the chat that will be used as context for the new chat.\nThe messages from the previous chat will be used as context.\nMutually exclusive with sessionId." + }, + "transport": { + "description": "This is used to send the chat through a transport like SMS.\nIf transport.phoneNumberId and transport.customer are provided, creates a new session.\nIf sessionId is provided without transport fields, uses existing session data.\nCannot specify both sessionId and transport fields (phoneNumberId/customer) together.", + "allOf": [ + { + "$ref": "#/components/schemas/TwilioSMSChatTransport" + } + ] + } + }, + "required": [ + "input" + ] + }, + "ChatAssistantOverrides": { + "type": "object", + "properties": { + "variableValues": { + "type": "object", + "description": "Variable values for template substitution", + "example": { + "name": "John", + "company": "ACME Corp" + } + } + } + }, + "CreateWebCustomerDTO": { + "type": "object", + "properties": { + "numberE164CheckEnabled": { + "type": "boolean", + "description": "This is the flag to toggle the E164 check for the `number` field. This is an advanced property which should be used if you know your use case requires it.\n\nUse cases:\n- `false`: To allow non-E164 numbers like `+001234567890`, `1234`, or `abc`. This is useful for dialing out to non-E164 numbers on your SIP trunks.\n- `true` (default): To allow only E164 numbers like `+14155551234`. This is standard for PSTN calls.\n\nIf `false`, the `number` is still required to only contain alphanumeric characters (regex: `/^\\+?[a-zA-Z0-9]+$/`).\n\n@default true (E164 check is enabled)", + "default": true + }, + "extension": { + "type": "string", + "description": "This is the extension that will be dialed after the call is answered.", + "maxLength": 10, + "example": null + }, + "assistantOverrides": { + "description": "These are the variable values that will be used to replace template variables in the assistant messages.\nOnly variable substitution is supported in web chat - other assistant properties cannot be overridden.", + "allOf": [ + { + "$ref": "#/components/schemas/ChatAssistantOverrides" + } + ] + }, + "number": { + "type": "string", + "description": "This is the number of the customer.", + "minLength": 3, + "maxLength": 40 + }, + "sipUri": { + "type": "string", + "description": "This is the SIP URI of the customer." + }, + "name": { + "type": "string", + "description": "This is the name of the customer. This is just for your own reference.\n\nFor SIP inbound calls, this is extracted from the `From` SIP header with format `\"Display Name\" `.", + "maxLength": 40 + }, + "email": { + "type": "string", + "description": "This is the email of the customer.", + "maxLength": 40 + }, + "externalId": { + "type": "string", + "description": "This is the external ID of the customer.", + "maxLength": 40 + } + } + }, + "CreateWebChatDTO": { + "type": "object", + "properties": { + "assistantId": { + "type": "string", + "description": "This is the assistant ID to use for this chat. To use a transient assistant, use `assistant` instead." + }, + "assistant": { + "description": "This is the transient assistant configuration for this chat. To use an existing assistant, use `assistantId` instead.", + "allOf": [ + { + "$ref": "#/components/schemas/CreateAssistantDTO" + } + ] + }, + "sessionId": { + "type": "string", + "description": "This is the ID of the session that will be used for the chat.\nIf provided, the conversation will continue from the previous state.\nIf not provided or expired, a new session will be created." + }, + "sessionExpirationSeconds": { + "type": "number", + "description": "This is the expiration time for the session. This can ONLY be set if starting a new chat and therefore a new session is created.\nIf session already exists, this will be ignored and NOT be updated for the existing session. Use PATCH /session/:id to update the session expiration time.", + "minimum": 60, + "maximum": 2592000 + }, + "assistantOverrides": { + "description": "These are the variable values that will be used to replace template variables in the assistant messages.\nOnly variable substitution is supported in web chat - other assistant properties cannot be overridden.", + "allOf": [ + { + "$ref": "#/components/schemas/ChatAssistantOverrides" + } + ] + }, + "customer": { + "description": "This is the customer information for the chat.\nUsed to automatically manage sessions for repeat customers.", + "allOf": [ + { + "$ref": "#/components/schemas/CreateWebCustomerDTO" + } + ] + }, + "input": { + "description": "This is the input text for the chat.\nCan be a string or an array of chat messages.", + "oneOf": [ + { + "type": "string", + "title": "String" + }, + { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/SystemMessage", + "title": "SystemMessage" + }, + { + "$ref": "#/components/schemas/UserMessage", + "title": "UserMessage" + }, + { + "$ref": "#/components/schemas/AssistantMessage", + "title": "AssistantMessage" + }, + { + "$ref": "#/components/schemas/ToolMessage", + "title": "ToolMessage" + }, + { + "$ref": "#/components/schemas/DeveloperMessage", + "title": "DeveloperMessage" + } + ] + }, + "title": "MessageArray" + } + ], + "examples": [ + "Hello, how can you help me?", + [ + { + "role": "user", + "content": "Hello, how can you help me?" + } + ] + ] + }, + "stream": { + "type": "boolean", + "description": "This is a flag that determines whether the response should be streamed.\nWhen true, the response will be sent as chunks of text.", + "default": false + }, + "sessionEnd": { + "type": "boolean", + "description": "This is a flag to indicate end of session. When true, the session will be marked as completed and the chat will be ended.\nUsed to end session to send End-of-session report to the customer.\nWhen flag is set to true, any messages sent will not be processed and session will directly be marked as completed.", + "default": false + } + }, + "required": [ + "input" + ] + }, + "WebChat": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "This is the unique identifier for the chat." + }, + "sessionId": { + "type": "string", + "description": "This is the ID of the session for the chat. Send it in the next chat request to continue the conversation." + }, + "output": { + "type": "array", + "description": "This is the output messages generated by the system in response to the input.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/SystemMessage", + "title": "SystemMessage" + }, + { + "$ref": "#/components/schemas/UserMessage", + "title": "UserMessage" + }, + { + "$ref": "#/components/schemas/AssistantMessage", + "title": "AssistantMessage" + }, + { + "$ref": "#/components/schemas/ToolMessage", + "title": "ToolMessage" + }, + { + "$ref": "#/components/schemas/DeveloperMessage", + "title": "DeveloperMessage" + } + ] + } + } + }, + "required": [ + "id", + "output" + ] + }, + "OpenAIWebChatRequest": { + "type": "object", + "properties": { + "assistantId": { + "type": "string", + "description": "This is the assistant ID to use for this chat. To use a transient assistant, use `assistant` instead." + }, + "assistant": { + "description": "This is the transient assistant configuration for this chat. To use an existing assistant, use `assistantId` instead.", + "allOf": [ + { + "$ref": "#/components/schemas/CreateAssistantDTO" + } + ] + }, + "sessionId": { + "type": "string", + "description": "This is the ID of the session that will be used for the chat.\nIf provided, the conversation will continue from the previous state.\nIf not provided or expired, a new session will be created." + }, + "sessionExpirationSeconds": { + "type": "number", + "description": "This is the expiration time for the session. This can ONLY be set if starting a new chat and therefore a new session is created.\nIf session already exists, this will be ignored and NOT be updated for the existing session. Use PATCH /session/:id to update the session expiration time.", + "minimum": 60, + "maximum": 2592000 + }, + "assistantOverrides": { + "description": "These are the variable values that will be used to replace template variables in the assistant messages.\nOnly variable substitution is supported in web chat - other assistant properties cannot be overridden.", + "allOf": [ + { + "$ref": "#/components/schemas/ChatAssistantOverrides" + } + ] + }, + "customer": { + "description": "This is the customer information for the chat.\nUsed to automatically manage sessions for repeat customers.", + "allOf": [ + { + "$ref": "#/components/schemas/CreateWebCustomerDTO" + } + ] + }, + "input": { + "description": "This is the input text for the chat.\nCan be a string or an array of chat messages.", + "oneOf": [ + { + "type": "string", + "title": "String" + }, + { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/SystemMessage", + "title": "SystemMessage" + }, + { + "$ref": "#/components/schemas/UserMessage", + "title": "UserMessage" + }, + { + "$ref": "#/components/schemas/AssistantMessage", + "title": "AssistantMessage" + }, + { + "$ref": "#/components/schemas/ToolMessage", + "title": "ToolMessage" + }, + { + "$ref": "#/components/schemas/DeveloperMessage", + "title": "DeveloperMessage" + } + ] + }, + "title": "MessageArray" + } + ], + "examples": [ + "Hello, how can you help me?", + [ + { + "role": "user", + "content": "Hello, how can you help me?" + } + ] + ] + }, + "stream": { + "type": "boolean", + "description": "Whether to stream the response or not.", + "default": true + }, + "sessionEnd": { + "type": "boolean", + "description": "This is a flag to indicate end of session. When true, the session will be marked as completed and the chat will be ended.\nUsed to end session to send End-of-session report to the customer.\nWhen flag is set to true, any messages sent will not be processed and session will directly be marked as completed.", + "default": false + } + }, + "required": [ + "input" + ] + }, + "ExportChatDTO": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "This is the unique identifier for the chat to filter by." + }, + "assistantId": { + "type": "string", + "description": "This is the unique identifier for the assistant that will be used for the chat." + }, + "assistantIdAny": { + "type": "string", + "description": "Filter by multiple assistant IDs. Provide as comma-separated values.", + "example": "assistant-1,assistant-2,assistant-3" + }, + "squadId": { + "type": "string", + "description": "This is the unique identifier for the squad that will be used for the chat." + }, + "sessionId": { + "type": "string", + "description": "This is the unique identifier for the session that will be used for the chat." + }, + "previousChatId": { + "type": "string", + "description": "This is the unique identifier for the previous chat to filter by." + }, + "idAny": { + "type": "string", + "description": "Filter by multiple chat IDs. Provide as comma-separated values." + }, + "columns": { + "type": "string", + "description": "Columns to include in the CSV export", + "enum": [ + "id", + "assistantId", + "squadId", + "sessionId", + "previousChatId", + "cost", + "messages", + "output", + "createdAt", + "updatedAt" + ], + "default": [ + "id", + "assistantId", + "squadId", + "sessionId", + "previousChatId", + "cost", + "messages", + "output", + "createdAt", + "updatedAt" + ] + }, + "email": { + "type": "string", + "description": "This is the email address to send the export to.\nRequired if userId is not available in the request context." + }, + "format": { + "type": "string", + "description": "This is the format of the export.\n\n@default csv", + "enum": [ + "csv", + "json" + ], + "default": "csv" + }, + "page": { + "type": "number", + "description": "This is the page number to return. Defaults to 1.", + "minimum": 1 + }, + "sortOrder": { + "type": "string", + "description": "This is the sort order for pagination. Defaults to 'DESC'.", + "enum": [ + "ASC", + "DESC" + ] + }, + "sortBy": { + "type": "string", + "description": "This is the column to sort by. Defaults to 'createdAt'.", + "enum": [ + "createdAt", + "duration", + "cost" + ] + }, + "limit": { + "type": "number", + "description": "This is the maximum number of items to return. Defaults to 100.", + "minimum": 0, + "maximum": 1000 + }, + "createdAtGt": { + "format": "date-time", + "type": "string", + "description": "This will return items where the createdAt is greater than the specified value." + }, + "createdAtLt": { + "format": "date-time", + "type": "string", + "description": "This will return items where the createdAt is less than the specified value." + }, + "createdAtGe": { + "format": "date-time", + "type": "string", + "description": "This will return items where the createdAt is greater than or equal to the specified value." + }, + "createdAtLe": { + "format": "date-time", + "type": "string", + "description": "This will return items where the createdAt is less than or equal to the specified value." + }, + "updatedAtGt": { + "format": "date-time", + "type": "string", + "description": "This will return items where the updatedAt is greater than the specified value." + }, + "updatedAtLt": { + "format": "date-time", + "type": "string", + "description": "This will return items where the updatedAt is less than the specified value." + }, + "updatedAtGe": { + "format": "date-time", + "type": "string", + "description": "This will return items where the updatedAt is greater than or equal to the specified value." + }, + "updatedAtLe": { + "format": "date-time", + "type": "string", + "description": "This will return items where the updatedAt is less than or equal to the specified value." + } + } + }, + "ResponseOutputText": { + "type": "object", + "properties": { + "annotations": { + "default": [], + "description": "Annotations in the text output", + "type": "array", + "items": { + "type": "object" + } + }, + "text": { + "type": "string", + "description": "The text output from the model" + }, + "type": { + "type": "string", + "default": "output_text", + "description": "The type of the output text", + "enum": [ + "output_text" + ] + } + }, + "required": [ + "annotations", + "text", + "type" + ] + }, + "ResponseOutputMessage": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "The unique ID of the output message" + }, + "content": { + "description": "Content of the output message", + "type": "array", + "items": { + "$ref": "#/components/schemas/ResponseOutputText" + } + }, + "role": { + "type": "string", + "default": "assistant", + "description": "The role of the output message", + "enum": [ + "assistant" + ] + }, + "status": { + "type": "string", + "description": "The status of the message", + "enum": [ + "in_progress", + "completed", + "incomplete" + ] + }, + "type": { + "type": "string", + "default": "message", + "description": "The type of the output message", + "enum": [ + "message" + ] + } + }, + "required": [ + "id", + "content", + "role", + "status", + "type" + ] + }, + "ResponseObject": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique identifier for this Response" + }, + "object": { + "type": "string", + "default": "response", + "description": "The object type", + "enum": [ + "response" + ] + }, + "created_at": { + "type": "number", + "description": "Unix timestamp (in seconds) of when this Response was created" + }, + "status": { + "type": "string", + "description": "Status of the response", + "enum": [ + "completed", + "failed", + "in_progress", + "incomplete" + ] + }, + "error": { + "type": "string", + "nullable": true, + "default": null, + "description": "Error message if the response failed" + }, + "output": { + "description": "Output messages from the model", + "type": "array", + "items": { + "$ref": "#/components/schemas/ResponseOutputMessage" + } + } + }, + "required": [ + "id", + "object", + "created_at", + "status", + "output" + ] + }, + "ResponseTextDeltaEvent": { + "type": "object", + "properties": { + "content_index": { + "type": "number", + "description": "Index of the content part" + }, + "delta": { + "type": "string", + "description": "Text delta being added" + }, + "item_id": { + "type": "string", + "description": "ID of the output item" + }, + "output_index": { + "type": "number", + "description": "Index of the output item" + }, + "type": { + "type": "string", + "default": "response.output_text.delta", + "description": "Event type", + "enum": [ + "response.output_text.delta" + ] + } + }, + "required": [ + "content_index", + "delta", + "item_id", + "output_index", + "type" + ] + }, + "ResponseTextDoneEvent": { + "type": "object", + "properties": { + "content_index": { + "type": "number", + "description": "Index of the content part" + }, + "item_id": { + "type": "string", + "description": "ID of the output item" + }, + "output_index": { + "type": "number", + "description": "Index of the output item" + }, + "text": { + "type": "string", + "description": "Complete text content" + }, + "type": { + "type": "string", + "default": "response.output_text.done", + "description": "Event type", + "enum": [ + "response.output_text.done" + ] + } + }, + "required": [ + "content_index", + "item_id", + "output_index", + "text", + "type" + ] + }, + "ResponseCompletedEvent": { + "type": "object", + "properties": { + "response": { + "description": "The completed response", + "allOf": [ + { + "$ref": "#/components/schemas/ResponseObject" + } + ] + }, + "type": { + "type": "string", + "default": "response.completed", + "description": "Event type", + "enum": [ + "response.completed" + ] + } + }, + "required": [ + "response", + "type" + ] + }, + "ResponseErrorEvent": { + "type": "object", + "properties": { + "type": { + "type": "string", + "default": "error", + "description": "Event type", + "enum": [ + "error" + ] + }, + "code": { + "type": "string", + "description": "Error code", + "example": "ERR_SOMETHING" + }, + "message": { + "type": "string", + "description": "Error message", + "example": "Something went wrong" + }, + "param": { + "type": "string", + "nullable": true, + "description": "Parameter that caused the error" + }, + "sequence_number": { + "type": "number", + "description": "Sequence number of the event", + "example": 1 + } + }, + "required": [ + "type", + "code", + "message", + "sequence_number" + ] + }, + "DialPlanEntry": { + "type": "object", + "properties": { + "phoneNumberId": { + "type": "string", + "description": "The phone number ID to use for calling the customers in this entry." + }, + "customers": { + "description": "The list of customers to call using this phone number.", + "type": "array", + "items": { + "$ref": "#/components/schemas/CreateCustomerDTO" + } + } + }, + "required": [ + "phoneNumberId", + "customers" + ] + }, + "CampaignPredialPlan": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Whether the pre-dial eligibility webhook is active. Defaults to true when `predialPlan` is set. Set to false to keep the plan without running the webhook (useful when duplicating a campaign)." + } + } + }, + "CreateCampaignDTO": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "This is the name of the campaign. This is just for your own reference.", + "example": "Q2 Sales Campaign" + }, + "assistantId": { + "type": "string", + "description": "This is the assistant ID that will be used for the campaign calls. Note: Only one of assistantId, workflowId, or squadId can be used." + }, + "workflowId": { + "type": "string", + "description": "This is the workflow ID that will be used for the campaign calls. Note: Only one of assistantId, workflowId, or squadId can be used." + }, + "squadId": { + "type": "string", + "description": "This is the squad ID that will be used for the campaign calls. Note: Only one of assistantId, workflowId, or squadId can be used." + }, + "phoneNumberId": { + "type": "string", + "description": "This is the phone number ID that will be used for the campaign calls. Required if dialPlan is not provided. Note: phoneNumberId and dialPlan are mutually exclusive." + }, + "dialPlan": { + "description": "This is a list of dial entries, each specifying a phone number and the customers to call using that number. Use this when you want different phone numbers to call different sets of customers. Note: phoneNumberId and dialPlan are mutually exclusive.", + "type": "array", + "items": { + "$ref": "#/components/schemas/DialPlanEntry" + } + }, + "schedulePlan": { + "description": "This is the schedule plan for the campaign. Calls will start at startedAt and continue until your organization’s concurrency limit is reached. Any remaining calls will be retried for up to one hour as capacity becomes available. After that hour or after latestAt, whichever comes first, any calls that couldn’t be placed won’t be retried.", + "allOf": [ + { + "$ref": "#/components/schemas/SchedulePlan" + } + ] + }, + "customers": { + "description": "These are the customers that will be called in the campaign. Required if dialPlan is not provided. Maximum of 10000 customers per campaign.", + "type": "array", + "items": { + "$ref": "#/components/schemas/CreateCustomerDTO" + } + }, + "maxConcurrency": { + "type": "number", + "minimum": 1, + "description": "This is the maximum number of concurrent calls that will be made for the campaign. Defaults to 10." + }, + "assistantOverrides": { + "description": "These are the overrides for the assistant's settings and template variables for the campaign. Use this when the campaign targets an `assistantId`.", + "allOf": [ + { + "$ref": "#/components/schemas/AssistantOverrides" + } + ] + }, + "squadOverrides": { + "description": "These are the overrides for the squad and template variables for the campaign. Use this when the campaign targets a `squadId`. Per-contact `squadOverrides` are deep-merged on top of this at dispatch time.", + "allOf": [ + { + "$ref": "#/components/schemas/AssistantOverrides" + } + ] + }, + "server": { + "description": "This is the server (URL, auth headers, timeout, etc.) for the campaign webhooks.", + "allOf": [ + { + "$ref": "#/components/schemas/Server" + } + ] + }, + "serverMessages": { + "type": "array", + "enum": [ + "campaign.started", + "campaign.cancelled", + "campaign.ended", + "campaign.archived", + "campaign.unarchived", + "contact.dispatched", + "contact.completed", + "contact.failed", + "contact.skipped", + "contact.predial-failed", + "campaign.job.continued" + ], + "example": [ + "campaign.started", + "contact.dispatched" + ], + "description": "These are the messages that will be sent to your Server URL.", + "items": { + "type": "string", + "enum": [ + "campaign.started", + "campaign.cancelled", + "campaign.ended", + "campaign.archived", + "campaign.unarchived", + "contact.dispatched", + "contact.completed", + "contact.failed", + "contact.skipped", + "contact.predial-failed", + "campaign.job.continued" + ] + } + }, + "predialPlan": { + "description": "This opts the campaign into the blocking `campaign.predial` eligibility webhook. When set, every contact triggers a `campaign.predial` POST to the Server URL before dialing, and the response `{ eligible: boolean }` decides whether the call is placed. Requires `server`. When unset, no pre-dial webhook is sent.", + "allOf": [ + { + "$ref": "#/components/schemas/CampaignPredialPlan" + } + ] + }, + "duplicateFromCampaignId": { + "type": "string", + "description": "Optional campaign ID to duplicate config from. Provided fields in the request override the source. If `customers` is omitted, contacts are copied from the source." + } + }, + "required": [ + "name" + ] + }, + "Campaign": { + "type": "object", + "properties": { + "status": { + "type": "string", + "description": "This is the status of the campaign.", + "enum": [ + "scheduled", + "in-progress", + "ended", + "cancelled", + "archived" + ] + }, + "endedReason": { + "type": "string", + "description": "This is the explanation for how the campaign ended.", + "enum": [ + "campaign.scheduled.ended-by-user", + "campaign.in-progress.ended-by-user", + "campaign.ended.success" + ] + }, + "name": { + "type": "string", + "description": "This is the name of the campaign. This is just for your own reference.", + "example": "Q2 Sales Campaign" + }, + "assistantId": { + "type": "string", + "description": "This is the assistant ID that will be used for the campaign calls. Note: Only one of assistantId, workflowId, or squadId can be used." + }, + "workflowId": { + "type": "string", + "description": "This is the workflow ID that will be used for the campaign calls. Note: Only one of assistantId, workflowId, or squadId can be used." + }, + "squadId": { + "type": "string", + "description": "This is the squad ID that will be used for the campaign calls. Note: Only one of assistantId, workflowId, or squadId can be used." + }, + "phoneNumberId": { + "type": "string", + "description": "This is the phone number ID that will be used for the campaign calls. Required if dialPlan is not provided. Note: phoneNumberId and dialPlan are mutually exclusive." + }, + "dialPlan": { + "description": "This is a list of dial entries, each specifying a phone number and the customers to call using that number. Use this when you want different phone numbers to call different sets of customers. Note: phoneNumberId and dialPlan are mutually exclusive.", + "type": "array", + "items": { + "$ref": "#/components/schemas/DialPlanEntry" + } + }, + "schedulePlan": { + "description": "This is the schedule plan for the campaign. Calls will start at startedAt and continue until your organization’s concurrency limit is reached. Any remaining calls will be retried for up to one hour as capacity becomes available. After that hour or after latestAt, whichever comes first, any calls that couldn’t be placed won’t be retried.", + "allOf": [ + { + "$ref": "#/components/schemas/SchedulePlan" + } + ] + }, + "customers": { + "description": "These are the customers that will be called in the campaign. Required if dialPlan is not provided. Maximum of 10000 customers per campaign.", + "type": "array", + "items": { + "$ref": "#/components/schemas/CreateCustomerDTO" + } + }, + "maxConcurrency": { + "type": "number", + "minimum": 1, + "description": "This is the maximum number of concurrent calls that will be made for the campaign. Defaults to 10." + }, + "assistantOverrides": { + "description": "These are the overrides for the assistant's settings and template variables for the campaign. Use this when the campaign targets an `assistantId`.", + "allOf": [ + { + "$ref": "#/components/schemas/AssistantOverrides" + } + ] + }, + "squadOverrides": { + "description": "These are the overrides for the squad and template variables for the campaign. Use this when the campaign targets a `squadId`. Per-contact `squadOverrides` are deep-merged on top of this at dispatch time.", + "allOf": [ + { + "$ref": "#/components/schemas/AssistantOverrides" + } + ] + }, + "server": { + "description": "This is the server (URL, auth headers, timeout, etc.) for the campaign webhooks.", + "allOf": [ + { + "$ref": "#/components/schemas/Server" + } + ] + }, + "serverMessages": { + "type": "array", + "enum": [ + "campaign.started", + "campaign.cancelled", + "campaign.ended", + "campaign.archived", + "campaign.unarchived", + "contact.dispatched", + "contact.completed", + "contact.failed", + "contact.skipped", + "contact.predial-failed", + "campaign.job.continued" + ], + "example": [ + "campaign.started", + "contact.dispatched" + ], + "description": "These are the messages that will be sent to your Server URL.", + "items": { + "type": "string", + "enum": [ + "campaign.started", + "campaign.cancelled", + "campaign.ended", + "campaign.archived", + "campaign.unarchived", + "contact.dispatched", + "contact.completed", + "contact.failed", + "contact.skipped", + "contact.predial-failed", + "campaign.job.continued" + ] + } + }, + "predialPlan": { + "description": "This opts the campaign into the blocking `campaign.predial` eligibility webhook. When set, every contact triggers a `campaign.predial` POST to the Server URL before dialing, and the response `{ eligible: boolean }` decides whether the call is placed. Requires `server`. When unset, no pre-dial webhook is sent.", + "allOf": [ + { + "$ref": "#/components/schemas/CampaignPredialPlan" + } + ] + }, + "id": { + "type": "string", + "description": "This is the unique identifier for the campaign." + }, + "orgId": { + "type": "string", + "description": "This is the unique identifier for the org that this campaign belongs to." + }, + "createdAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the campaign was created." + }, + "updatedAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the campaign was last updated." + }, + "calls": { + "type": "object", + "description": "This is a map of call IDs to campaign call details." + }, + "callsCounterScheduled": { + "type": "number", + "description": "This is the number of calls that have been scheduled." + }, + "callsCounterQueued": { + "type": "number", + "description": "This is the number of calls that have been queued." + }, + "callsCounterInProgress": { + "type": "number", + "description": "This is the number of calls that have been in progress." + }, + "callsCounterEndedVoicemail": { + "type": "number", + "description": "This is the number of calls whose ended reason is 'voicemail'." + }, + "callsCounterEnded": { + "type": "number", + "description": "This is the number of calls that have ended." + } + }, + "required": [ + "status", + "name", + "id", + "orgId", + "createdAt", + "updatedAt", + "calls", + "callsCounterScheduled", + "callsCounterQueued", + "callsCounterInProgress", + "callsCounterEndedVoicemail", + "callsCounterEnded" + ] + }, + "CampaignPaginatedResponse": { + "type": "object", + "properties": { + "results": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Campaign" + } + }, + "metadata": { + "$ref": "#/components/schemas/PaginationMeta" + } + }, + "required": [ + "results", + "metadata" + ] + }, + "CampaignContactCounters": { + "type": "object", + "properties": { + "pending": { + "type": "number" + }, + "dispatched": { + "type": "number" + }, + "completed": { + "type": "number" + }, + "failed": { + "type": "number" + }, + "skipped": { + "type": "number" + }, + "predialFailed": { + "type": "number" + } + }, + "required": [ + "pending", + "dispatched", + "completed", + "failed", + "skipped", + "predialFailed" + ] + }, + "CampaignCallMetrics": { + "type": "object", + "properties": { + "dialed": { + "type": "number", + "description": "This is the number of contacts a call was actually placed for. Contacts\nthat were skipped, rejected before dialing, or failed to dispatch are not\ncounted — no call existed, so there was nothing to answer." + }, + "connected": { + "type": "number", + "description": "This is the number of those calls a human picked up. Voicemail does not\ncount. Divide by `dialed` for the pick-up rate." + } + }, + "required": [ + "dialed", + "connected" + ] + }, + "CampaignSummary": { + "type": "object", + "properties": { + "status": { + "type": "string", + "description": "This is the status of the campaign.", + "enum": [ + "scheduled", + "in-progress", + "ended", + "cancelled", + "archived" + ] + }, + "endedReason": { + "type": "string", + "description": "This is the explanation for how the campaign ended.", + "enum": [ + "campaign.scheduled.ended-by-user", + "campaign.in-progress.ended-by-user", + "campaign.ended.success" + ] + }, + "name": { + "type": "string", + "description": "This is the name of the campaign. This is just for your own reference.", + "example": "Q2 Sales Campaign" + }, + "assistantId": { + "type": "string", + "description": "This is the assistant ID that will be used for the campaign calls. Note: Only one of assistantId, workflowId, or squadId can be used." + }, + "squadId": { + "type": "string", + "description": "This is the squad ID that will be used for the campaign calls. Note: Only one of assistantId, workflowId, or squadId can be used." + }, + "phoneNumberId": { + "type": "string", + "description": "This is the phone number ID that will be used for the campaign calls. Required if dialPlan is not provided. Note: phoneNumberId and dialPlan are mutually exclusive." + }, + "schedulePlan": { + "description": "This is the schedule plan for the campaign. Calls will start at startedAt and continue until your organization’s concurrency limit is reached. Any remaining calls will be retried for up to one hour as capacity becomes available. After that hour or after latestAt, whichever comes first, any calls that couldn’t be placed won’t be retried.", + "allOf": [ + { + "$ref": "#/components/schemas/SchedulePlan" + } + ] + }, + "maxConcurrency": { + "type": "number", + "minimum": 1, + "description": "This is the maximum number of concurrent calls that will be made for the campaign. Defaults to 10." + }, + "assistantOverrides": { + "description": "These are the overrides for the assistant's settings and template variables for the campaign. Use this when the campaign targets an `assistantId`.", + "allOf": [ + { + "$ref": "#/components/schemas/AssistantOverrides" + } + ] + }, + "squadOverrides": { + "description": "These are the overrides for the squad and template variables for the campaign. Use this when the campaign targets a `squadId`. Per-contact `squadOverrides` are deep-merged on top of this at dispatch time.", + "allOf": [ + { + "$ref": "#/components/schemas/AssistantOverrides" + } + ] + }, + "server": { + "description": "This is the server (URL, auth headers, timeout, etc.) for the campaign webhooks.", + "allOf": [ + { + "$ref": "#/components/schemas/Server" + } + ] + }, + "serverMessages": { + "type": "array", + "enum": [ + "campaign.started", + "campaign.cancelled", + "campaign.ended", + "campaign.archived", + "campaign.unarchived", + "contact.dispatched", + "contact.completed", + "contact.failed", + "contact.skipped", + "contact.predial-failed", + "campaign.job.continued" + ], + "example": [ + "campaign.started", + "contact.dispatched" + ], + "description": "These are the messages that will be sent to your Server URL.", + "items": { + "type": "string", + "enum": [ + "campaign.started", + "campaign.cancelled", + "campaign.ended", + "campaign.archived", + "campaign.unarchived", + "contact.dispatched", + "contact.completed", + "contact.failed", + "contact.skipped", + "contact.predial-failed", + "campaign.job.continued" + ] + } + }, + "predialPlan": { + "description": "This opts the campaign into the blocking `campaign.predial` eligibility webhook. When set, every contact triggers a `campaign.predial` POST to the Server URL before dialing, and the response `{ eligible: boolean }` decides whether the call is placed. Requires `server`. When unset, no pre-dial webhook is sent.", + "allOf": [ + { + "$ref": "#/components/schemas/CampaignPredialPlan" + } + ] + }, + "contactCounters": { + "description": "These are the per-status contact counts for this campaign. Sum them for the\ncampaign's total audience; `pending` plus `dispatched` is what is left to\ncomplete.", + "allOf": [ + { + "$ref": "#/components/schemas/CampaignContactCounters" + } + ] + }, + "callMetrics": { + "description": "These are the call-level outcomes for this campaign — how many contacts\nwere actually dialed, and how many of those a human picked up.", + "allOf": [ + { + "$ref": "#/components/schemas/CampaignCallMetrics" + } + ] + }, + "id": { + "type": "string", + "description": "This is the unique identifier for the campaign." + }, + "orgId": { + "type": "string", + "description": "This is the unique identifier for the org that this campaign belongs to." + }, + "createdAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the campaign was created." + }, + "updatedAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the campaign was last updated." + } + }, + "required": [ + "status", + "name", + "id", + "orgId", + "createdAt", + "updatedAt" + ] + }, + "CampaignSummaryPaginatedResponse": { + "type": "object", + "properties": { + "results": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CampaignSummary" + } + }, + "metadata": { + "$ref": "#/components/schemas/PaginationMeta" + } + }, + "required": [ + "results", + "metadata" + ] + }, + "UpdateCampaignDTO": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "This is the name of the campaign. This is just for your own reference." + }, + "assistantId": { + "type": "string", + "description": "This is the assistant ID that will be used for the campaign calls.\nCan only be updated if campaign is not in progress or has ended." + }, + "workflowId": { + "type": "string", + "description": "This is the workflow ID that will be used for the campaign calls.\nCan only be updated if campaign is not in progress or has ended." + }, + "squadId": { + "type": "string", + "description": "This is the squad ID that will be used for the campaign calls.\nCan only be updated if campaign is not in progress or has ended." + }, + "phoneNumberId": { + "type": "string", + "description": "This is the phone number ID that will be used for the campaign calls.\nCan only be updated if campaign is not in progress or has ended.\nNote: `phoneNumberId` and `dialPlan` are mutually exclusive." + }, + "dialPlan": { + "description": "This is a list of dial entries, each specifying a phone number and the customers to call using that number. Can only be updated if campaign is not in progress or has ended. Note: phoneNumberId and dialPlan are mutually exclusive.", + "type": "array", + "items": { + "$ref": "#/components/schemas/DialPlanEntry" + } + }, + "schedulePlan": { + "description": "This is the schedule plan for the campaign.\nCan only be updated if campaign is not in progress or has ended.", + "allOf": [ + { + "$ref": "#/components/schemas/SchedulePlan" + } + ] + }, + "status": { + "type": "string", + "description": "Set to 'cancelled' to stop the campaign ('ended' is a V1 alias). Scheduled\ncalls are deleted; in-progress calls are allowed to finish.", + "enum": [ + "ended", + "cancelled" + ] + } + } + }, + "CampaignContactWithOutcome": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "number": { + "type": "string" + }, + "name": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "contact.pending", + "contact.dispatched", + "contact.completed", + "contact.failed", + "contact.skipped", + "contact.predial-failed" + ] + }, + "callId": { + "type": "string" + }, + "dispatchedAt": { + "format": "date-time", + "type": "string" + }, + "endedReason": { + "type": "string" + } + }, + "required": [ + "id", + "number", + "status" + ] + }, + "CampaignContactPaginatedResponse": { + "type": "object", + "properties": { + "results": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CampaignContactWithOutcome" + } + }, + "metadata": { + "$ref": "#/components/schemas/PaginationMeta" + } + }, + "required": [ + "results", + "metadata" + ] + }, + "RelayTargetAssistant": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "assistant" + ], + "description": "The type of relay target" + }, + "assistantId": { + "type": "string", + "description": "The unique identifier of the assistant" + }, + "assistantName": { + "type": "string", + "description": "The name of the assistant" + } + }, + "required": [ + "type" + ] + }, + "RelayTargetSquad": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "squad" + ], + "description": "The type of relay target" + }, + "squadId": { + "type": "string", + "description": "The unique identifier of the squad" + }, + "squadName": { + "type": "string", + "description": "The name of the squad" + } + }, + "required": [ + "type" + ] + }, + "RelayTargetOptions": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "assistant", + "squad" + ] + } + }, + "required": [ + "type" + ] + }, + "RelayCommandSay": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "say" + ], + "description": "The type of relay command" + }, + "content": { + "type": "string", + "description": "The content for the assistant to speak" + } + }, + "required": [ + "type", + "content" + ] + }, + "RelayCommandNote": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "message.add" + ], + "description": "The type of relay command" + }, + "content": { + "type": "string", + "description": "The note content to add to the conversation" + } + }, + "required": [ + "type", + "content" + ] + }, + "RelayCommandOptions": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "say", + "message.add" + ] + } + }, + "required": [ + "type" + ] + }, + "RelayRequest": { + "type": "object", + "properties": { + "source": { + "type": "string", + "description": "The source identifier of the relay request" + }, + "target": { + "oneOf": [ + { + "$ref": "#/components/schemas/RelayTargetAssistant" + }, + { + "$ref": "#/components/schemas/RelayTargetSquad" + } + ], + "description": "The target assistant or squad to relay the commands to" + }, + "customerId": { + "type": "string", + "description": "The unique identifier of the customer" + }, + "commands": { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/RelayCommandSay" + }, + { + "$ref": "#/components/schemas/RelayCommandNote" + } + ] + }, + "description": "The list of commands to relay to the target" + } + }, + "required": [ + "source", + "target", + "customerId", + "commands" + ] + }, + "RelayResponse": { + "type": "object", + "properties": { + "status": { + "type": "string", + "enum": [ + "deliveredLive", + "deliveredHeadless", + "failed" + ], + "description": "The status of the relay request" + }, + "callId": { + "type": "string", + "description": "The unique identifier of the call, if delivered to a live call" + }, + "sessionId": { + "type": "string", + "description": "The unique identifier of the session, if delivered to a headless session" + }, + "chatId": { + "type": "string" + } + }, + "required": [ + "status" + ] + }, + "Session": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "This is the unique identifier for the session." + }, + "orgId": { + "type": "string", + "description": "This is the unique identifier for the organization that owns this session." + }, + "createdAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 timestamp indicating when the session was created." + }, + "updatedAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 timestamp indicating when the session was last updated." + }, + "cost": { + "type": "number", + "description": "This is the cost of the session in USD." + }, + "costs": { + "type": "array", + "description": "These are the costs of individual components of the session in USD.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/ModelCost", + "title": "ModelCost" + }, + { + "$ref": "#/components/schemas/AnalysisCost", + "title": "AnalysisCost" + }, + { + "$ref": "#/components/schemas/SessionCost", + "title": "SessionCost" + } + ] + } + }, + "name": { + "type": "string", + "description": "This is a user-defined name for the session. Maximum length is 40 characters.", + "maxLength": 40 + }, + "status": { + "type": "string", + "description": "This is the current status of the session. Can be either 'active' or 'completed'.", + "enum": [ + "active", + "completed" + ] + }, + "expirationSeconds": { + "type": "number", + "description": "Session expiration time in seconds. Defaults to 24 hours (86400 seconds) if not set.", + "minimum": 60, + "maximum": 2592000, + "example": 86400 + }, + "assistantId": { + "type": "string", + "description": "This is the ID of the assistant associated with this session. Use this when referencing an existing assistant." + }, + "assistant": { + "description": "This is the assistant configuration for this session. Use this when creating a new assistant configuration.\nIf assistantId is provided, this will be ignored.", + "allOf": [ + { + "$ref": "#/components/schemas/CreateAssistantDTO" + } + ] + }, + "assistantOverrides": { + "description": "These are the overrides for the assistant configuration.\nUse this to provide variable values and other overrides when using assistantId.\nVariable substitution will be applied to the assistant's messages and other text-based fields.", + "allOf": [ + { + "$ref": "#/components/schemas/AssistantOverrides" + } + ] + }, + "squadId": { + "type": "string", + "description": "This is the squad ID associated with this session. Use this when referencing an existing squad." + }, + "squad": { + "description": "This is the squad configuration for this session. Use this when creating a new squad configuration.\nIf squadId is provided, this will be ignored.", + "allOf": [ + { + "$ref": "#/components/schemas/CreateSquadDTO" + } + ] + }, + "messages": { + "type": "array", + "description": "This is an array of chat messages in the session.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/SystemMessage", + "title": "SystemMessage" + }, + { + "$ref": "#/components/schemas/UserMessage", + "title": "UserMessage" + }, + { + "$ref": "#/components/schemas/AssistantMessage", + "title": "AssistantMessage" + }, + { + "$ref": "#/components/schemas/ToolMessage", + "title": "ToolMessage" + }, + { + "$ref": "#/components/schemas/DeveloperMessage", + "title": "DeveloperMessage" + } + ] + } + }, + "customer": { + "description": "This is the customer information associated with this session.", + "allOf": [ + { + "$ref": "#/components/schemas/CreateCustomerDTO" + } + ] + }, + "customerId": { + "type": "string", + "description": "This is the customerId of the customer associated with this session." + }, + "phoneNumberId": { + "type": "string", + "description": "This is the ID of the phone number associated with this session." + }, + "phoneNumber": { + "description": "This is the phone number configuration for this session.", + "allOf": [ + { + "$ref": "#/components/schemas/ImportTwilioPhoneNumberDTO" + } + ] + }, + "artifact": { + "description": "These are the artifacts that were extracted from the session messages.\nThey are only available after the session has completed.\nThe artifact plan from the assistant or active assistant of squad is used to generate the artifact.\nCurrently the only supported fields of assistant artifact plan are:\n- structuredOutputIds", + "allOf": [ + { + "$ref": "#/components/schemas/Artifact" + } + ] + } + }, + "required": [ + "id", + "orgId", + "createdAt", + "updatedAt" + ] + }, + "CreateSessionDTO": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "This is a user-defined name for the session. Maximum length is 40 characters.", + "maxLength": 40 + }, + "status": { + "type": "string", + "description": "This is the current status of the session. Can be either 'active' or 'completed'.", + "enum": [ + "active", + "completed" + ] + }, + "expirationSeconds": { + "type": "number", + "description": "Session expiration time in seconds. Defaults to 24 hours (86400 seconds) if not set.", + "minimum": 60, + "maximum": 2592000, + "example": 86400 + }, + "assistantId": { + "type": "string", + "description": "This is the ID of the assistant associated with this session. Use this when referencing an existing assistant." + }, + "assistant": { + "description": "This is the assistant configuration for this session. Use this when creating a new assistant configuration.\nIf assistantId is provided, this will be ignored.", + "allOf": [ + { + "$ref": "#/components/schemas/CreateAssistantDTO" + } + ] + }, + "assistantOverrides": { + "description": "These are the overrides for the assistant configuration.\nUse this to provide variable values and other overrides when using assistantId.\nVariable substitution will be applied to the assistant's messages and other text-based fields.", + "allOf": [ + { + "$ref": "#/components/schemas/AssistantOverrides" + } + ] + }, + "squadId": { + "type": "string", + "description": "This is the squad ID associated with this session. Use this when referencing an existing squad." + }, + "squad": { + "description": "This is the squad configuration for this session. Use this when creating a new squad configuration.\nIf squadId is provided, this will be ignored.", + "allOf": [ + { + "$ref": "#/components/schemas/CreateSquadDTO" + } + ] + }, + "messages": { + "type": "array", + "description": "This is an array of chat messages in the session.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/SystemMessage", + "title": "SystemMessage" + }, + { + "$ref": "#/components/schemas/UserMessage", + "title": "UserMessage" + }, + { + "$ref": "#/components/schemas/AssistantMessage", + "title": "AssistantMessage" + }, + { + "$ref": "#/components/schemas/ToolMessage", + "title": "ToolMessage" + }, + { + "$ref": "#/components/schemas/DeveloperMessage", + "title": "DeveloperMessage" + } + ] + } + }, + "customer": { + "description": "This is the customer information associated with this session.", + "allOf": [ + { + "$ref": "#/components/schemas/CreateCustomerDTO" + } + ] + }, + "customerId": { + "type": "string", + "description": "This is the customerId of the customer associated with this session." + }, + "phoneNumberId": { + "type": "string", + "description": "This is the ID of the phone number associated with this session." + }, + "phoneNumber": { + "description": "This is the phone number configuration for this session.", + "allOf": [ + { + "$ref": "#/components/schemas/ImportTwilioPhoneNumberDTO" + } + ] + } + } + }, + "UpdateSessionDTO": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "This is the new name for the session. Maximum length is 40 characters.", + "maxLength": 40 + }, + "status": { + "type": "string", + "description": "This is the new status for the session.", + "enum": [ + "active", + "completed" + ] + }, + "expirationSeconds": { + "type": "number", + "description": "Session expiration time in seconds. Defaults to 24 hours (86400 seconds) if not set.", + "minimum": 60, + "maximum": 2592000, + "example": 86400 + }, + "messages": { + "type": "array", + "description": "This is the updated array of chat messages.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/SystemMessage", + "title": "SystemMessage" + }, + { + "$ref": "#/components/schemas/UserMessage", + "title": "UserMessage" + }, + { + "$ref": "#/components/schemas/AssistantMessage", + "title": "AssistantMessage" + }, + { + "$ref": "#/components/schemas/ToolMessage", + "title": "ToolMessage" + }, + { + "$ref": "#/components/schemas/DeveloperMessage", + "title": "DeveloperMessage" + } + ] + } + } + } + }, + "GetSessionPaginatedDTO": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "This is the unique identifier for the session to filter by." + }, + "name": { + "type": "string", + "description": "This is the name of the session to filter by." + }, + "assistantId": { + "type": "string", + "description": "This is the ID of the assistant to filter sessions by." + }, + "assistantIdAny": { + "type": "string", + "description": "Filter by multiple assistant IDs. Provide as comma-separated values.", + "example": "assistant-1,assistant-2,assistant-3" + }, + "squadId": { + "type": "string", + "description": "This is the ID of the squad to filter sessions by." + }, + "workflowId": { + "type": "string", + "description": "This is the ID of the workflow to filter sessions by." + }, + "customer": { + "description": "This is the customer information to filter by.", + "allOf": [ + { + "$ref": "#/components/schemas/CreateCustomerDTO" + } + ] + }, + "customerNumberAny": { + "type": "string", + "description": "Filter by any of the specified customer phone numbers (comma-separated).", + "example": "+1234567890,+0987654321" + }, + "idAny": { + "type": "string", + "description": "Filter by multiple session IDs. Provide as comma-separated values." + }, + "phoneNumberId": { + "type": "string", + "description": "This will return sessions with the specified phoneNumberId." + }, + "phoneNumberIdAny": { + "description": "This will return sessions with any of the specified phoneNumberIds.", + "type": "array", + "items": { + "type": "string" + } + }, + "page": { + "type": "number", + "description": "This is the page number to return. Defaults to 1.", + "minimum": 1 + }, + "sortOrder": { + "type": "string", + "description": "This is the sort order for pagination. Defaults to 'DESC'.", + "enum": [ + "ASC", + "DESC" + ] + }, + "sortBy": { + "type": "string", + "description": "This is the column to sort by. Defaults to 'createdAt'.", + "enum": [ + "createdAt", + "duration", + "cost" + ] + }, + "limit": { + "type": "number", + "description": "This is the maximum number of items to return. Defaults to 100.", + "minimum": 0, + "maximum": 1000 + }, + "createdAtGt": { + "format": "date-time", + "type": "string", + "description": "This will return items where the createdAt is greater than the specified value." + }, + "createdAtLt": { + "format": "date-time", + "type": "string", + "description": "This will return items where the createdAt is less than the specified value." + }, + "createdAtGe": { + "format": "date-time", + "type": "string", + "description": "This will return items where the createdAt is greater than or equal to the specified value." + }, + "createdAtLe": { + "format": "date-time", + "type": "string", + "description": "This will return items where the createdAt is less than or equal to the specified value." + }, + "updatedAtGt": { + "format": "date-time", + "type": "string", + "description": "This will return items where the updatedAt is greater than the specified value." + }, + "updatedAtLt": { + "format": "date-time", + "type": "string", + "description": "This will return items where the updatedAt is less than the specified value." + }, + "updatedAtGe": { + "format": "date-time", + "type": "string", + "description": "This will return items where the updatedAt is greater than or equal to the specified value." + }, + "updatedAtLe": { + "format": "date-time", + "type": "string", + "description": "This will return items where the updatedAt is less than or equal to the specified value." + } + } + }, + "SessionPaginatedResponse": { + "type": "object", + "properties": { + "results": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Session" + } + }, + "metadata": { + "$ref": "#/components/schemas/PaginationMeta" + } + }, + "required": [ + "results", + "metadata" + ] + }, + "ExportSessionDTO": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "This is the unique identifier for the session to filter by." + }, + "name": { + "type": "string", + "description": "This is the name of the session to filter by." + }, + "assistantId": { + "type": "string", + "description": "This is the ID of the assistant to filter sessions by." + }, + "assistantIdAny": { + "type": "string", + "description": "Filter by multiple assistant IDs. Provide as comma-separated values.", + "example": "assistant-1,assistant-2,assistant-3" + }, + "squadId": { + "type": "string", + "description": "This is the ID of the squad to filter sessions by." + }, + "workflowId": { + "type": "string", + "description": "This is the ID of the workflow to filter sessions by." + }, + "customer": { + "description": "This is the customer information to filter by.", + "allOf": [ + { + "$ref": "#/components/schemas/CreateCustomerDTO" + } + ] + }, + "customerNumberAny": { + "type": "string", + "description": "Filter by any of the specified customer phone numbers (comma-separated).", + "example": "+1234567890,+0987654321" + }, + "idAny": { + "type": "string", + "description": "Filter by multiple session IDs. Provide as comma-separated values." + }, + "columns": { + "type": "string", + "description": "Columns to include in the CSV export", + "enum": [ + "id", + "name", + "status", + "assistantId", + "squadId", + "customerName", + "customerNumber", + "phoneNumberId", + "cost", + "messages", + "createdAt", + "updatedAt" + ], + "default": [ + "id", + "name", + "status", + "assistantId", + "squadId", + "customerName", + "customerNumber", + "phoneNumberId", + "cost", + "messages", + "createdAt", + "updatedAt" + ] + }, + "email": { + "type": "string", + "description": "This is the email address to send the export to.\nRequired if userId is not available in the request context." + }, + "format": { + "type": "string", + "description": "This is the format of the export.\n\n@default csv", + "enum": [ + "csv", + "json" + ], + "default": "csv" + }, + "phoneNumberId": { + "type": "string", + "description": "This will return sessions with the specified phoneNumberId." + }, + "phoneNumberIdAny": { + "description": "This will return sessions with any of the specified phoneNumberIds.", + "type": "array", + "items": { + "type": "string" + } + }, + "page": { + "type": "number", + "description": "This is the page number to return. Defaults to 1.", + "minimum": 1 + }, + "sortOrder": { + "type": "string", + "description": "This is the sort order for pagination. Defaults to 'DESC'.", + "enum": [ + "ASC", + "DESC" + ] + }, + "sortBy": { + "type": "string", + "description": "This is the column to sort by. Defaults to 'createdAt'.", + "enum": [ + "createdAt", + "duration", + "cost" + ] + }, + "limit": { + "type": "number", + "description": "This is the maximum number of items to return. Defaults to 100.", + "minimum": 0, + "maximum": 1000 + }, + "createdAtGt": { + "format": "date-time", + "type": "string", + "description": "This will return items where the createdAt is greater than the specified value." + }, + "createdAtLt": { + "format": "date-time", + "type": "string", + "description": "This will return items where the createdAt is less than the specified value." + }, + "createdAtGe": { + "format": "date-time", + "type": "string", + "description": "This will return items where the createdAt is greater than or equal to the specified value." + }, + "createdAtLe": { + "format": "date-time", + "type": "string", + "description": "This will return items where the createdAt is less than or equal to the specified value." + }, + "updatedAtGt": { + "format": "date-time", + "type": "string", + "description": "This will return items where the updatedAt is greater than the specified value." + }, + "updatedAtLt": { + "format": "date-time", + "type": "string", + "description": "This will return items where the updatedAt is less than the specified value." + }, + "updatedAtGe": { + "format": "date-time", + "type": "string", + "description": "This will return items where the updatedAt is greater than or equal to the specified value." + }, + "updatedAtLe": { + "format": "date-time", + "type": "string", + "description": "This will return items where the updatedAt is less than or equal to the specified value." + } + } + }, + "ByoPhoneNumber": { + "type": "object", + "properties": { + "fallbackDestination": { + "description": "This is the fallback destination an inbound call will be transferred to if:\n1. `assistantId` is not set\n2. `squadId` is not set\n3. and, `assistant-request` message to the `serverUrl` fails\n\nIf this is not set and above conditions are met, the inbound call is hung up with an error message.", + "oneOf": [ + { + "$ref": "#/components/schemas/TransferDestinationNumber", + "title": "NumberTransferDestination" + }, + { + "$ref": "#/components/schemas/TransferDestinationSip", + "title": "SipTransferDestination" + } + ] + }, + "hooks": { + "type": "array", + "description": "This is the hooks that will be used for incoming calls to this phone number.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/PhoneNumberHookCallRinging", + "title": "PhoneNumberHookCallRinging" + }, + { + "$ref": "#/components/schemas/PhoneNumberHookCallEnding", + "title": "PhoneNumberHookCallEnding" + } + ] + } + }, + "provider": { + "type": "string", + "description": "This is to bring your own phone numbers from your own SIP trunks or Carriers.", + "enum": [ + "byo-phone-number" + ] + }, + "numberE164CheckEnabled": { + "type": "boolean", + "description": "This is the flag to toggle the E164 check for the `number` field. This is an advanced property which should be used if you know your use case requires it.\n\nUse cases:\n- `false`: To allow non-E164 numbers like `+001234567890`, `1234`, or `abc`. This is useful for dialing out to non-E164 numbers on your SIP trunks.\n- `true` (default): To allow only E164 numbers like `+14155551234`. This is standard for PSTN calls.\n\nIf `false`, the `number` is still required to only contain alphanumeric characters (regex: `/^\\+?[a-zA-Z0-9]+$/`).\n\n@default true (E164 check is enabled)", + "default": true + }, + "id": { + "type": "string", + "description": "This is the unique identifier for the phone number." + }, + "orgId": { + "type": "string", + "description": "This is the unique identifier for the org that this phone number belongs to." + }, + "createdAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the phone number was created." + }, + "updatedAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the phone number was last updated." + }, + "status": { + "type": "string", + "description": "This is the status of the phone number.", + "enum": [ + "active", + "activating", + "blocked" + ] + }, + "name": { + "type": "string", + "description": "This is the name of the phone number. This is just for your own reference.", + "maxLength": 40 + }, + "assistantId": { + "type": "string", + "description": "This is the assistant that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId` nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + }, + "workflowId": { + "type": "string", + "description": "This is the workflow that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + }, + "squadId": { + "type": "string", + "description": "This is the squad that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + }, + "server": { + "description": "This is where Vapi will send webhooks. You can find all webhooks available along with their shape in ServerMessage schema.\n\nThe order of precedence is:\n\n1. assistant.server\n2. phoneNumber.server\n3. org.server", + "allOf": [ + { + "$ref": "#/components/schemas/Server" + } + ] + }, + "number": { + "type": "string", + "description": "This is the number of the customer.", + "minLength": 3, + "maxLength": 40 + }, + "credentialId": { + "type": "string", + "description": "This is the credential of your own SIP trunk or Carrier (type `byo-sip-trunk`) which can be used to make calls to this phone number.\n\nYou can add the SIP trunk or Carrier credential in the Provider Credentials page on the Dashboard to get the credentialId." + } + }, + "required": [ + "provider", + "id", + "orgId", + "createdAt", + "updatedAt", + "credentialId" + ] + }, + "TwilioPhoneNumber": { + "type": "object", + "properties": { + "fallbackDestination": { + "description": "This is the fallback destination an inbound call will be transferred to if:\n1. `assistantId` is not set\n2. `squadId` is not set\n3. and, `assistant-request` message to the `serverUrl` fails\n\nIf this is not set and above conditions are met, the inbound call is hung up with an error message.", + "oneOf": [ + { + "$ref": "#/components/schemas/TransferDestinationNumber", + "title": "NumberTransferDestination" + }, + { + "$ref": "#/components/schemas/TransferDestinationSip", + "title": "SipTransferDestination" + } + ] + }, + "hooks": { + "type": "array", + "description": "This is the hooks that will be used for incoming calls to this phone number.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/PhoneNumberHookCallRinging", + "title": "PhoneNumberHookCallRinging" + }, + { + "$ref": "#/components/schemas/PhoneNumberHookCallEnding", + "title": "PhoneNumberHookCallEnding" + } + ] + } + }, + "provider": { + "type": "string", + "description": "This is to use numbers bought on Twilio.", + "enum": [ + "twilio" + ] + }, + "smsEnabled": { + "type": "boolean", + "description": "Controls whether Vapi sets the messaging webhook URL on the Twilio number during import.\n\nIf set to `false`, Vapi will not update the Twilio messaging URL, leaving it as is.\nIf `true` or omitted (default), Vapi will configure both the voice and messaging URLs.\n\n@default true", + "default": true + }, + "id": { + "type": "string", + "description": "This is the unique identifier for the phone number." + }, + "orgId": { + "type": "string", + "description": "This is the unique identifier for the org that this phone number belongs to." + }, + "createdAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the phone number was created." + }, + "updatedAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the phone number was last updated." + }, + "status": { + "type": "string", + "description": "This is the status of the phone number.", + "enum": [ + "active", + "activating", + "blocked" + ] + }, + "twilioAuthToken": { + "type": "string", + "description": "This is the Twilio Auth Token for the phone number." + }, + "twilioApiKey": { + "type": "string", + "description": "This is the Twilio API Key for the phone number." + }, + "twilioApiSecret": { + "type": "string", + "description": "This is the Twilio API Secret for the phone number." + }, + "name": { + "type": "string", + "description": "This is the name of the phone number. This is just for your own reference.", + "maxLength": 40 + }, + "assistantId": { + "type": "string", + "description": "This is the assistant that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId` nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + }, + "workflowId": { + "type": "string", + "description": "This is the workflow that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + }, + "squadId": { + "type": "string", + "description": "This is the squad that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + }, + "server": { + "description": "This is where Vapi will send webhooks. You can find all webhooks available along with their shape in ServerMessage schema.\n\nThe order of precedence is:\n\n1. assistant.server\n2. phoneNumber.server\n3. org.server", + "allOf": [ + { + "$ref": "#/components/schemas/Server" + } + ] + }, + "number": { + "type": "string", + "description": "These are the digits of the phone number you own on your Twilio." + }, + "twilioAccountSid": { + "type": "string", + "description": "This is the Twilio Account SID for the phone number." + } + }, + "required": [ + "provider", + "id", + "orgId", + "createdAt", + "updatedAt", + "number", + "twilioAccountSid" + ] + }, + "VonagePhoneNumber": { + "type": "object", + "properties": { + "fallbackDestination": { + "description": "This is the fallback destination an inbound call will be transferred to if:\n1. `assistantId` is not set\n2. `squadId` is not set\n3. and, `assistant-request` message to the `serverUrl` fails\n\nIf this is not set and above conditions are met, the inbound call is hung up with an error message.", + "oneOf": [ + { + "$ref": "#/components/schemas/TransferDestinationNumber", + "title": "NumberTransferDestination" + }, + { + "$ref": "#/components/schemas/TransferDestinationSip", + "title": "SipTransferDestination" + } + ] + }, + "hooks": { + "type": "array", + "description": "This is the hooks that will be used for incoming calls to this phone number.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/PhoneNumberHookCallRinging", + "title": "PhoneNumberHookCallRinging" + }, + { + "$ref": "#/components/schemas/PhoneNumberHookCallEnding", + "title": "PhoneNumberHookCallEnding" + } + ] + } + }, + "provider": { + "type": "string", + "description": "This is to use numbers bought on Vonage.", + "enum": [ + "vonage" + ] + }, + "id": { + "type": "string", + "description": "This is the unique identifier for the phone number." + }, + "orgId": { + "type": "string", + "description": "This is the unique identifier for the org that this phone number belongs to." + }, + "createdAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the phone number was created." + }, + "updatedAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the phone number was last updated." + }, + "status": { + "type": "string", + "description": "This is the status of the phone number.", + "enum": [ + "active", + "activating", + "blocked" + ] + }, + "name": { + "type": "string", + "description": "This is the name of the phone number. This is just for your own reference.", + "maxLength": 40 + }, + "assistantId": { + "type": "string", + "description": "This is the assistant that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId` nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + }, + "workflowId": { + "type": "string", + "description": "This is the workflow that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + }, + "squadId": { + "type": "string", + "description": "This is the squad that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + }, + "server": { + "description": "This is where Vapi will send webhooks. You can find all webhooks available along with their shape in ServerMessage schema.\n\nThe order of precedence is:\n\n1. assistant.server\n2. phoneNumber.server\n3. org.server", + "allOf": [ + { + "$ref": "#/components/schemas/Server" + } + ] + }, + "number": { + "type": "string", + "description": "These are the digits of the phone number you own on your Vonage." + }, + "credentialId": { + "type": "string", + "description": "This is the credential you added in dashboard.vapi.ai/keys. This is used to configure the number to send inbound calls to Vapi, make outbound calls and do live call updates like transfers and hangups." + } + }, + "required": [ + "provider", + "id", + "orgId", + "createdAt", + "updatedAt", + "number", + "credentialId" + ] + }, + "SipAuthentication": { + "type": "object", + "properties": { + "realm": { + "type": "string", + "description": "This will be expected in the `realm` field of the `authorization` header of the SIP INVITE. Defaults to the SIP realm of the Vapi region serving the request (e.g. `sip.vapi.ai` for US, `sip.eu.vapi.ai` for EU)." + }, + "username": { + "type": "string", + "description": "This will be expected in the `username` field of the `authorization` header of the SIP INVITE.", + "minLength": 20, + "maxLength": 40 + }, + "password": { + "type": "string", + "description": "This will be expected to generate the `response` field of the `authorization` header of the SIP INVITE, through digest authentication.", + "minLength": 20, + "maxLength": 40 + } + }, + "required": [ + "username", + "password" + ] + }, + "VapiPhoneNumber": { + "type": "object", + "properties": { + "fallbackDestination": { + "description": "This is the fallback destination an inbound call will be transferred to if:\n1. `assistantId` is not set\n2. `squadId` is not set\n3. and, `assistant-request` message to the `serverUrl` fails\n\nIf this is not set and above conditions are met, the inbound call is hung up with an error message.", + "oneOf": [ + { + "$ref": "#/components/schemas/TransferDestinationNumber", + "title": "NumberTransferDestination" + }, + { + "$ref": "#/components/schemas/TransferDestinationSip", + "title": "SipTransferDestination" + } + ] + }, + "hooks": { + "type": "array", + "description": "This is the hooks that will be used for incoming calls to this phone number.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/PhoneNumberHookCallRinging", + "title": "PhoneNumberHookCallRinging" + }, + { + "$ref": "#/components/schemas/PhoneNumberHookCallEnding", + "title": "PhoneNumberHookCallEnding" + } + ] + } + }, + "provider": { + "type": "string", + "description": "This is to create free SIP phone numbers on Vapi.", + "enum": [ + "vapi" + ] + }, + "id": { + "type": "string", + "description": "This is the unique identifier for the phone number." + }, + "orgId": { + "type": "string", + "description": "This is the unique identifier for the org that this phone number belongs to." + }, + "createdAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the phone number was created." + }, + "updatedAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the phone number was last updated." + }, + "status": { + "type": "string", + "description": "This is the status of the phone number.", + "enum": [ + "active", + "activating", + "blocked" + ] + }, + "number": { + "type": "string", + "description": "These are the digits of the phone number you purchased from Vapi." + }, + "name": { + "type": "string", + "description": "This is the name of the phone number. This is just for your own reference.", + "maxLength": 40 + }, + "assistantId": { + "type": "string", + "description": "This is the assistant that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId` nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + }, + "workflowId": { + "type": "string", + "description": "This is the workflow that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + }, + "squadId": { + "type": "string", + "description": "This is the squad that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + }, + "server": { + "description": "This is where Vapi will send webhooks. You can find all webhooks available along with their shape in ServerMessage schema.\n\nThe order of precedence is:\n\n1. assistant.server\n2. phoneNumber.server\n3. org.server", + "allOf": [ + { + "$ref": "#/components/schemas/Server" + } + ] + }, + "numberDesiredAreaCode": { + "type": "string", + "description": "This is the area code of the phone number to purchase.", + "minLength": 3, + "maxLength": 3 + }, + "sipUri": { + "type": "string", + "description": "This is the SIP URI of the phone number. You can SIP INVITE this. The assistant attached to this number will answer.\n\nThis is case-insensitive." + }, + "authentication": { + "description": "This enables authentication for incoming SIP INVITE requests to the `sipUri`.\n\nIf not set, any username/password to the 401 challenge of the SIP INVITE will be accepted.", + "allOf": [ + { + "$ref": "#/components/schemas/SipAuthentication" + } + ] + } + }, + "required": [ + "provider", + "id", + "orgId", + "createdAt", + "updatedAt" + ] + }, + "TelnyxPhoneNumber": { + "type": "object", + "properties": { + "fallbackDestination": { + "description": "This is the fallback destination an inbound call will be transferred to if:\n1. `assistantId` is not set\n2. `squadId` is not set\n3. and, `assistant-request` message to the `serverUrl` fails\n\nIf this is not set and above conditions are met, the inbound call is hung up with an error message.", + "oneOf": [ + { + "$ref": "#/components/schemas/TransferDestinationNumber", + "title": "NumberTransferDestination" + }, + { + "$ref": "#/components/schemas/TransferDestinationSip", + "title": "SipTransferDestination" + } + ] + }, + "hooks": { + "type": "array", + "description": "This is the hooks that will be used for incoming calls to this phone number.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/PhoneNumberHookCallRinging", + "title": "PhoneNumberHookCallRinging" + }, + { + "$ref": "#/components/schemas/PhoneNumberHookCallEnding", + "title": "PhoneNumberHookCallEnding" + } + ] + } + }, + "provider": { + "type": "string", + "description": "This is to use numbers bought on Telnyx.", + "enum": [ + "telnyx" + ] + }, + "id": { + "type": "string", + "description": "This is the unique identifier for the phone number." + }, + "orgId": { + "type": "string", + "description": "This is the unique identifier for the org that this phone number belongs to." + }, + "createdAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the phone number was created." + }, + "updatedAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the phone number was last updated." + }, + "status": { + "type": "string", + "description": "This is the status of the phone number.", + "enum": [ + "active", + "activating", + "blocked" + ] + }, + "name": { + "type": "string", + "description": "This is the name of the phone number. This is just for your own reference.", + "maxLength": 40 + }, + "assistantId": { + "type": "string", + "description": "This is the assistant that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId` nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + }, + "workflowId": { + "type": "string", + "description": "This is the workflow that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + }, + "squadId": { + "type": "string", + "description": "This is the squad that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + }, + "server": { + "description": "This is where Vapi will send webhooks. You can find all webhooks available along with their shape in ServerMessage schema.\n\nThe order of precedence is:\n\n1. assistant.server\n2. phoneNumber.server\n3. org.server", + "allOf": [ + { + "$ref": "#/components/schemas/Server" + } + ] + }, + "number": { + "type": "string", + "description": "These are the digits of the phone number you own on your Telnyx." + }, + "credentialId": { + "type": "string", + "description": "This is the credential you added in dashboard.vapi.ai/keys. This is used to configure the number to send inbound calls to Vapi, make outbound calls and do live call updates like transfers and hangups." + } + }, + "required": [ + "provider", + "id", + "orgId", + "createdAt", + "updatedAt", + "number", + "credentialId" + ] + }, + "CreateByoPhoneNumberDTO": { + "type": "object", + "properties": { + "fallbackDestination": { + "description": "This is the fallback destination an inbound call will be transferred to if:\n1. `assistantId` is not set\n2. `squadId` is not set\n3. and, `assistant-request` message to the `serverUrl` fails\n\nIf this is not set and above conditions are met, the inbound call is hung up with an error message.", + "oneOf": [ + { + "$ref": "#/components/schemas/TransferDestinationNumber", + "title": "NumberTransferDestination" + }, + { + "$ref": "#/components/schemas/TransferDestinationSip", + "title": "SipTransferDestination" + } + ] + }, + "hooks": { + "type": "array", + "description": "This is the hooks that will be used for incoming calls to this phone number.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/PhoneNumberHookCallRinging", + "title": "PhoneNumberHookCallRinging" + }, + { + "$ref": "#/components/schemas/PhoneNumberHookCallEnding", + "title": "PhoneNumberHookCallEnding" + } + ] + } + }, + "provider": { + "type": "string", + "description": "This is to bring your own phone numbers from your own SIP trunks or Carriers.", + "enum": [ + "byo-phone-number" + ] + }, + "numberE164CheckEnabled": { + "type": "boolean", + "description": "This is the flag to toggle the E164 check for the `number` field. This is an advanced property which should be used if you know your use case requires it.\n\nUse cases:\n- `false`: To allow non-E164 numbers like `+001234567890`, `1234`, or `abc`. This is useful for dialing out to non-E164 numbers on your SIP trunks.\n- `true` (default): To allow only E164 numbers like `+14155551234`. This is standard for PSTN calls.\n\nIf `false`, the `number` is still required to only contain alphanumeric characters (regex: `/^\\+?[a-zA-Z0-9]+$/`).\n\n@default true (E164 check is enabled)", + "default": true + }, + "number": { + "type": "string", + "description": "This is the number of the customer.", + "minLength": 3, + "maxLength": 40 + }, + "credentialId": { + "type": "string", + "description": "This is the credential of your own SIP trunk or Carrier (type `byo-sip-trunk`) which can be used to make calls to this phone number.\n\nYou can add the SIP trunk or Carrier credential in the Provider Credentials page on the Dashboard to get the credentialId." + }, + "name": { + "type": "string", + "description": "This is the name of the phone number. This is just for your own reference.", + "maxLength": 40 + }, + "assistantId": { + "type": "string", + "description": "This is the assistant that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId` nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + }, + "workflowId": { + "type": "string", + "description": "This is the workflow that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + }, + "squadId": { + "type": "string", + "description": "This is the squad that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + }, + "server": { + "description": "This is where Vapi will send webhooks. You can find all webhooks available along with their shape in ServerMessage schema.\n\nThe order of precedence is:\n\n1. assistant.server\n2. phoneNumber.server\n3. org.server", + "allOf": [ + { + "$ref": "#/components/schemas/Server" + } + ] + } + }, + "required": [ + "provider", + "credentialId" + ] + }, + "CreateTwilioPhoneNumberDTO": { + "type": "object", + "properties": { + "fallbackDestination": { + "description": "This is the fallback destination an inbound call will be transferred to if:\n1. `assistantId` is not set\n2. `squadId` is not set\n3. and, `assistant-request` message to the `serverUrl` fails\n\nIf this is not set and above conditions are met, the inbound call is hung up with an error message.", + "oneOf": [ + { + "$ref": "#/components/schemas/TransferDestinationNumber", + "title": "NumberTransferDestination" + }, + { + "$ref": "#/components/schemas/TransferDestinationSip", + "title": "SipTransferDestination" + } + ] + }, + "hooks": { + "type": "array", + "description": "This is the hooks that will be used for incoming calls to this phone number.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/PhoneNumberHookCallRinging", + "title": "PhoneNumberHookCallRinging" + }, + { + "$ref": "#/components/schemas/PhoneNumberHookCallEnding", + "title": "PhoneNumberHookCallEnding" + } + ] + } + }, + "provider": { + "type": "string", + "description": "This is to use numbers bought on Twilio.", + "enum": [ + "twilio" ] }, - "destination": { - "description": "This is the destination where the call ended up being transferred to. If the call was not transferred, this will be empty.", + "smsEnabled": { + "type": "boolean", + "description": "Controls whether Vapi sets the messaging webhook URL on the Twilio number during import.\n\nIf set to `false`, Vapi will not update the Twilio messaging URL, leaving it as is.\nIf `true` or omitted (default), Vapi will configure both the voice and messaging URLs.\n\n@default true", + "default": true + }, + "number": { + "type": "string", + "description": "These are the digits of the phone number you own on your Twilio." + }, + "twilioAccountSid": { + "type": "string", + "description": "This is the Twilio Account SID for the phone number." + }, + "twilioAuthToken": { + "type": "string", + "description": "This is the Twilio Auth Token for the phone number." + }, + "twilioApiKey": { + "type": "string", + "description": "This is the Twilio API Key for the phone number." + }, + "twilioApiSecret": { + "type": "string", + "description": "This is the Twilio API Secret for the phone number." + }, + "name": { + "type": "string", + "description": "This is the name of the phone number. This is just for your own reference.", + "maxLength": 40 + }, + "assistantId": { + "type": "string", + "description": "This is the assistant that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId` nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + }, + "workflowId": { + "type": "string", + "description": "This is the workflow that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + }, + "squadId": { + "type": "string", + "description": "This is the squad that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + }, + "server": { + "description": "This is where Vapi will send webhooks. You can find all webhooks available along with their shape in ServerMessage schema.\n\nThe order of precedence is:\n\n1. assistant.server\n2. phoneNumber.server\n3. org.server", + "allOf": [ + { + "$ref": "#/components/schemas/Server" + } + ] + } + }, + "required": [ + "provider", + "number", + "twilioAccountSid" + ] + }, + "CreateVonagePhoneNumberDTO": { + "type": "object", + "properties": { + "fallbackDestination": { + "description": "This is the fallback destination an inbound call will be transferred to if:\n1. `assistantId` is not set\n2. `squadId` is not set\n3. and, `assistant-request` message to the `serverUrl` fails\n\nIf this is not set and above conditions are met, the inbound call is hung up with an error message.", "oneOf": [ { "$ref": "#/components/schemas/TransferDestinationNumber", @@ -27504,364 +50925,737 @@ } ] }, - "id": { + "hooks": { + "type": "array", + "description": "This is the hooks that will be used for incoming calls to this phone number.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/PhoneNumberHookCallRinging", + "title": "PhoneNumberHookCallRinging" + }, + { + "$ref": "#/components/schemas/PhoneNumberHookCallEnding", + "title": "PhoneNumberHookCallEnding" + } + ] + } + }, + "provider": { "type": "string", - "description": "This is the unique identifier for the call." + "description": "This is to use numbers bought on Vonage.", + "enum": [ + "vonage" + ] }, - "orgId": { + "number": { "type": "string", - "description": "This is the unique identifier for the org that this call belongs to." + "description": "These are the digits of the phone number you own on your Vonage." }, - "createdAt": { - "format": "date-time", + "credentialId": { "type": "string", - "description": "This is the ISO 8601 date-time string of when the call was created." + "description": "This is the credential you added in dashboard.vapi.ai/keys. This is used to configure the number to send inbound calls to Vapi, make outbound calls and do live call updates like transfers and hangups." }, - "updatedAt": { - "format": "date-time", + "name": { "type": "string", - "description": "This is the ISO 8601 date-time string of when the call was last updated." + "description": "This is the name of the phone number. This is just for your own reference.", + "maxLength": 40 }, - "startedAt": { - "format": "date-time", + "assistantId": { "type": "string", - "description": "This is the ISO 8601 date-time string of when the call was started." + "description": "This is the assistant that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId` nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." }, - "endedAt": { - "format": "date-time", + "workflowId": { "type": "string", - "description": "This is the ISO 8601 date-time string of when the call was ended." + "description": "This is the workflow that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." }, - "cost": { - "type": "number", - "description": "This is the cost of the call in USD." + "squadId": { + "type": "string", + "description": "This is the squad that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." }, - "costBreakdown": { - "description": "This is the cost of the call in USD.", + "server": { + "description": "This is where Vapi will send webhooks. You can find all webhooks available along with their shape in ServerMessage schema.\n\nThe order of precedence is:\n\n1. assistant.server\n2. phoneNumber.server\n3. org.server", "allOf": [ { - "$ref": "#/components/schemas/CostBreakdown" + "$ref": "#/components/schemas/Server" + } + ] + } + }, + "required": [ + "provider", + "number", + "credentialId" + ] + }, + "CreateVapiPhoneNumberDTO": { + "type": "object", + "properties": { + "fallbackDestination": { + "description": "This is the fallback destination an inbound call will be transferred to if:\n1. `assistantId` is not set\n2. `squadId` is not set\n3. and, `assistant-request` message to the `serverUrl` fails\n\nIf this is not set and above conditions are met, the inbound call is hung up with an error message.", + "oneOf": [ + { + "$ref": "#/components/schemas/TransferDestinationNumber", + "title": "NumberTransferDestination" + }, + { + "$ref": "#/components/schemas/TransferDestinationSip", + "title": "SipTransferDestination" } ] }, - "artifactPlan": { - "description": "This is a copy of assistant artifact plan. This isn't actually stored on the call but rather just returned in POST /call/web to enable artifact creation client side.", + "hooks": { + "type": "array", + "description": "This is the hooks that will be used for incoming calls to this phone number.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/PhoneNumberHookCallRinging", + "title": "PhoneNumberHookCallRinging" + }, + { + "$ref": "#/components/schemas/PhoneNumberHookCallEnding", + "title": "PhoneNumberHookCallEnding" + } + ] + } + }, + "provider": { + "type": "string", + "description": "This is to create free SIP phone numbers on Vapi.", + "enum": [ + "vapi" + ] + }, + "numberDesiredAreaCode": { + "type": "string", + "description": "This is the area code of the phone number to purchase.", + "minLength": 3, + "maxLength": 3 + }, + "sipUri": { + "type": "string", + "description": "This is the SIP URI of the phone number. You can SIP INVITE this. The assistant attached to this number will answer.\n\nThis is case-insensitive." + }, + "authentication": { + "description": "This enables authentication for incoming SIP INVITE requests to the `sipUri`.\n\nIf not set, any username/password to the 401 challenge of the SIP INVITE will be accepted.", "allOf": [ { - "$ref": "#/components/schemas/ArtifactPlan" + "$ref": "#/components/schemas/SipAuthentication" } ] }, - "analysis": { - "description": "This is the analysis of the call. Configure in `assistant.analysisPlan`.", + "name": { + "type": "string", + "description": "This is the name of the phone number. This is just for your own reference.", + "maxLength": 40 + }, + "assistantId": { + "type": "string", + "description": "This is the assistant that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId` nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + }, + "workflowId": { + "type": "string", + "description": "This is the workflow that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + }, + "squadId": { + "type": "string", + "description": "This is the squad that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + }, + "server": { + "description": "This is where Vapi will send webhooks. You can find all webhooks available along with their shape in ServerMessage schema.\n\nThe order of precedence is:\n\n1. assistant.server\n2. phoneNumber.server\n3. org.server", "allOf": [ { - "$ref": "#/components/schemas/Analysis" + "$ref": "#/components/schemas/Server" + } + ] + } + }, + "required": [ + "provider" + ] + }, + "CreateTelnyxPhoneNumberDTO": { + "type": "object", + "properties": { + "fallbackDestination": { + "description": "This is the fallback destination an inbound call will be transferred to if:\n1. `assistantId` is not set\n2. `squadId` is not set\n3. and, `assistant-request` message to the `serverUrl` fails\n\nIf this is not set and above conditions are met, the inbound call is hung up with an error message.", + "oneOf": [ + { + "$ref": "#/components/schemas/TransferDestinationNumber", + "title": "NumberTransferDestination" + }, + { + "$ref": "#/components/schemas/TransferDestinationSip", + "title": "SipTransferDestination" } ] }, - "monitor": { - "description": "This is to real-time monitor the call. Configure in `assistant.monitorPlan`.", + "hooks": { + "type": "array", + "description": "This is the hooks that will be used for incoming calls to this phone number.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/PhoneNumberHookCallRinging", + "title": "PhoneNumberHookCallRinging" + }, + { + "$ref": "#/components/schemas/PhoneNumberHookCallEnding", + "title": "PhoneNumberHookCallEnding" + } + ] + } + }, + "provider": { + "type": "string", + "description": "This is to use numbers bought on Telnyx.", + "enum": [ + "telnyx" + ] + }, + "number": { + "type": "string", + "description": "These are the digits of the phone number you own on your Telnyx." + }, + "credentialId": { + "type": "string", + "description": "This is the credential you added in dashboard.vapi.ai/keys. This is used to configure the number to send inbound calls to Vapi, make outbound calls and do live call updates like transfers and hangups." + }, + "name": { + "type": "string", + "description": "This is the name of the phone number. This is just for your own reference.", + "maxLength": 40 + }, + "assistantId": { + "type": "string", + "description": "This is the assistant that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId` nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + }, + "workflowId": { + "type": "string", + "description": "This is the workflow that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + }, + "squadId": { + "type": "string", + "description": "This is the squad that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + }, + "server": { + "description": "This is where Vapi will send webhooks. You can find all webhooks available along with their shape in ServerMessage schema.\n\nThe order of precedence is:\n\n1. assistant.server\n2. phoneNumber.server\n3. org.server", "allOf": [ { - "$ref": "#/components/schemas/Monitor" + "$ref": "#/components/schemas/Server" + } + ] + } + }, + "required": [ + "provider", + "number", + "credentialId" + ] + }, + "UpdateByoPhoneNumberDTO": { + "type": "object", + "properties": { + "fallbackDestination": { + "description": "This is the fallback destination an inbound call will be transferred to if:\n1. `assistantId` is not set\n2. `squadId` is not set\n3. and, `assistant-request` message to the `serverUrl` fails\n\nIf this is not set and above conditions are met, the inbound call is hung up with an error message.", + "oneOf": [ + { + "$ref": "#/components/schemas/TransferDestinationNumber", + "title": "NumberTransferDestination" + }, + { + "$ref": "#/components/schemas/TransferDestinationSip", + "title": "SipTransferDestination" } ] }, - "artifact": { - "description": "These are the artifacts created from the call. Configure in `assistant.artifactPlan`.", + "hooks": { + "type": "array", + "description": "This is the hooks that will be used for incoming calls to this phone number.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/PhoneNumberHookCallRinging", + "title": "PhoneNumberHookCallRinging" + }, + { + "$ref": "#/components/schemas/PhoneNumberHookCallEnding", + "title": "PhoneNumberHookCallEnding" + } + ] + } + }, + "provider": { + "type": "string", + "description": "This is to bring your own phone numbers from your own SIP trunks or Carriers.", + "enum": [ + "byo-phone-number" + ] + }, + "numberE164CheckEnabled": { + "type": "boolean", + "description": "This is the flag to toggle the E164 check for the `number` field. This is an advanced property which should be used if you know your use case requires it.\n\nUse cases:\n- `false`: To allow non-E164 numbers like `+001234567890`, `1234`, or `abc`. This is useful for dialing out to non-E164 numbers on your SIP trunks.\n- `true` (default): To allow only E164 numbers like `+14155551234`. This is standard for PSTN calls.\n\nIf `false`, the `number` is still required to only contain alphanumeric characters (regex: `/^\\+?[a-zA-Z0-9]+$/`).\n\n@default true (E164 check is enabled)", + "default": true + }, + "name": { + "type": "string", + "description": "This is the name of the phone number. This is just for your own reference.", + "maxLength": 40 + }, + "assistantId": { + "type": "string", + "description": "This is the assistant that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId` nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + }, + "workflowId": { + "type": "string", + "description": "This is the workflow that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + }, + "squadId": { + "type": "string", + "description": "This is the squad that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + }, + "server": { + "description": "This is where Vapi will send webhooks. You can find all webhooks available along with their shape in ServerMessage schema.\n\nThe order of precedence is:\n\n1. assistant.server\n2. phoneNumber.server\n3. org.server", "allOf": [ { - "$ref": "#/components/schemas/Artifact" + "$ref": "#/components/schemas/Server" + } + ] + }, + "number": { + "type": "string", + "description": "This is the number of the customer.", + "minLength": 3, + "maxLength": 40 + }, + "credentialId": { + "type": "string", + "description": "This is the credential of your own SIP trunk or Carrier (type `byo-sip-trunk`) which can be used to make calls to this phone number.\n\nYou can add the SIP trunk or Carrier credential in the Provider Credentials page on the Dashboard to get the credentialId." + } + } + }, + "UpdateTwilioPhoneNumberDTO": { + "type": "object", + "properties": { + "fallbackDestination": { + "description": "This is the fallback destination an inbound call will be transferred to if:\n1. `assistantId` is not set\n2. `squadId` is not set\n3. and, `assistant-request` message to the `serverUrl` fails\n\nIf this is not set and above conditions are met, the inbound call is hung up with an error message.", + "oneOf": [ + { + "$ref": "#/components/schemas/TransferDestinationNumber", + "title": "NumberTransferDestination" + }, + { + "$ref": "#/components/schemas/TransferDestinationSip", + "title": "SipTransferDestination" + } + ] + }, + "hooks": { + "type": "array", + "description": "This is the hooks that will be used for incoming calls to this phone number.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/PhoneNumberHookCallRinging", + "title": "PhoneNumberHookCallRinging" + }, + { + "$ref": "#/components/schemas/PhoneNumberHookCallEnding", + "title": "PhoneNumberHookCallEnding" + } + ] + } + }, + "provider": { + "type": "string", + "description": "This is to use numbers bought on Twilio.", + "enum": [ + "twilio" + ] + }, + "smsEnabled": { + "type": "boolean", + "description": "Controls whether Vapi sets the messaging webhook URL on the Twilio number during import.\n\nIf set to `false`, Vapi will not update the Twilio messaging URL, leaving it as is.\nIf `true` or omitted (default), Vapi will configure both the voice and messaging URLs.\n\n@default true", + "default": true + }, + "name": { + "type": "string", + "description": "This is the name of the phone number. This is just for your own reference.", + "maxLength": 40 + }, + "assistantId": { + "type": "string", + "description": "This is the assistant that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId` nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + }, + "workflowId": { + "type": "string", + "description": "This is the workflow that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + }, + "squadId": { + "type": "string", + "description": "This is the squad that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + }, + "server": { + "description": "This is where Vapi will send webhooks. You can find all webhooks available along with their shape in ServerMessage schema.\n\nThe order of precedence is:\n\n1. assistant.server\n2. phoneNumber.server\n3. org.server", + "allOf": [ + { + "$ref": "#/components/schemas/Server" + } + ] + }, + "number": { + "type": "string", + "description": "These are the digits of the phone number you own on your Twilio." + }, + "twilioAccountSid": { + "type": "string", + "description": "This is the Twilio Account SID for the phone number." + }, + "twilioAuthToken": { + "type": "string", + "description": "This is the Twilio Auth Token for the phone number." + }, + "twilioApiKey": { + "type": "string", + "description": "This is the Twilio API Key for the phone number." + }, + "twilioApiSecret": { + "type": "string", + "description": "This is the Twilio API Secret for the phone number." + } + } + }, + "UpdateVonagePhoneNumberDTO": { + "type": "object", + "properties": { + "fallbackDestination": { + "description": "This is the fallback destination an inbound call will be transferred to if:\n1. `assistantId` is not set\n2. `squadId` is not set\n3. and, `assistant-request` message to the `serverUrl` fails\n\nIf this is not set and above conditions are met, the inbound call is hung up with an error message.", + "oneOf": [ + { + "$ref": "#/components/schemas/TransferDestinationNumber", + "title": "NumberTransferDestination" + }, + { + "$ref": "#/components/schemas/TransferDestinationSip", + "title": "SipTransferDestination" } ] }, - "phoneCallProviderId": { + "hooks": { + "type": "array", + "description": "This is the hooks that will be used for incoming calls to this phone number.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/PhoneNumberHookCallRinging", + "title": "PhoneNumberHookCallRinging" + }, + { + "$ref": "#/components/schemas/PhoneNumberHookCallEnding", + "title": "PhoneNumberHookCallEnding" + } + ] + } + }, + "provider": { "type": "string", - "description": "The ID of the call as provided by the phone number service. callSid in Twilio. conversationUuid in Vonage. callControlId in Telnyx.\n\nOnly relevant for `outboundPhoneCall` and `inboundPhoneCall` type.", - "deprecated": true + "description": "This is to use numbers bought on Vonage.", + "enum": [ + "vonage" + ] }, - "campaignId": { + "name": { "type": "string", - "description": "This is the campaign ID that the call belongs to." + "description": "This is the name of the phone number. This is just for your own reference.", + "maxLength": 40 }, "assistantId": { "type": "string", - "description": "This is the assistant ID that will be used for the call. To use a transient assistant, use `assistant` instead.\n\nTo start a call with:\n- Assistant, use `assistantId` or `assistant`\n- Squad, use `squadId` or `squad`\n- Workflow, use `workflowId` or `workflow`" - }, - "assistant": { - "description": "This is the assistant that will be used for the call. To use an existing assistant, use `assistantId` instead.\n\nTo start a call with:\n- Assistant, use `assistant`\n- Squad, use `squad`\n- Workflow, use `workflow`", - "allOf": [ - { - "$ref": "#/components/schemas/CreateAssistantDTO" - } - ] + "description": "This is the assistant that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId` nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." }, - "assistantOverrides": { - "description": "These are the overrides for the `assistant` or `assistantId`'s settings and template variables.", - "allOf": [ - { - "$ref": "#/components/schemas/AssistantOverrides" - } - ] + "workflowId": { + "type": "string", + "description": "This is the workflow that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." }, "squadId": { "type": "string", - "description": "This is the squad that will be used for the call. To use a transient squad, use `squad` instead.\n\nTo start a call with:\n- Assistant, use `assistant` or `assistantId`\n- Squad, use `squad` or `squadId`\n- Workflow, use `workflow` or `workflowId`" + "description": "This is the squad that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." }, - "squad": { - "description": "This is a squad that will be used for the call. To use an existing squad, use `squadId` instead.\n\nTo start a call with:\n- Assistant, use `assistant` or `assistantId`\n- Squad, use `squad` or `squadId`\n- Workflow, use `workflow` or `workflowId`", + "server": { + "description": "This is where Vapi will send webhooks. You can find all webhooks available along with their shape in ServerMessage schema.\n\nThe order of precedence is:\n\n1. assistant.server\n2. phoneNumber.server\n3. org.server", "allOf": [ { - "$ref": "#/components/schemas/CreateSquadDTO" + "$ref": "#/components/schemas/Server" } ] }, - "workflowId": { + "number": { "type": "string", - "description": "This is the workflow that will be used for the call. To use a transient workflow, use `workflow` instead.\n\nTo start a call with:\n- Assistant, use `assistant` or `assistantId`\n- Squad, use `squad` or `squadId`\n- Workflow, use `workflow` or `workflowId`" + "description": "These are the digits of the phone number you own on your Vonage." }, - "workflow": { - "description": "This is a workflow that will be used for the call. To use an existing workflow, use `workflowId` instead.\n\nTo start a call with:\n- Assistant, use `assistant` or `assistantId`\n- Squad, use `squad` or `squadId`\n- Workflow, use `workflow` or `workflowId`", - "allOf": [ + "credentialId": { + "type": "string", + "description": "This is the credential you added in dashboard.vapi.ai/keys. This is used to configure the number to send inbound calls to Vapi, make outbound calls and do live call updates like transfers and hangups." + } + } + }, + "UpdateVapiPhoneNumberDTO": { + "type": "object", + "properties": { + "fallbackDestination": { + "description": "This is the fallback destination an inbound call will be transferred to if:\n1. `assistantId` is not set\n2. `squadId` is not set\n3. and, `assistant-request` message to the `serverUrl` fails\n\nIf this is not set and above conditions are met, the inbound call is hung up with an error message.", + "oneOf": [ { - "$ref": "#/components/schemas/CreateWorkflowDTO" + "$ref": "#/components/schemas/TransferDestinationNumber", + "title": "NumberTransferDestination" + }, + { + "$ref": "#/components/schemas/TransferDestinationSip", + "title": "SipTransferDestination" } ] }, - "workflowOverrides": { - "description": "These are the overrides for the `workflow` or `workflowId`'s settings and template variables.", - "allOf": [ - { - "$ref": "#/components/schemas/WorkflowOverrides" - } + "hooks": { + "type": "array", + "description": "This is the hooks that will be used for incoming calls to this phone number.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/PhoneNumberHookCallRinging", + "title": "PhoneNumberHookCallRinging" + }, + { + "$ref": "#/components/schemas/PhoneNumberHookCallEnding", + "title": "PhoneNumberHookCallEnding" + } + ] + } + }, + "provider": { + "type": "string", + "enum": [ + "vapi" ] }, - "phoneNumberId": { + "name": { "type": "string", - "description": "This is the phone number that will be used for the call. To use a transient number, use `phoneNumber` instead.\n\nOnly relevant for `outboundPhoneCall` and `inboundPhoneCall` type." + "description": "This is the name of the phone number. This is just for your own reference.", + "maxLength": 40 }, - "phoneNumber": { - "description": "This is the phone number that will be used for the call. To use an existing number, use `phoneNumberId` instead.\n\nOnly relevant for `outboundPhoneCall` and `inboundPhoneCall` type.", - "allOf": [ - { - "$ref": "#/components/schemas/ImportTwilioPhoneNumberDTO" - } - ] + "assistantId": { + "type": "string", + "description": "This is the assistant that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId` nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." }, - "customerId": { + "workflowId": { "type": "string", - "description": "This is the customer that will be called. To call a transient customer , use `customer` instead.\n\nOnly relevant for `outboundPhoneCall` and `inboundPhoneCall` type." + "description": "This is the workflow that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." }, - "customer": { - "description": "This is the customer that will be called. To call an existing customer, use `customerId` instead.\n\nOnly relevant for `outboundPhoneCall` and `inboundPhoneCall` type.", + "squadId": { + "type": "string", + "description": "This is the squad that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + }, + "server": { + "description": "This is where Vapi will send webhooks. You can find all webhooks available along with their shape in ServerMessage schema.\n\nThe order of precedence is:\n\n1. assistant.server\n2. phoneNumber.server\n3. org.server", "allOf": [ { - "$ref": "#/components/schemas/CreateCustomerDTO" + "$ref": "#/components/schemas/Server" } ] }, - "name": { + "sipUri": { "type": "string", - "description": "This is the name of the call. This is just for your own reference.", - "maxLength": 40 + "description": "This is the SIP URI of the phone number. You can SIP INVITE this. The assistant attached to this number will answer.\n\nThis is case-insensitive." }, - "schedulePlan": { - "description": "This is the schedule plan of the call.", + "authentication": { + "description": "This enables authentication for incoming SIP INVITE requests to the `sipUri`.\n\nIf not set, any username/password to the 401 challenge of the SIP INVITE will be accepted.", "allOf": [ { - "$ref": "#/components/schemas/SchedulePlan" + "$ref": "#/components/schemas/SipAuthentication" } ] - }, - "transport": { - "type": "object", - "description": "This is the transport of the call." } - }, - "required": [ - "id", - "orgId", - "createdAt", - "updatedAt" - ] + } }, - "CallBatchError": { + "UpdateTelnyxPhoneNumberDTO": { "type": "object", "properties": { - "customer": { - "$ref": "#/components/schemas/CreateCustomerDTO" + "fallbackDestination": { + "description": "This is the fallback destination an inbound call will be transferred to if:\n1. `assistantId` is not set\n2. `squadId` is not set\n3. and, `assistant-request` message to the `serverUrl` fails\n\nIf this is not set and above conditions are met, the inbound call is hung up with an error message.", + "oneOf": [ + { + "$ref": "#/components/schemas/TransferDestinationNumber", + "title": "NumberTransferDestination" + }, + { + "$ref": "#/components/schemas/TransferDestinationSip", + "title": "SipTransferDestination" + } + ] }, - "error": { - "type": "string" - } - }, - "required": [ - "customer", - "error" - ] - }, - "CallBatchResponse": { - "type": "object", - "properties": { - "results": { - "description": "This is the list of calls that were created.", + "hooks": { "type": "array", + "description": "This is the hooks that will be used for incoming calls to this phone number.", "items": { - "$ref": "#/components/schemas/Call" + "oneOf": [ + { + "$ref": "#/components/schemas/PhoneNumberHookCallRinging", + "title": "PhoneNumberHookCallRinging" + }, + { + "$ref": "#/components/schemas/PhoneNumberHookCallEnding", + "title": "PhoneNumberHookCallEnding" + } + ] } }, - "errors": { - "description": "This is the list of calls that failed to be created.", - "type": "array", - "items": { - "$ref": "#/components/schemas/CallBatchError" - } - } - }, - "required": [ - "results", - "errors" - ] - }, - "CreateCallDTO": { - "type": "object", - "properties": { - "customers": { - "description": "This is used to issue batch calls to multiple customers.\n\nOnly relevant for `outboundPhoneCall`. To call a single customer, use `customer` instead.", - "type": "array", - "items": { - "$ref": "#/components/schemas/CreateCustomerDTO" - } + "provider": { + "type": "string", + "description": "This is to use numbers bought on Telnyx.", + "enum": [ + "telnyx" + ] }, "name": { "type": "string", - "description": "This is the name of the call. This is just for your own reference.", + "description": "This is the name of the phone number. This is just for your own reference.", "maxLength": 40 }, - "schedulePlan": { - "description": "This is the schedule plan of the call.", - "allOf": [ - { - "$ref": "#/components/schemas/SchedulePlan" - } - ] - }, - "transport": { - "type": "object", - "description": "This is the transport of the call." - }, "assistantId": { "type": "string", - "description": "This is the assistant ID that will be used for the call. To use a transient assistant, use `assistant` instead.\n\nTo start a call with:\n- Assistant, use `assistantId` or `assistant`\n- Squad, use `squadId` or `squad`\n- Workflow, use `workflowId` or `workflow`" - }, - "assistant": { - "description": "This is the assistant that will be used for the call. To use an existing assistant, use `assistantId` instead.\n\nTo start a call with:\n- Assistant, use `assistant`\n- Squad, use `squad`\n- Workflow, use `workflow`", - "allOf": [ - { - "$ref": "#/components/schemas/CreateAssistantDTO" - } - ] + "description": "This is the assistant that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId` nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." }, - "assistantOverrides": { - "description": "These are the overrides for the `assistant` or `assistantId`'s settings and template variables.", - "allOf": [ - { - "$ref": "#/components/schemas/AssistantOverrides" - } - ] + "workflowId": { + "type": "string", + "description": "This is the workflow that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." }, "squadId": { "type": "string", - "description": "This is the squad that will be used for the call. To use a transient squad, use `squad` instead.\n\nTo start a call with:\n- Assistant, use `assistant` or `assistantId`\n- Squad, use `squad` or `squadId`\n- Workflow, use `workflow` or `workflowId`" + "description": "This is the squad that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." }, - "squad": { - "description": "This is a squad that will be used for the call. To use an existing squad, use `squadId` instead.\n\nTo start a call with:\n- Assistant, use `assistant` or `assistantId`\n- Squad, use `squad` or `squadId`\n- Workflow, use `workflow` or `workflowId`", + "server": { + "description": "This is where Vapi will send webhooks. You can find all webhooks available along with their shape in ServerMessage schema.\n\nThe order of precedence is:\n\n1. assistant.server\n2. phoneNumber.server\n3. org.server", "allOf": [ { - "$ref": "#/components/schemas/CreateSquadDTO" + "$ref": "#/components/schemas/Server" } ] }, - "workflowId": { + "number": { "type": "string", - "description": "This is the workflow that will be used for the call. To use a transient workflow, use `workflow` instead.\n\nTo start a call with:\n- Assistant, use `assistant` or `assistantId`\n- Squad, use `squad` or `squadId`\n- Workflow, use `workflow` or `workflowId`" + "description": "These are the digits of the phone number you own on your Telnyx." }, - "workflow": { - "description": "This is a workflow that will be used for the call. To use an existing workflow, use `workflowId` instead.\n\nTo start a call with:\n- Assistant, use `assistant` or `assistantId`\n- Squad, use `squad` or `squadId`\n- Workflow, use `workflow` or `workflowId`", - "allOf": [ + "credentialId": { + "type": "string", + "description": "This is the credential you added in dashboard.vapi.ai/keys. This is used to configure the number to send inbound calls to Vapi, make outbound calls and do live call updates like transfers and hangups." + } + } + }, + "ImportVonagePhoneNumberDTO": { + "type": "object", + "properties": { + "fallbackDestination": { + "description": "This is the fallback destination an inbound call will be transferred to if:\n1. `assistantId` is not set\n2. `squadId` is not set\n3. and, `assistant-request` message to the `serverUrl` fails\n\nIf this is not set and above conditions are met, the inbound call is hung up with an error message.", + "oneOf": [ { - "$ref": "#/components/schemas/CreateWorkflowDTO" - } - ] - }, - "workflowOverrides": { - "description": "These are the overrides for the `workflow` or `workflowId`'s settings and template variables.", - "allOf": [ + "$ref": "#/components/schemas/TransferDestinationNumber", + "title": "NumberTransferDestination" + }, { - "$ref": "#/components/schemas/WorkflowOverrides" + "$ref": "#/components/schemas/TransferDestinationSip", + "title": "SipTransferDestination" } ] }, - "phoneNumberId": { + "hooks": { + "type": "array", + "description": "This is the hooks that will be used for incoming calls to this phone number.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/PhoneNumberHookCallRinging", + "title": "PhoneNumberHookCallRinging" + }, + { + "$ref": "#/components/schemas/PhoneNumberHookCallEnding", + "title": "PhoneNumberHookCallEnding" + } + ] + } + }, + "vonagePhoneNumber": { "type": "string", - "description": "This is the phone number that will be used for the call. To use a transient number, use `phoneNumber` instead.\n\nOnly relevant for `outboundPhoneCall` and `inboundPhoneCall` type." + "description": "These are the digits of the phone number you own on your Vonage.", + "deprecated": true }, - "phoneNumber": { - "description": "This is the phone number that will be used for the call. To use an existing number, use `phoneNumberId` instead.\n\nOnly relevant for `outboundPhoneCall` and `inboundPhoneCall` type.", - "allOf": [ - { - "$ref": "#/components/schemas/ImportTwilioPhoneNumberDTO" - } - ] + "credentialId": { + "type": "string", + "description": "This is the credential you added in dashboard.vapi.ai/keys. This is used to configure the number to send inbound calls to Vapi, make outbound calls and do live call updates like transfers and hangups." }, - "customerId": { + "name": { "type": "string", - "description": "This is the customer that will be called. To call a transient customer , use `customer` instead.\n\nOnly relevant for `outboundPhoneCall` and `inboundPhoneCall` type." + "description": "This is the name of the phone number. This is just for your own reference.", + "maxLength": 40 }, - "customer": { - "description": "This is the customer that will be called. To call an existing customer, use `customerId` instead.\n\nOnly relevant for `outboundPhoneCall` and `inboundPhoneCall` type.", + "assistantId": { + "type": "string", + "description": "This is the assistant that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId` nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + }, + "workflowId": { + "type": "string", + "description": "This is the workflow that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + }, + "squadId": { + "type": "string", + "description": "This is the squad that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + }, + "server": { + "description": "This is where Vapi will send webhooks. You can find all webhooks available along with their shape in ServerMessage schema.\n\nThe order of precedence is:\n\n1. assistant.server\n2. phoneNumber.server\n3. org.server", "allOf": [ { - "$ref": "#/components/schemas/CreateCustomerDTO" + "$ref": "#/components/schemas/Server" } ] } - } - }, - "PaginationMeta": { - "type": "object", - "properties": { - "itemsPerPage": { - "type": "number" - }, - "totalItems": { - "type": "number" - }, - "currentPage": { - "type": "number" - }, - "itemsBeyondRetention": { - "type": "boolean" - } }, "required": [ - "itemsPerPage", - "totalItems", - "currentPage" + "vonagePhoneNumber", + "credentialId" ] }, - "CallPaginatedResponse": { + "PhoneNumberPaginatedResponse": { "type": "object", "properties": { "results": { "type": "array", + "description": "A list of phone numbers, which can be of any provider type.", "items": { - "$ref": "#/components/schemas/Call" + "oneOf": [ + { + "$ref": "#/components/schemas/ByoPhoneNumber" + }, + { + "$ref": "#/components/schemas/TwilioPhoneNumber" + }, + { + "$ref": "#/components/schemas/VonagePhoneNumber" + }, + { + "$ref": "#/components/schemas/VapiPhoneNumber" + }, + { + "$ref": "#/components/schemas/TelnyxPhoneNumber" + } + ] } }, "metadata": { - "$ref": "#/components/schemas/PaginationMeta" + "description": "Metadata about the pagination.", + "allOf": [ + { + "$ref": "#/components/schemas/PaginationMeta" + } + ] } }, "required": [ @@ -27869,5172 +51663,5425 @@ "metadata" ] }, - "CreateOutboundCallDTO": { + "ApiRequestTool": { "type": "object", "properties": { - "customers": { - "description": "This is used to issue batch calls to multiple customers.\n\nOnly relevant for `outboundPhoneCall`. To call a single customer, use `customer` instead.", + "latestVersion": { + "type": "string", + "nullable": true + }, + "messages": { "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", "items": { - "$ref": "#/components/schemas/CreateCustomerDTO" + "oneOf": [ + { + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" + }, + { + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] } }, + "type": { + "type": "string", + "enum": [ + "apiRequest" + ], + "description": "The type of tool. \"apiRequest\" for API request tool." + }, "name": { "type": "string", - "description": "This is the name of the call. This is just for your own reference.", - "maxLength": 40 + "description": "This is the name of the tool. This will be passed to the model.\n\nMust be a-z, A-Z, 0-9, or contain underscores and dashes, with a maximum length of 40.", + "maxLength": 40, + "pattern": "/^[a-zA-Z0-9_-]{1,40}$/" }, - "schedulePlan": { - "description": "This is the schedule plan of the call.", - "allOf": [ - { - "$ref": "#/components/schemas/SchedulePlan" - } + "method": { + "type": "string", + "enum": [ + "POST", + "GET", + "PUT", + "PATCH", + "DELETE" ] }, - "transport": { - "type": "object", - "description": "This is the transport of the call." + "timeoutSeconds": { + "type": "number", + "description": "This is the timeout in seconds for the request. Defaults to 20 seconds.\n\n@default 20", + "minimum": 1, + "maximum": 300, + "example": 20 }, - "assistantId": { + "credentialId": { "type": "string", - "description": "This is the assistant ID that will be used for the call. To use a transient assistant, use `assistant` instead.\n\nTo start a call with:\n- Assistant, use `assistantId` or `assistant`\n- Squad, use `squadId` or `squad`\n- Workflow, use `workflowId` or `workflow`" + "description": "The credential ID for API request authentication", + "example": "550e8400-e29b-41d4-a716-446655440000" }, - "assistant": { - "description": "This is the assistant that will be used for the call. To use an existing assistant, use `assistantId` instead.\n\nTo start a call with:\n- Assistant, use `assistant`\n- Squad, use `squad`\n- Workflow, use `workflow`", - "allOf": [ - { - "$ref": "#/components/schemas/CreateAssistantDTO" - } - ] + "encryptedPaths": { + "type": "array", + "description": "This is the paths to encrypt in the request body if credentialId and encryptionPlan are defined.", + "items": { + "type": "string" + } }, - "assistantOverrides": { - "description": "These are the overrides for the `assistant` or `assistantId`'s settings and template variables.", - "allOf": [ - { - "$ref": "#/components/schemas/AssistantOverrides" - } - ] + "parameters": { + "description": "Static key-value pairs merged into the request body. Values support Liquid templates.", + "type": "array", + "items": { + "$ref": "#/components/schemas/ToolParameter" + } }, - "squadId": { + "id": { "type": "string", - "description": "This is the squad that will be used for the call. To use a transient squad, use `squad` instead.\n\nTo start a call with:\n- Assistant, use `assistant` or `assistantId`\n- Squad, use `squad` or `squadId`\n- Workflow, use `workflow` or `workflowId`" + "description": "This is the unique identifier for the tool." }, - "squad": { - "description": "This is a squad that will be used for the call. To use an existing squad, use `squadId` instead.\n\nTo start a call with:\n- Assistant, use `assistant` or `assistantId`\n- Squad, use `squad` or `squadId`\n- Workflow, use `workflow` or `workflowId`", + "orgId": { + "type": "string", + "description": "This is the unique identifier for the organization that this tool belongs to." + }, + "createdAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the tool was created." + }, + "updatedAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the tool was last updated." + }, + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", "allOf": [ { - "$ref": "#/components/schemas/CreateSquadDTO" + "$ref": "#/components/schemas/ToolRejectionPlan" } ] }, - "workflowId": { + "description": { "type": "string", - "description": "This is the workflow that will be used for the call. To use a transient workflow, use `workflow` instead.\n\nTo start a call with:\n- Assistant, use `assistant` or `assistantId`\n- Squad, use `squad` or `squadId`\n- Workflow, use `workflow` or `workflowId`" + "description": "This is the description of the tool. This will be passed to the model." }, - "workflow": { - "description": "This is a workflow that will be used for the call. To use an existing workflow, use `workflowId` instead.\n\nTo start a call with:\n- Assistant, use `assistant` or `assistantId`\n- Squad, use `squad` or `squadId`\n- Workflow, use `workflow` or `workflowId`", + "url": { + "type": "string", + "description": "This is where the request will be sent." + }, + "body": { + "description": "This is the body of the request.", "allOf": [ { - "$ref": "#/components/schemas/CreateWorkflowDTO" + "$ref": "#/components/schemas/JsonSchema" } ] }, - "workflowOverrides": { - "description": "These are the overrides for the `workflow` or `workflowId`'s settings and template variables.", + "headers": { + "description": "These are the headers to send with the request.", "allOf": [ { - "$ref": "#/components/schemas/WorkflowOverrides" + "$ref": "#/components/schemas/JsonSchema" } ] }, - "phoneNumberId": { - "type": "string", - "description": "This is the phone number that will be used for the call. To use a transient number, use `phoneNumber` instead.\n\nOnly relevant for `outboundPhoneCall` and `inboundPhoneCall` type." - }, - "phoneNumber": { - "description": "This is the phone number that will be used for the call. To use an existing number, use `phoneNumberId` instead.\n\nOnly relevant for `outboundPhoneCall` and `inboundPhoneCall` type.", + "backoffPlan": { + "description": "This is the backoff plan if the request fails. Defaults to undefined (the request will not be retried).\n\n@default undefined (the request will not be retried)", "allOf": [ { - "$ref": "#/components/schemas/ImportTwilioPhoneNumberDTO" + "$ref": "#/components/schemas/BackoffPlan" } ] }, - "customerId": { - "type": "string", - "description": "This is the customer that will be called. To call a transient customer , use `customer` instead.\n\nOnly relevant for `outboundPhoneCall` and `inboundPhoneCall` type." - }, - "customer": { - "description": "This is the customer that will be called. To call an existing customer, use `customerId` instead.\n\nOnly relevant for `outboundPhoneCall` and `inboundPhoneCall` type.", + "variableExtractionPlan": { + "description": "This is the plan to extract variables from the tool's response. These will be accessible during the call and stored in `call.artifact.variableValues` after the call.\n\nUsage:\n1. Use `aliases` to extract variables from the tool's response body. (Most common case)\n\n```json\n{\n \"aliases\": [\n {\n \"key\": \"customerName\",\n \"value\": \"{{customer.name}}\"\n },\n {\n \"key\": \"customerAge\",\n \"value\": \"{{customer.age}}\"\n }\n ]\n}\n```\n\nThe tool response body is made available to the liquid template.\n\n2. Use `aliases` to extract variables from the tool's response body if the response is an array.\n\n```json\n{\n \"aliases\": [\n {\n \"key\": \"customerName\",\n \"value\": \"{{$[0].name}}\"\n },\n {\n \"key\": \"customerAge\",\n \"value\": \"{{$[0].age}}\"\n }\n ]\n}\n```\n\n$ is a shorthand for the tool's response body. `$[0]` is the first item in the array. `$[n]` is the nth item in the array. Note, $ is available regardless of the response body type (both object and array).\n\n3. Use `aliases` to extract variables from the tool's response headers.\n\n```json\n{\n \"aliases\": [\n {\n \"key\": \"customerName\",\n \"value\": \"{{tool.response.headers.customer-name}}\"\n },\n {\n \"key\": \"customerAge\",\n \"value\": \"{{tool.response.headers.customer-age}}\"\n }\n ]\n}\n```\n\n`tool.response` is made available to the liquid template. Particularly, both `tool.response.headers` and `tool.response.body` are available. Note, `tool.response` is available regardless of the response body type (both object and array).\n\n4. Use `schema` to extract a large portion of the tool's response body.\n\n4.1. If you hit example.com and it returns `{\"name\": \"John\", \"age\": 30}`, then you can specify the schema as:\n\n```json\n{\n \"schema\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n },\n \"age\": {\n \"type\": \"number\"\n }\n }\n }\n}\n```\nThese will be extracted as `{{ name }}` and `{{ age }}` respectively. To emphasize, object properties are extracted as direct global variables.\n\n4.2. If you hit example.com and it returns `{\"name\": {\"first\": \"John\", \"last\": \"Doe\"}}`, then you can specify the schema as:\n\n```json\n{\n \"schema\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"object\",\n \"properties\": {\n \"first\": {\n \"type\": \"string\"\n },\n \"last\": {\n \"type\": \"string\"\n }\n }\n }\n }\n }\n}\n```\n\nThese will be extracted as `{{ name }}`. And, `{{ name.first }}` and `{{ name.last }}` will be accessible.\n\n4.3. If you hit example.com and it returns `[\"94123\", \"94124\"]`, then you can specify the schema as:\n\n```json\n{\n \"schema\": {\n \"type\": \"array\",\n \"title\": \"zipCodes\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n}\n```\n\nThis will be extracted as `{{ zipCodes }}`. To access the array items, you can use `{{ zipCodes[0] }}` and `{{ zipCodes[1] }}`.\n\n4.4. If you hit example.com and it returns `[{\"name\": \"John\", \"age\": 30, \"zipCodes\": [\"94123\", \"94124\"]}, {\"name\": \"Jane\", \"age\": 25, \"zipCodes\": [\"94125\", \"94126\"]}]`, then you can specify the schema as:\n\n```json\n{\n \"schema\": {\n \"type\": \"array\",\n \"title\": \"people\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n },\n \"age\": {\n \"type\": \"number\"\n },\n \"zipCodes\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n }\n }\n }\n}\n```\n\nThis will be extracted as `{{ people }}`. To access the array items, you can use `{{ people[n].name }}`, `{{ people[n].age }}`, `{{ people[n].zipCodes }}`, `{{ people[n].zipCodes[0] }}` and `{{ people[n].zipCodes[1] }}`.\n\nNote: Both `aliases` and `schema` can be used together.", "allOf": [ { - "$ref": "#/components/schemas/CreateCustomerDTO" + "$ref": "#/components/schemas/VariableExtractionPlan" } ] } - } + }, + "required": [ + "type", + "method", + "id", + "orgId", + "createdAt", + "updatedAt", + "url" + ] }, - "CreateWebCallDTO": { + "CodeToolEnvironmentVariable": { "type": "object", "properties": { - "assistantId": { + "name": { "type": "string", - "description": "This is the assistant ID that will be used for the call. To use a transient assistant, use `assistant` instead.\n\nTo start a call with:\n- Assistant, use `assistantId` or `assistant`\n- Squad, use `squadId` or `squad`\n- Workflow, use `workflowId` or `workflow`" + "description": "Name of the environment variable", + "maxLength": 64, + "pattern": "/^[A-Z][A-Z0-9_]*$/", + "example": "API_KEY" }, - "assistant": { - "description": "This is the assistant that will be used for the call. To use an existing assistant, use `assistantId` instead.\n\nTo start a call with:\n- Assistant, use `assistant`\n- Squad, use `squad`\n- Workflow, use `workflow`", - "allOf": [ - { - "$ref": "#/components/schemas/CreateAssistantDTO" - } - ] + "value": { + "type": "string", + "description": "Value of the environment variable. Supports Liquid templates.", + "maxLength": 10000, + "example": "{{apiKey}}" + } + }, + "required": [ + "name", + "value" + ] + }, + "CodeTool": { + "type": "object", + "properties": { + "latestVersion": { + "type": "string", + "nullable": true }, - "assistantOverrides": { - "description": "These are the overrides for the `assistant` or `assistantId`'s settings and template variables.", + "messages": { + "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" + }, + { + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] + } + }, + "type": { + "type": "string", + "enum": [ + "code" + ], + "description": "The type of tool. \"code\" for Code tool." + }, + "async": { + "type": "boolean", + "example": false, + "description": "This determines if the tool is async.\n\n If async, the assistant will move forward without waiting for your server to respond. This is useful if you just want to trigger something on your server.\n\n If sync, the assistant will wait for your server to respond. This is useful if want assistant to respond with the result from your server.\n\n Defaults to synchronous (`false`)." + }, + "server": { + "description": "\n This is the server where a `tool-calls` webhook will be sent.\n\n Notes:\n - Webhook is sent to this server when a tool call is made.\n - Webhook contains the call, assistant, and phone number objects.\n - Webhook contains the variables set on the assistant.\n - Webhook is sent to the first available URL in this order: {{tool.server.url}}, {{assistant.server.url}}, {{phoneNumber.server.url}}, {{org.server.url}}.\n - Webhook expects a response with tool call result.", "allOf": [ { - "$ref": "#/components/schemas/AssistantOverrides" + "$ref": "#/components/schemas/Server" } ] }, - "squadId": { + "code": { "type": "string", - "description": "This is the squad that will be used for the call. To use a transient squad, use `squad` instead.\n\nTo start a call with:\n- Assistant, use `assistant` or `assistantId`\n- Squad, use `squad` or `squadId`\n- Workflow, use `workflow` or `workflowId`" + "description": "TypeScript code to execute when the tool is called", + "maxLength": 50000 }, - "squad": { - "description": "This is a squad that will be used for the call. To use an existing squad, use `squadId` instead.\n\nTo start a call with:\n- Assistant, use `assistant` or `assistantId`\n- Squad, use `squad` or `squadId`\n- Workflow, use `workflow` or `workflowId`", + "environmentVariables": { + "description": "Environment variables available in code via `env` object", + "type": "array", + "items": { + "$ref": "#/components/schemas/CodeToolEnvironmentVariable" + } + }, + "timeoutSeconds": { + "type": "number", + "description": "This is the timeout in seconds for the code execution. Defaults to 10 seconds.\nMaximum is 30 seconds to prevent abuse.\n\n@default 10", + "minimum": 1, + "maximum": 30, + "example": 10 + }, + "credentialId": { + "type": "string", + "description": "Credential ID containing the Val Town API key", + "example": "550e8400-e29b-41d4-a716-446655440000" + }, + "variableExtractionPlan": { + "description": "Plan to extract variables from the tool response", "allOf": [ { - "$ref": "#/components/schemas/CreateSquadDTO" + "$ref": "#/components/schemas/VariableExtractionPlan" } ] }, - "workflowId": { + "id": { "type": "string", - "description": "This is the workflow that will be used for the call. To use a transient workflow, use `workflow` instead.\n\nTo start a call with:\n- Assistant, use `assistant` or `assistantId`\n- Squad, use `squad` or `squadId`\n- Workflow, use `workflow` or `workflowId`" + "description": "This is the unique identifier for the tool." }, - "workflow": { - "description": "This is a workflow that will be used for the call. To use an existing workflow, use `workflowId` instead.\n\nTo start a call with:\n- Assistant, use `assistant` or `assistantId`\n- Squad, use `squad` or `squadId`\n- Workflow, use `workflow` or `workflowId`", + "orgId": { + "type": "string", + "description": "This is the unique identifier for the organization that this tool belongs to." + }, + "createdAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the tool was created." + }, + "updatedAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the tool was last updated." + }, + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", "allOf": [ { - "$ref": "#/components/schemas/CreateWorkflowDTO" + "$ref": "#/components/schemas/ToolRejectionPlan" } ] }, - "workflowOverrides": { - "description": "These are the overrides for the `workflow` or `workflowId`'s settings and template variables.", + "function": { + "description": "This is the function definition of the tool.\n\nFor the Code tool, this defines the name, description, and parameters that the model\nwill use to understand when and how to call this tool.", "allOf": [ { - "$ref": "#/components/schemas/WorkflowOverrides" + "$ref": "#/components/schemas/OpenAIFunction" } ] } - } + }, + "required": [ + "type", + "code", + "id", + "orgId", + "createdAt", + "updatedAt" + ] }, - "UpdateCallDTO": { + "DtmfTool": { "type": "object", "properties": { - "name": { + "latestVersion": { "type": "string", - "description": "This is the name of the call. This is just for your own reference.", - "maxLength": 40 - } - } - }, - "DeveloperMessage": { - "type": "object", - "properties": { - "role": { + "nullable": true + }, + "messages": { + "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" + }, + { + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] + } + }, + "type": { "type": "string", - "description": "This is the role of the message author", - "default": "developer", "enum": [ - "developer" - ] + "dtmf" + ], + "description": "The type of tool. \"dtmf\" for DTMF tool." }, - "content": { + "sipInfoDtmfEnabled": { + "type": "boolean", + "description": "This enables sending DTMF tones via SIP INFO messages instead of RFC 2833 (RTP events). When enabled, DTMF digits will be sent using the SIP INFO method, which can be more reliable in some network configurations. Only relevant when using the `vapi.sip` transport.", + "default": false + }, + "id": { "type": "string", - "description": "This is the content of the developer message", - "maxLength": 10000 + "description": "This is the unique identifier for the tool." }, - "name": { + "orgId": { "type": "string", - "description": "This is an optional name for the participant", - "maxLength": 40 + "description": "This is the unique identifier for the organization that this tool belongs to." }, - "metadata": { - "type": "object", - "description": "This is an optional metadata for the message" + "createdAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the tool was created." + }, + "updatedAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the tool was last updated." + }, + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "allOf": [ + { + "$ref": "#/components/schemas/ToolRejectionPlan" + } + ] } }, "required": [ - "role", - "content" + "type", + "id", + "orgId", + "createdAt", + "updatedAt" ] }, - "SystemMessage": { + "EndCallTool": { "type": "object", "properties": { - "role": { + "latestVersion": { "type": "string", - "description": "The role of the system in the conversation." + "nullable": true }, - "message": { + "messages": { + "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" + }, + { + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] + } + }, + "type": { "type": "string", - "description": "The message content from the system." + "enum": [ + "endCall" + ], + "description": "The type of tool. \"endCall\" for End Call tool." }, - "time": { - "type": "number", - "description": "The timestamp when the message was sent." + "id": { + "type": "string", + "description": "This is the unique identifier for the tool." }, - "secondsFromStart": { - "type": "number", - "description": "The number of seconds from the start of the conversation." + "orgId": { + "type": "string", + "description": "This is the unique identifier for the organization that this tool belongs to." + }, + "createdAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the tool was created." + }, + "updatedAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the tool was last updated." + }, + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "allOf": [ + { + "$ref": "#/components/schemas/ToolRejectionPlan" + } + ] } }, "required": [ - "role", - "message", - "time", - "secondsFromStart" + "type", + "id", + "orgId", + "createdAt", + "updatedAt" ] }, - "UserMessage": { + "FunctionTool": { "type": "object", "properties": { - "role": { - "type": "string", - "description": "The role of the user in the conversation." - }, - "message": { + "latestVersion": { "type": "string", - "description": "The message content from the user." + "nullable": true }, - "time": { - "type": "number", - "description": "The timestamp when the message was sent." + "messages": { + "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" + }, + { + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] + } }, - "endTime": { - "type": "number", - "description": "The timestamp when the message ended." + "type": { + "type": "string", + "enum": [ + "function" + ], + "description": "The type of tool. \"function\" for Function tool." }, - "secondsFromStart": { - "type": "number", - "description": "The number of seconds from the start of the conversation." + "async": { + "type": "boolean", + "example": false, + "description": "This determines if the tool is async.\n\n If async, the assistant will move forward without waiting for your server to respond. This is useful if you just want to trigger something on your server.\n\n If sync, the assistant will wait for your server to respond. This is useful if want assistant to respond with the result from your server.\n\n Defaults to synchronous (`false`)." }, - "duration": { - "type": "number", - "description": "The duration of the message in seconds." + "server": { + "description": "\n This is the server where a `tool-calls` webhook will be sent.\n\n Notes:\n - Webhook is sent to this server when a tool call is made.\n - Webhook contains the call, assistant, and phone number objects.\n - Webhook contains the variables set on the assistant.\n - Webhook is sent to the first available URL in this order: {{tool.server.url}}, {{assistant.server.url}}, {{phoneNumber.server.url}}, {{org.server.url}}.\n - Webhook expects a response with tool call result.", + "allOf": [ + { + "$ref": "#/components/schemas/Server" + } + ] }, - "isFiltered": { - "type": "boolean", - "description": "Indicates if the message was filtered for security reasons." + "variableExtractionPlan": { + "description": "Plan to extract variables from the tool response", + "allOf": [ + { + "$ref": "#/components/schemas/VariableExtractionPlan" + } + ] }, - "detectedThreats": { - "description": "List of detected security threats if the message was filtered.", + "parameters": { + "description": "Static key-value pairs merged into the request body. Values support Liquid templates.", "type": "array", "items": { - "type": "string" + "$ref": "#/components/schemas/ToolParameter" } }, - "originalMessage": { + "id": { "type": "string", - "description": "The original message before filtering (only included if content was filtered)." + "description": "This is the unique identifier for the tool." + }, + "orgId": { + "type": "string", + "description": "This is the unique identifier for the organization that this tool belongs to." + }, + "createdAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the tool was created." + }, + "updatedAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the tool was last updated." + }, + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "allOf": [ + { + "$ref": "#/components/schemas/ToolRejectionPlan" + } + ] + }, + "function": { + "description": "This is the function definition of the tool.", + "allOf": [ + { + "$ref": "#/components/schemas/OpenAIFunction" + } + ] } }, "required": [ - "role", - "message", - "time", - "endTime", - "secondsFromStart" + "type", + "id", + "orgId", + "createdAt", + "updatedAt" ] }, - "ToolCallFunction": { + "KnowledgeBaseToolFunction": { "type": "object", "properties": { - "arguments": { + "name": { "type": "string", - "description": "This is the arguments to call the function with" + "description": "This is the the name of the function to be called.\n\nMust be a-z, A-Z, 0-9, or contain underscores and dashes, with a maximum length of 64.", + "maxLength": 64, + "pattern": "/^[a-zA-Z0-9_-]{1,64}$/" }, - "name": { + "strict": { + "type": "boolean", + "description": "This is a boolean that controls whether to enable strict schema adherence when generating the function call. If set to true, the model will follow the exact schema defined in the parameters field. Only a subset of JSON Schema is supported when strict is true. Learn more about Structured Outputs in the [OpenAI guide](https://openai.com/index/introducing-structured-outputs-in-the-api/).\n\n@default false", + "default": false + }, + "description": { "type": "string", - "description": "This is the name of the function to call", - "maxLength": 40 + "description": "This is the description of what the function does, used by the AI to choose when and how to call the function." + }, + "parameters": { + "description": "These are the parameters the functions accepts, described as a JSON Schema object.\n\nSee the [OpenAI guide](https://platform.openai.com/docs/guides/function-calling) for examples, and the [JSON Schema reference](https://json-schema.org/understanding-json-schema) for documentation about the format.\n\nOmitting parameters defines a function with an empty parameter list.", + "allOf": [ + { + "$ref": "#/components/schemas/OpenAIFunctionParameters" + } + ] } }, "required": [ - "arguments", - "name" + "name", + "description", + "parameters" ] }, - "ToolCall": { + "KnowledgeBaseTool": { "type": "object", "properties": { - "id": { + "latestVersion": { "type": "string", - "description": "This is the ID of the tool call" + "nullable": true + }, + "messages": { + "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" + }, + { + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] + } }, "type": { "type": "string", - "description": "This is the type of tool" + "enum": [ + "knowledgeBase" + ], + "description": "A Vapi-hosted knowledge base retrieval tool." + }, + "knowledgeBaseId": { + "type": "string", + "nullable": true, + "format": "uuid", + "description": "The knowledge base this tool searches. At most one search tool references a knowledge base. Deleting the base also deletes its generated tool; null references are retained only for backward compatibility and are inert." + }, + "function": { + "$ref": "#/components/schemas/KnowledgeBaseToolFunction" + }, + "id": { + "type": "string", + "description": "This is the unique identifier for the tool." + }, + "orgId": { + "type": "string", + "description": "This is the unique identifier for the organization that this tool belongs to." + }, + "createdAt": { + "type": "string", + "description": "This is the ISO 8601 date-time string of when the tool was created.", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "description": "This is the ISO 8601 date-time string of when the tool was last updated.", + "format": "date-time" }, - "function": { - "description": "This is the function that was called", + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", "allOf": [ { - "$ref": "#/components/schemas/ToolCallFunction" + "$ref": "#/components/schemas/ToolRejectionPlan" } ] } }, "required": [ - "id", "type", - "function" + "knowledgeBaseId", + "function", + "id", + "orgId", + "createdAt", + "updatedAt" ] }, - "AssistantMessage": { + "GhlTool": { "type": "object", "properties": { - "role": { - "type": "string", - "description": "This is the role of the message author", - "default": "assistant", - "enum": [ - "assistant" - ] - }, - "content": { - "type": "string", - "description": "This is the content of the assistant message", - "maxLength": 10000 - }, - "refusal": { + "latestVersion": { "type": "string", - "description": "This is the refusal message generated by the model", - "maxLength": 10000 + "nullable": true }, - "tool_calls": { - "description": "This is the tool calls generated by the model", + "messages": { "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", "items": { - "$ref": "#/components/schemas/ToolCall" + "oneOf": [ + { + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" + }, + { + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] } }, - "name": { + "type": { "type": "string", - "description": "This is an optional name for the participant", - "maxLength": 40 + "enum": [ + "ghl" + ], + "description": "The type of tool. \"ghl\" for GHL tool." }, - "metadata": { - "type": "object", - "description": "This is an optional metadata for the message" - } - }, - "required": [ - "role" - ] - }, - "ToolMessage": { - "type": "object", - "properties": { - "role": { + "id": { "type": "string", - "description": "This is the role of the message author", - "default": "tool", - "enum": [ - "tool" - ] + "description": "This is the unique identifier for the tool." }, - "content": { + "orgId": { "type": "string", - "description": "This is the content of the tool message", - "maxLength": 10000 + "description": "This is the unique identifier for the organization that this tool belongs to." }, - "tool_call_id": { + "createdAt": { + "format": "date-time", "type": "string", - "description": "This is the ID of the tool call this message is responding to" + "description": "This is the ISO 8601 date-time string of when the tool was created." }, - "name": { + "updatedAt": { + "format": "date-time", "type": "string", - "description": "This is an optional name for the participant", - "maxLength": 40 + "description": "This is the ISO 8601 date-time string of when the tool was last updated." + }, + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "allOf": [ + { + "$ref": "#/components/schemas/ToolRejectionPlan" + } + ] }, "metadata": { - "type": "object", - "description": "This is an optional metadata for the message" + "$ref": "#/components/schemas/GhlToolMetadata" } }, "required": [ - "role", - "content", - "tool_call_id" + "type", + "id", + "orgId", + "createdAt", + "updatedAt", + "metadata" ] }, - "FunctionCall": { + "MakeTool": { "type": "object", "properties": { - "arguments": { + "latestVersion": { "type": "string", - "description": "This is the arguments to call the function with" + "nullable": true }, - "name": { - "type": "string", - "description": "This is the name of the function to call", - "maxLength": 40 - } - }, - "required": [ - "arguments", - "name" - ] - }, - "Chat": { - "type": "object", - "properties": { - "assistantId": { + "messages": { + "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" + }, + { + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] + } + }, + "type": { "type": "string", - "description": "This is the assistant that will be used for the chat. To use an existing assistant, use `assistantId` instead." + "enum": [ + "make" + ], + "description": "The type of tool. \"make\" for Make tool." }, - "assistant": { - "description": "This is the assistant that will be used for the chat. To use an existing assistant, use `assistantId` instead.", - "allOf": [ - { - "$ref": "#/components/schemas/CreateAssistantDTO" - } - ] + "id": { + "type": "string", + "description": "This is the unique identifier for the tool." }, - "assistantOverrides": { - "description": "These are the variable values that will be used to replace template variables in the assistant messages.\nOnly variable substitution is supported in chat contexts - other assistant properties cannot be overridden.", - "allOf": [ - { - "$ref": "#/components/schemas/AssistantOverrides" - } - ] + "orgId": { + "type": "string", + "description": "This is the unique identifier for the organization that this tool belongs to." }, - "name": { + "createdAt": { + "format": "date-time", "type": "string", - "description": "This is the name of the chat. This is just for your own reference.", - "maxLength": 40 + "description": "This is the ISO 8601 date-time string of when the tool was created." }, - "sessionId": { + "updatedAt": { + "format": "date-time", "type": "string", - "description": "This is the ID of the session that will be used for the chat.\nMutually exclusive with previousChatId." + "description": "This is the ISO 8601 date-time string of when the tool was last updated." }, - "input": { - "description": "This is the input text for the chat.\nCan be a string or an array of chat messages.", - "oneOf": [ - { - "type": "string", - "title": "String" - }, + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "allOf": [ { - "type": "array", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/SystemMessage", - "title": "SystemMessage" - }, - { - "$ref": "#/components/schemas/UserMessage", - "title": "UserMessage" - }, - { - "$ref": "#/components/schemas/AssistantMessage", - "title": "AssistantMessage" - }, - { - "$ref": "#/components/schemas/ToolMessage", - "title": "ToolMessage" - }, - { - "$ref": "#/components/schemas/DeveloperMessage", - "title": "DeveloperMessage" - } - ] - }, - "title": "MessageArray" + "$ref": "#/components/schemas/ToolRejectionPlan" } - ], - "examples": [ - "Hello, how can you help me?", - [ - { - "role": "user", - "content": "Hello, how can you help me?" - } - ] ] }, - "stream": { - "type": "boolean", - "description": "This is a flag that determines whether the response should be streamed.\nWhen true, the response will be sent as chunks of text.", - "default": false - }, - "previousChatId": { - "type": "string", - "description": "This is the ID of the chat that will be used as context for the new chat.\nThe messages from the previous chat will be used as context.\nMutually exclusive with sessionId." - }, - "id": { - "type": "string", - "description": "This is the unique identifier for the chat." - }, - "orgId": { + "metadata": { + "$ref": "#/components/schemas/MakeToolMetadata" + } + }, + "required": [ + "type", + "id", + "orgId", + "createdAt", + "updatedAt", + "metadata" + ] + }, + "TransferCallTool": { + "type": "object", + "properties": { + "latestVersion": { "type": "string", - "description": "This is the unique identifier for the org that this chat belongs to." + "nullable": true }, "messages": { "type": "array", - "description": "This is an array of messages used as context for the chat.\nUsed to provide message history for multi-turn conversations.", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", "items": { "oneOf": [ { - "$ref": "#/components/schemas/SystemMessage", - "title": "SystemMessage" - }, - { - "$ref": "#/components/schemas/UserMessage", - "title": "UserMessage" + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" }, { - "$ref": "#/components/schemas/AssistantMessage", - "title": "AssistantMessage" + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" }, { - "$ref": "#/components/schemas/ToolMessage", - "title": "ToolMessage" + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" }, { - "$ref": "#/components/schemas/DeveloperMessage", - "title": "DeveloperMessage" + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" } ] } }, - "output": { + "type": { + "type": "string", + "enum": [ + "transferCall" + ] + }, + "destinations": { "type": "array", - "description": "This is the output messages generated by the system in response to the input.", + "description": "These are the destinations that the call can be transferred to. If no destinations are provided, server.url will be used to get the transfer destination once the tool is called.", "items": { "oneOf": [ { - "$ref": "#/components/schemas/SystemMessage", - "title": "SystemMessage" - }, - { - "$ref": "#/components/schemas/UserMessage", - "title": "UserMessage" - }, - { - "$ref": "#/components/schemas/AssistantMessage", - "title": "AssistantMessage" + "$ref": "#/components/schemas/TransferDestinationAssistant", + "title": "Assistant" }, { - "$ref": "#/components/schemas/ToolMessage", - "title": "ToolMessage" + "$ref": "#/components/schemas/TransferDestinationNumber", + "title": "Number" }, { - "$ref": "#/components/schemas/DeveloperMessage", - "title": "DeveloperMessage" + "$ref": "#/components/schemas/TransferDestinationSip", + "title": "Sip" } ] } }, + "id": { + "type": "string", + "description": "This is the unique identifier for the tool." + }, + "orgId": { + "type": "string", + "description": "This is the unique identifier for the organization that this tool belongs to." + }, "createdAt": { "format": "date-time", "type": "string", - "description": "This is the ISO 8601 date-time string of when the chat was created." + "description": "This is the ISO 8601 date-time string of when the tool was created." }, "updatedAt": { "format": "date-time", "type": "string", - "description": "This is the ISO 8601 date-time string of when the chat was last updated." - }, - "costs": { - "type": "array", - "description": "These are the costs of individual components of the chat in USD.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ModelCost", - "title": "ModelCost" - }, - { - "$ref": "#/components/schemas/ChatCost", - "title": "ChatCost" - } - ] - } + "description": "This is the ISO 8601 date-time string of when the tool was last updated." }, - "cost": { - "type": "number", - "description": "This is the cost of the chat in USD." + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "allOf": [ + { + "$ref": "#/components/schemas/ToolRejectionPlan" + } + ] } }, "required": [ + "type", "id", "orgId", "createdAt", "updatedAt" ] }, - "CreateChatDTO": { + "HandoffTool": { "type": "object", "properties": { - "assistantId": { - "type": "string", - "description": "This is the assistant that will be used for the chat. To use an existing assistant, use `assistantId` instead." - }, - "assistant": { - "description": "This is the assistant that will be used for the chat. To use an existing assistant, use `assistantId` instead.", - "allOf": [ - { - "$ref": "#/components/schemas/CreateAssistantDTO" - } - ] - }, - "assistantOverrides": { - "description": "These are the variable values that will be used to replace template variables in the assistant messages.\nOnly variable substitution is supported in chat contexts - other assistant properties cannot be overridden.", - "allOf": [ - { - "$ref": "#/components/schemas/AssistantOverrides" - } - ] - }, - "name": { - "type": "string", - "description": "This is the name of the chat. This is just for your own reference.", - "maxLength": 40 - }, - "sessionId": { + "latestVersion": { "type": "string", - "description": "This is the ID of the session that will be used for the chat.\nMutually exclusive with previousChatId." + "nullable": true }, - "input": { - "description": "This is the input text for the chat.\nCan be a string or an array of chat messages.\nThis field is REQUIRED for chat creation.", - "oneOf": [ - { - "type": "string", - "title": "String" - }, - { - "type": "array", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/SystemMessage", - "title": "SystemMessage" - }, - { - "$ref": "#/components/schemas/UserMessage", - "title": "UserMessage" - }, - { - "$ref": "#/components/schemas/AssistantMessage", - "title": "AssistantMessage" - }, - { - "$ref": "#/components/schemas/ToolMessage", - "title": "ToolMessage" - }, - { - "$ref": "#/components/schemas/DeveloperMessage", - "title": "DeveloperMessage" - } - ] + "messages": { + "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" }, - "title": "MessageArray" - } - ], - "examples": [ - "Hello, how can you help me?", - [ { - "role": "user", - "content": "Hello, how can you help me?" + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" } ] - ] - }, - "stream": { - "type": "boolean", - "description": "This is a flag that determines whether the response should be streamed.\nWhen true, the response will be sent as chunks of text.", - "default": false - }, - "previousChatId": { - "type": "string", - "description": "This is the ID of the chat that will be used as context for the new chat.\nThe messages from the previous chat will be used as context.\nMutually exclusive with sessionId." - } - }, - "required": [ - "input" - ] - }, - "GetChatPaginatedDTO": { - "type": "object", - "properties": { - "assistantId": { - "type": "string", - "description": "This is the unique identifier for the assistant that will be used for the chat." - }, - "workflowId": { - "type": "string", - "description": "This is the unique identifier for the workflow that will be used for the chat." - }, - "sessionId": { - "type": "string", - "description": "This is the unique identifier for the session that will be used for the chat." - }, - "page": { - "type": "number", - "description": "This is the page number to return. Defaults to 1.", - "minimum": 1 + } }, - "sortOrder": { + "type": { "type": "string", - "description": "This is the sort order for pagination. Defaults to 'DESC'.", + "description": "This is the type of the tool.\nWhen you're using handoff tool, we recommend adding this to your system prompt\n---\n# System context\n\nYou are part of a multi-agent system designed to make agent coordination and execution easy. Agents uses two primary abstraction: **Agents** and **Handoffs**. An agent encompasses instructions and tools and can hand off a conversation to another agent when appropriate. Handoffs are achieved by calling a handoff function, generally named `handoff_to_`. Handoffs between agents are handled seamlessly in the background; do not mention or draw attention to these handoffs in your conversation with the user.\n\n# Agent context\n\n{put your agent system prompt here}\n---", "enum": [ - "ASC", - "DESC" + "handoff" ] }, - "limit": { - "type": "number", - "description": "This is the maximum number of items to return. Defaults to 100.", - "minimum": 0, - "maximum": 1000 - }, - "createdAtGt": { - "format": "date-time", + "defaultResult": { "type": "string", - "description": "This will return items where the createdAt is greater than the specified value." + "description": "This is the default local tool result message used when no runtime handoff result override is returned." }, - "createdAtLt": { - "format": "date-time", - "type": "string", - "description": "This will return items where the createdAt is less than the specified value." + "destinations": { + "type": "array", + "description": "These are the destinations that the call can be handed off to.\n\nUsage:\n1. Single destination\n\nUse `assistantId` to handoff the call to a saved assistant, or `assistantName` to handoff the call to an assistant in the same squad.\n\n```json\n{\n \"tools\": [\n {\n \"type\": \"handoff\",\n \"destinations\": [\n {\n \"type\": \"assistant\",\n \"assistantId\": \"assistant-123\", // or \"assistantName\": \"Assistant123\"\n \"description\": \"customer wants to be handed off to assistant-123\",\n \"contextEngineeringPlan\": {\n \"type\": \"all\"\n }\n }\n ],\n }\n ]\n}\n```\n\n2. Multiple destinations\n\n2.1. Multiple Tools, Each With One Destination (OpenAI recommended)\n\n```json\n{\n \"tools\": [\n {\n \"type\": \"handoff\",\n \"destinations\": [\n {\n \"type\": \"assistant\",\n \"assistantId\": \"assistant-123\",\n \"description\": \"customer wants to be handed off to assistant-123\",\n \"contextEngineeringPlan\": {\n \"type\": \"all\"\n }\n },\n ],\n },\n {\n \"type\": \"handoff\",\n \"destinations\": [\n {\n \"type\": \"assistant\",\n \"assistantId\": \"assistant-456\",\n \"description\": \"customer wants to be handed off to assistant-456\",\n \"contextEngineeringPlan\": {\n \"type\": \"all\"\n }\n }\n ],\n }\n ]\n}\n```\n\n2.2. One Tool, Multiple Destinations (Anthropic recommended)\n\n```json\n{\n \"tools\": [\n {\n \"type\": \"handoff\",\n \"destinations\": [\n {\n \"type\": \"assistant\",\n \"assistantId\": \"assistant-123\",\n \"description\": \"customer wants to be handed off to assistant-123\",\n \"contextEngineeringPlan\": {\n \"type\": \"all\"\n }\n },\n {\n \"type\": \"assistant\",\n \"assistantId\": \"assistant-456\",\n \"description\": \"customer wants to be handed off to assistant-456\",\n \"contextEngineeringPlan\": {\n \"type\": \"all\"\n }\n }\n ],\n }\n ]\n}\n```\n\n3. Dynamic destination\n\n3.1 To determine the destination dynamically, supply a `dynamic` handoff destination type and a `server` object.\n VAPI will send a handoff-destination-request webhook to the `server.url`.\n The response from the server will be used as the destination (if valid).\n\n```json\n{\n \"tools\": [\n {\n \"type\": \"handoff\",\n \"destinations\": [\n {\n \"type\": \"dynamic\",\n \"server\": {\n \"url\": \"https://example.com\"\n }\n }\n ],\n }\n ]\n}\n```\n\n3.2. To pass custom parameters to the server, you can use the `function` object.\n\n```json\n{\n \"tools\": [\n {\n \"type\": \"handoff\",\n \"destinations\": [\n {\n \"type\": \"dynamic\",\n \"server\": {\n \"url\": \"https://example.com\"\n },\n }\n ],\n \"function\": {\n \"name\": \"handoff\",\n \"description\": \"Call this function when the customer is ready to be handed off to the next assistant\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"destination\": {\n \"type\": \"string\",\n \"description\": \"Use dynamic when customer is ready to be handed off to the next assistant\",\n \"enum\": [\"dynamic\"]\n },\n \"customerAreaCode\": {\n \"type\": \"number\",\n \"description\": \"Area code of the customer\"\n },\n \"customerIntent\": {\n \"type\": \"string\",\n \"enum\": [\"new-customer\", \"existing-customer\"],\n \"description\": \"Use new-customer when customer is a new customer, existing-customer when customer is an existing customer\"\n },\n \"customerSentiment\": {\n \"type\": \"string\",\n \"enum\": [\"positive\", \"negative\", \"neutral\"],\n \"description\": \"Use positive when customer is happy, negative when customer is unhappy, neutral when customer is neutral\"\n }\n }\n }\n }\n }\n ]\n}\n```\n\nThe properties `customerAreaCode`, `customerIntent`, and `customerSentiment` will be passed to the server in the webhook request body.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/HandoffDestinationAssistant", + "title": "Assistant" + }, + { + "$ref": "#/components/schemas/HandoffDestinationDynamic", + "title": "Dynamic" + }, + { + "$ref": "#/components/schemas/HandoffDestinationSquad", + "title": "Squad" + } + ] + } }, - "createdAtGe": { - "format": "date-time", + "id": { "type": "string", - "description": "This will return items where the createdAt is greater than or equal to the specified value." + "description": "This is the unique identifier for the tool." }, - "createdAtLe": { - "format": "date-time", + "orgId": { "type": "string", - "description": "This will return items where the createdAt is less than or equal to the specified value." + "description": "This is the unique identifier for the organization that this tool belongs to." }, - "updatedAtGt": { + "createdAt": { "format": "date-time", "type": "string", - "description": "This will return items where the updatedAt is greater than the specified value." + "description": "This is the ISO 8601 date-time string of when the tool was created." }, - "updatedAtLt": { + "updatedAt": { "format": "date-time", "type": "string", - "description": "This will return items where the updatedAt is less than the specified value." + "description": "This is the ISO 8601 date-time string of when the tool was last updated." }, - "updatedAtGe": { - "format": "date-time", - "type": "string", - "description": "This will return items where the updatedAt is greater than or equal to the specified value." + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "allOf": [ + { + "$ref": "#/components/schemas/ToolRejectionPlan" + } + ] }, - "updatedAtLe": { - "format": "date-time", - "type": "string", - "description": "This will return items where the updatedAt is less than or equal to the specified value." + "function": { + "description": "This is the optional function definition that will be passed to the LLM.\nIf this is not defined, we will construct this based on the other properties.\n\nFor example, given the following tools definition:\n```json\n{\n \"tools\": [\n {\n \"type\": \"handoff\",\n \"destinations\": [\n {\n \"type\": \"assistant\",\n \"assistantId\": \"assistant-123\",\n \"description\": \"customer wants to be handed off to assistant-123\",\n \"contextEngineeringPlan\": {\n \"type\": \"all\"\n }\n },\n {\n \"type\": \"assistant\",\n \"assistantId\": \"assistant-456\",\n \"description\": \"customer wants to be handed off to assistant-456\",\n \"contextEngineeringPlan\": {\n \"type\": \"all\"\n }\n }\n ],\n }\n ]\n}\n```\n\nWe will construct the following function definition:\n```json\n{\n \"function\": {\n \"name\": \"handoff_to_assistant-123\",\n \"description\": \"\n Use this function to handoff the call to the next assistant.\n Only use it when instructions explicitly ask you to use the handoff_to_assistant function.\n DO NOT call this function unless you are instructed to do so.\n Here are the destinations you can handoff the call to:\n 1. assistant-123. When: customer wants to be handed off to assistant-123\n 2. assistant-456. When: customer wants to be handed off to assistant-456\n \",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"destination\": {\n \"type\": \"string\",\n \"description\": \"Options: assistant-123 (customer wants to be handed off to assistant-123), assistant-456 (customer wants to be handed off to assistant-456)\",\n \"enum\": [\"assistant-123\", \"assistant-456\"]\n },\n },\n \"required\": [\"destination\"]\n }\n }\n}\n```\n\nTo override this function, please provide an OpenAI function definition and refer to it in the system prompt.\nYou may override parts of the function definition (i.e. you may only want to change the function name for your prompt).\nIf you choose to override the function parameters, it must include `destination` as a required parameter, and it must evaluate to either an assistantId, assistantName, or a the string literal `dynamic`.\n\nTo pass custom parameters to the server in a dynamic handoff, you can use the function parameters, with `dynamic` as the destination.\n```json\n{\n \"function\": {\n \"name\": \"dynamic_handoff\",\n \"description\": \"\n Call this function when the customer is ready to be handed off to the next assistant\n \",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"destination\": {\n \"type\": \"string\",\n \"enum\": [\"dynamic\"]\n },\n \"customerAreaCode\": {\n \"type\": \"number\",\n \"description\": \"Area code of the customer\"\n },\n \"customerIntent\": {\n \"type\": \"string\",\n \"enum\": [\"new-customer\", \"existing-customer\"],\n \"description\": \"Use new-customer when customer is a new customer, existing-customer when customer is an existing customer\"\n },\n \"customerSentiment\": {\n \"type\": \"string\",\n \"enum\": [\"positive\", \"negative\", \"neutral\"],\n \"description\": \"Use positive when customer is happy, negative when customer is unhappy, neutral when customer is neutral\"\n }\n },\n \"required\": [\"destination\", \"customerAreaCode\", \"customerIntent\", \"customerSentiment\"]\n }\n }\n}\n```", + "allOf": [ + { + "$ref": "#/components/schemas/OpenAIFunction" + } + ] } - } + }, + "required": [ + "type", + "id", + "orgId", + "createdAt", + "updatedAt" + ] }, - "ChatPaginatedResponse": { + "OutputTool": { "type": "object", "properties": { - "results": { + "latestVersion": { + "type": "string", + "nullable": true + }, + "messages": { "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", "items": { - "$ref": "#/components/schemas/Chat" + "oneOf": [ + { + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" + }, + { + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] } }, - "metadata": { - "$ref": "#/components/schemas/PaginationMeta" - } - }, - "required": [ - "results", - "metadata" - ] - }, - "CreateChatStreamResponse": { - "type": "object", - "properties": { + "type": { + "type": "string", + "enum": [ + "output" + ], + "description": "The type of tool. \"output\" for Output tool." + }, "id": { "type": "string", - "description": "This is the unique identifier for the streaming response." + "description": "This is the unique identifier for the tool." }, - "sessionId": { + "orgId": { "type": "string", - "description": "This is the ID of the session that will be used for the chat.\nHelps track conversation context across multiple messages." + "description": "This is the unique identifier for the organization that this tool belongs to." }, - "path": { + "createdAt": { + "format": "date-time", "type": "string", - "description": "This is the path to the content being updated.\nFormat: `chat.output[{contentIndex}].content` where contentIndex identifies the specific content item.", - "example": "chat.output[0].content" + "description": "This is the ISO 8601 date-time string of when the tool was created." }, - "delta": { + "updatedAt": { + "format": "date-time", "type": "string", - "description": "This is the incremental content chunk being streamed." + "description": "This is the ISO 8601 date-time string of when the tool was last updated." + }, + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "allOf": [ + { + "$ref": "#/components/schemas/ToolRejectionPlan" + } + ] } }, "required": [ + "type", "id", - "path", - "delta" + "orgId", + "createdAt", + "updatedAt" ] }, - "OpenAIResponsesRequest": { + "BashTool": { "type": "object", "properties": { - "assistantId": { + "latestVersion": { "type": "string", - "description": "This is the assistant that will be used for the chat. To use an existing assistant, use `assistantId` instead." + "nullable": true }, - "assistant": { - "description": "This is the assistant that will be used for the chat. To use an existing assistant, use `assistantId` instead.", - "allOf": [ - { - "$ref": "#/components/schemas/CreateAssistantDTO" - } - ] + "messages": { + "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" + }, + { + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] + } }, - "assistantOverrides": { - "description": "These are the variable values that will be used to replace template variables in the assistant messages.\nOnly variable substitution is supported in chat contexts - other assistant properties cannot be overridden.", + "type": { + "type": "string", + "enum": [ + "bash" + ], + "description": "The type of tool. \"bash\" for Bash tool." + }, + "subType": { + "type": "string", + "enum": [ + "bash_20241022" + ], + "description": "The sub type of tool." + }, + "server": { + "description": "\n This is the server where a `tool-calls` webhook will be sent.\n\n Notes:\n - Webhook is sent to this server when a tool call is made.\n - Webhook contains the call, assistant, and phone number objects.\n - Webhook contains the variables set on the assistant.\n - Webhook is sent to the first available URL in this order: {{tool.server.url}}, {{assistant.server.url}}, {{phoneNumber.server.url}}, {{org.server.url}}.\n - Webhook expects a response with tool call result.", "allOf": [ { - "$ref": "#/components/schemas/AssistantOverrides" + "$ref": "#/components/schemas/Server" } ] }, - "name": { + "id": { "type": "string", - "description": "This is the name of the chat. This is just for your own reference.", - "maxLength": 40 + "description": "This is the unique identifier for the tool." }, - "sessionId": { + "orgId": { "type": "string", - "description": "This is the ID of the session that will be used for the chat.\nMutually exclusive with previousChatId." + "description": "This is the unique identifier for the organization that this tool belongs to." }, - "input": { - "description": "This is the input text for the chat.\nCan be a string or an array of chat messages.\nThis field is REQUIRED for chat creation.", - "oneOf": [ - { - "type": "string", - "title": "String" - }, + "createdAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the tool was created." + }, + "updatedAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the tool was last updated." + }, + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "allOf": [ { - "type": "array", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/SystemMessage", - "title": "SystemMessage" - }, - { - "$ref": "#/components/schemas/UserMessage", - "title": "UserMessage" - }, - { - "$ref": "#/components/schemas/AssistantMessage", - "title": "AssistantMessage" - }, - { - "$ref": "#/components/schemas/ToolMessage", - "title": "ToolMessage" - }, - { - "$ref": "#/components/schemas/DeveloperMessage", - "title": "DeveloperMessage" - } - ] - }, - "title": "MessageArray" + "$ref": "#/components/schemas/ToolRejectionPlan" } - ], - "examples": [ - "Hello, how can you help me?", - [ - { - "role": "user", - "content": "Hello, how can you help me?" - } - ] ] }, - "stream": { - "type": "boolean", - "description": "Whether to stream the response or not.", - "default": true - }, - "previousChatId": { + "name": { "type": "string", - "description": "This is the ID of the chat that will be used as context for the new chat.\nThe messages from the previous chat will be used as context.\nMutually exclusive with sessionId." + "description": "The name of the tool, fixed to 'bash'", + "default": "bash", + "enum": [ + "bash" + ] } }, "required": [ - "input" + "type", + "subType", + "id", + "orgId", + "createdAt", + "updatedAt", + "name" ] }, - "ChatAssistantOverrides": { + "ComputerTool": { "type": "object", "properties": { - "variableValues": { - "type": "object", - "description": "Variable values for template substitution", - "example": { - "name": "John", - "company": "ACME Corp" + "latestVersion": { + "type": "string", + "nullable": true + }, + "messages": { + "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" + }, + { + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] } - } - } - }, - "CreateWebCustomerDTO": { - "type": "object", - "properties": { - "numberE164CheckEnabled": { - "type": "boolean", - "description": "This is the flag to toggle the E164 check for the `number` field. This is an advanced property which should be used if you know your use case requires it.\n\nUse cases:\n- `false`: To allow non-E164 numbers like `+001234567890`, `1234`, or `abc`. This is useful for dialing out to non-E164 numbers on your SIP trunks.\n- `true` (default): To allow only E164 numbers like `+14155551234`. This is standard for PSTN calls.\n\nIf `false`, the `number` is still required to only contain alphanumeric characters (regex: `/^\\+?[a-zA-Z0-9]+$/`).\n\n@default true (E164 check is enabled)", - "default": true }, - "extension": { + "type": { "type": "string", - "description": "This is the extension that will be dialed after the call is answered.", - "maxLength": 10, - "example": null + "enum": [ + "computer" + ], + "description": "The type of tool. \"computer\" for Computer tool." }, - "assistantOverrides": { - "description": "These are the variable values that will be used to replace template variables in the assistant messages.\nOnly variable substitution is supported in web chat - other assistant properties cannot be overridden.", + "subType": { + "type": "string", + "enum": [ + "computer_20241022" + ], + "description": "The sub type of tool." + }, + "server": { + "description": "\n This is the server where a `tool-calls` webhook will be sent.\n\n Notes:\n - Webhook is sent to this server when a tool call is made.\n - Webhook contains the call, assistant, and phone number objects.\n - Webhook contains the variables set on the assistant.\n - Webhook is sent to the first available URL in this order: {{tool.server.url}}, {{assistant.server.url}}, {{phoneNumber.server.url}}, {{org.server.url}}.\n - Webhook expects a response with tool call result.", "allOf": [ { - "$ref": "#/components/schemas/ChatAssistantOverrides" + "$ref": "#/components/schemas/Server" } ] }, - "number": { + "id": { "type": "string", - "description": "This is the number of the customer.", - "minLength": 3, - "maxLength": 40 + "description": "This is the unique identifier for the tool." }, - "sipUri": { + "orgId": { "type": "string", - "description": "This is the SIP URI of the customer." + "description": "This is the unique identifier for the organization that this tool belongs to." }, - "name": { + "createdAt": { + "format": "date-time", "type": "string", - "description": "This is the name of the customer. This is just for your own reference.\n\nFor SIP inbound calls, this is extracted from the `From` SIP header with format `\"Display Name\" `.", - "maxLength": 40 + "description": "This is the ISO 8601 date-time string of when the tool was created." }, - "email": { + "updatedAt": { + "format": "date-time", "type": "string", - "description": "This is the email of the customer.", - "maxLength": 40 + "description": "This is the ISO 8601 date-time string of when the tool was last updated." }, - "externalId": { + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "allOf": [ + { + "$ref": "#/components/schemas/ToolRejectionPlan" + } + ] + }, + "name": { "type": "string", - "description": "This is the external ID of the customer.", - "maxLength": 40 + "description": "The name of the tool, fixed to 'computer'", + "default": "computer", + "enum": [ + "computer" + ] + }, + "displayWidthPx": { + "type": "number", + "description": "The display width in pixels" + }, + "displayHeightPx": { + "type": "number", + "description": "The display height in pixels" + }, + "displayNumber": { + "type": "number", + "description": "Optional display number" } - } + }, + "required": [ + "type", + "subType", + "id", + "orgId", + "createdAt", + "updatedAt", + "name", + "displayWidthPx", + "displayHeightPx" + ] }, - "CreateWebChatDTO": { + "TextEditorTool": { "type": "object", "properties": { - "assistantId": { + "latestVersion": { "type": "string", - "description": "The assistant ID to use for this chat" + "nullable": true }, - "sessionId": { + "messages": { + "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" + }, + { + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] + } + }, + "type": { "type": "string", - "description": "This is the ID of the session that will be used for the chat.\nIf provided, the conversation will continue from the previous state.\nIf not provided or expired, a new session will be created." + "enum": [ + "textEditor" + ], + "description": "The type of tool. \"textEditor\" for Text Editor tool." }, - "assistantOverrides": { - "description": "These are the variable values that will be used to replace template variables in the assistant messages.\nOnly variable substitution is supported in web chat - other assistant properties cannot be overridden.", - "allOf": [ - { - "$ref": "#/components/schemas/ChatAssistantOverrides" - } - ] + "subType": { + "type": "string", + "enum": [ + "text_editor_20241022" + ], + "description": "The sub type of tool." }, - "customer": { - "description": "This is the customer information for the chat.\nUsed to automatically manage sessions for repeat customers.", + "server": { + "description": "\n This is the server where a `tool-calls` webhook will be sent.\n\n Notes:\n - Webhook is sent to this server when a tool call is made.\n - Webhook contains the call, assistant, and phone number objects.\n - Webhook contains the variables set on the assistant.\n - Webhook is sent to the first available URL in this order: {{tool.server.url}}, {{assistant.server.url}}, {{phoneNumber.server.url}}, {{org.server.url}}.\n - Webhook expects a response with tool call result.", "allOf": [ { - "$ref": "#/components/schemas/CreateWebCustomerDTO" + "$ref": "#/components/schemas/Server" } ] }, - "input": { - "description": "This is the input text for the chat.\nCan be a string or an array of chat messages.", - "oneOf": [ - { - "type": "string", - "title": "String" - }, - { - "type": "array", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/SystemMessage", - "title": "SystemMessage" - }, - { - "$ref": "#/components/schemas/UserMessage", - "title": "UserMessage" - }, - { - "$ref": "#/components/schemas/AssistantMessage", - "title": "AssistantMessage" - }, - { - "$ref": "#/components/schemas/ToolMessage", - "title": "ToolMessage" - }, - { - "$ref": "#/components/schemas/DeveloperMessage", - "title": "DeveloperMessage" - } - ] - }, - "title": "MessageArray" - } - ], - "examples": [ - "Hello, how can you help me?", - [ - { - "role": "user", - "content": "Hello, how can you help me?" - } - ] + "id": { + "type": "string", + "description": "This is the unique identifier for the tool." + }, + "orgId": { + "type": "string", + "description": "This is the unique identifier for the organization that this tool belongs to." + }, + "createdAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the tool was created." + }, + "updatedAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the tool was last updated." + }, + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "allOf": [ + { + "$ref": "#/components/schemas/ToolRejectionPlan" + } ] }, - "stream": { - "type": "boolean", - "description": "This is a flag that determines whether the response should be streamed.\nWhen true, the response will be sent as chunks of text.", - "default": false + "name": { + "type": "string", + "description": "The name of the tool, fixed to 'str_replace_editor'", + "default": "str_replace_editor", + "enum": [ + "str_replace_editor" + ] } }, "required": [ - "assistantId", - "input" + "type", + "subType", + "id", + "orgId", + "createdAt", + "updatedAt", + "name" ] }, - "WebChat": { + "QueryTool": { "type": "object", "properties": { - "id": { - "type": "string", - "description": "This is the unique identifier for the chat." - }, - "sessionId": { + "latestVersion": { "type": "string", - "description": "This is the ID of the session for the chat. Send it in the next chat request to continue the conversation." + "nullable": true }, - "output": { + "messages": { "type": "array", - "description": "This is the output messages generated by the system in response to the input.", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", "items": { "oneOf": [ { - "$ref": "#/components/schemas/SystemMessage", - "title": "SystemMessage" - }, - { - "$ref": "#/components/schemas/UserMessage", - "title": "UserMessage" + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" }, { - "$ref": "#/components/schemas/AssistantMessage", - "title": "AssistantMessage" + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" }, { - "$ref": "#/components/schemas/ToolMessage", - "title": "ToolMessage" + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" }, { - "$ref": "#/components/schemas/DeveloperMessage", - "title": "DeveloperMessage" + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" } ] } - } - }, - "required": [ - "id", - "output" - ] - }, - "OpenAIWebChatRequest": { - "type": "object", - "properties": { - "assistantId": { + }, + "type": { "type": "string", - "description": "The assistant ID to use for this chat" + "enum": [ + "query" + ], + "description": "The type of tool. \"query\" for Query tool." }, - "sessionId": { + "knowledgeBases": { + "description": "The knowledge bases to query", + "type": "array", + "items": { + "$ref": "#/components/schemas/KnowledgeBase" + } + }, + "id": { "type": "string", - "description": "This is the ID of the session that will be used for the chat.\nIf provided, the conversation will continue from the previous state.\nIf not provided or expired, a new session will be created." + "description": "This is the unique identifier for the tool." }, - "assistantOverrides": { - "description": "These are the variable values that will be used to replace template variables in the assistant messages.\nOnly variable substitution is supported in web chat - other assistant properties cannot be overridden.", - "allOf": [ - { - "$ref": "#/components/schemas/ChatAssistantOverrides" - } - ] + "orgId": { + "type": "string", + "description": "This is the unique identifier for the organization that this tool belongs to." }, - "customer": { - "description": "This is the customer information for the chat.\nUsed to automatically manage sessions for repeat customers.", - "allOf": [ - { - "$ref": "#/components/schemas/CreateWebCustomerDTO" - } - ] + "createdAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the tool was created." }, - "input": { - "description": "This is the input text for the chat.\nCan be a string or an array of chat messages.", - "oneOf": [ - { - "type": "string", - "title": "String" - }, + "updatedAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the tool was last updated." + }, + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "allOf": [ { - "type": "array", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/SystemMessage", - "title": "SystemMessage" - }, - { - "$ref": "#/components/schemas/UserMessage", - "title": "UserMessage" - }, - { - "$ref": "#/components/schemas/AssistantMessage", - "title": "AssistantMessage" - }, - { - "$ref": "#/components/schemas/ToolMessage", - "title": "ToolMessage" - }, - { - "$ref": "#/components/schemas/DeveloperMessage", - "title": "DeveloperMessage" - } - ] - }, - "title": "MessageArray" + "$ref": "#/components/schemas/ToolRejectionPlan" } - ], - "examples": [ - "Hello, how can you help me?", - [ - { - "role": "user", - "content": "Hello, how can you help me?" - } - ] ] - }, - "stream": { - "type": "boolean", - "description": "Whether to stream the response or not.", - "default": true } }, "required": [ - "assistantId", - "input" + "type", + "id", + "orgId", + "createdAt", + "updatedAt" ] }, - "ResponseOutputText": { + "GoogleCalendarCreateEventTool": { "type": "object", "properties": { - "annotations": { - "default": [], - "description": "Annotations in the text output", + "latestVersion": { + "type": "string", + "nullable": true + }, + "messages": { "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", "items": { - "type": "object" + "oneOf": [ + { + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" + }, + { + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] } }, - "text": { - "type": "string", - "description": "The text output from the model" - }, "type": { "type": "string", - "default": "output_text", - "description": "The type of the output text", "enum": [ - "output_text" + "google.calendar.event.create" + ], + "description": "The type of tool. \"google.calendar.event.create\" for Google Calendar Create Event tool." + }, + "id": { + "type": "string", + "description": "This is the unique identifier for the tool." + }, + "orgId": { + "type": "string", + "description": "This is the unique identifier for the organization that this tool belongs to." + }, + "createdAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the tool was created." + }, + "updatedAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the tool was last updated." + }, + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "allOf": [ + { + "$ref": "#/components/schemas/ToolRejectionPlan" + } ] } }, "required": [ - "annotations", - "text", - "type" + "type", + "id", + "orgId", + "createdAt", + "updatedAt" ] }, - "ResponseOutputMessage": { + "GoogleSheetsRowAppendTool": { "type": "object", "properties": { - "id": { + "latestVersion": { "type": "string", - "description": "The unique ID of the output message" + "nullable": true }, - "content": { - "description": "Content of the output message", + "messages": { "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", "items": { - "$ref": "#/components/schemas/ResponseOutputText" + "oneOf": [ + { + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" + }, + { + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] } }, - "role": { + "type": { "type": "string", - "default": "assistant", - "description": "The role of the output message", "enum": [ - "assistant" - ] + "google.sheets.row.append" + ], + "description": "The type of tool. \"google.sheets.row.append\" for Google Sheets Row Append tool." }, - "status": { + "id": { "type": "string", - "description": "The status of the message", - "enum": [ - "in_progress", - "completed", - "incomplete" - ] + "description": "This is the unique identifier for the tool." }, - "type": { + "orgId": { "type": "string", - "default": "message", - "description": "The type of the output message", - "enum": [ - "message" + "description": "This is the unique identifier for the organization that this tool belongs to." + }, + "createdAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the tool was created." + }, + "updatedAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the tool was last updated." + }, + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "allOf": [ + { + "$ref": "#/components/schemas/ToolRejectionPlan" + } ] } }, "required": [ + "type", "id", - "content", - "role", - "status", - "type" + "orgId", + "createdAt", + "updatedAt" ] }, - "ResponseObject": { + "GoogleCalendarCheckAvailabilityTool": { "type": "object", "properties": { - "id": { + "latestVersion": { "type": "string", - "description": "Unique identifier for this Response" + "nullable": true }, - "object": { + "messages": { + "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" + }, + { + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] + } + }, + "type": { "type": "string", - "default": "response", - "description": "The object type", "enum": [ - "response" - ] + "google.calendar.availability.check" + ], + "description": "The type of tool. \"google.calendar.availability.check\" for Google Calendar Check Availability tool." }, - "created_at": { - "type": "number", - "description": "Unix timestamp (in seconds) of when this Response was created" + "id": { + "type": "string", + "description": "This is the unique identifier for the tool." }, - "status": { + "orgId": { "type": "string", - "description": "Status of the response", - "enum": [ - "completed", - "failed", - "in_progress", - "incomplete" - ] + "description": "This is the unique identifier for the organization that this tool belongs to." }, - "error": { + "createdAt": { + "format": "date-time", "type": "string", - "nullable": true, - "default": null, - "description": "Error message if the response failed" + "description": "This is the ISO 8601 date-time string of when the tool was created." }, - "output": { - "description": "Output messages from the model", - "type": "array", - "items": { - "$ref": "#/components/schemas/ResponseOutputMessage" - } + "updatedAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the tool was last updated." + }, + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "allOf": [ + { + "$ref": "#/components/schemas/ToolRejectionPlan" + } + ] } }, "required": [ + "type", "id", - "object", - "created_at", - "status", - "output" + "orgId", + "createdAt", + "updatedAt" ] }, - "ResponseTextDeltaEvent": { + "SlackSendMessageTool": { "type": "object", "properties": { - "content_index": { - "type": "number", - "description": "Index of the content part" - }, - "delta": { - "type": "string", - "description": "Text delta being added" - }, - "item_id": { + "latestVersion": { "type": "string", - "description": "ID of the output item" + "nullable": true }, - "output_index": { - "type": "number", - "description": "Index of the output item" + "messages": { + "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" + }, + { + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] + } }, "type": { "type": "string", - "default": "response.output_text.delta", - "description": "Event type", "enum": [ - "response.output_text.delta" - ] - } - }, - "required": [ - "content_index", - "delta", - "item_id", - "output_index", - "type" - ] - }, - "ResponseTextDoneEvent": { - "type": "object", - "properties": { - "content_index": { - "type": "number", - "description": "Index of the content part" + "slack.message.send" + ], + "description": "The type of tool. \"slack.message.send\" for Slack Send Message tool." }, - "item_id": { + "id": { "type": "string", - "description": "ID of the output item" + "description": "This is the unique identifier for the tool." }, - "output_index": { - "type": "number", - "description": "Index of the output item" + "orgId": { + "type": "string", + "description": "This is the unique identifier for the organization that this tool belongs to." }, - "text": { + "createdAt": { + "format": "date-time", "type": "string", - "description": "Complete text content" + "description": "This is the ISO 8601 date-time string of when the tool was created." }, - "type": { + "updatedAt": { + "format": "date-time", "type": "string", - "default": "response.output_text.done", - "description": "Event type", - "enum": [ - "response.output_text.done" - ] - } - }, - "required": [ - "content_index", - "item_id", - "output_index", - "text", - "type" - ] - }, - "ResponseCompletedEvent": { - "type": "object", - "properties": { - "response": { - "description": "The completed response", + "description": "This is the ISO 8601 date-time string of when the tool was last updated." + }, + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", "allOf": [ { - "$ref": "#/components/schemas/ResponseObject" - } - ] - }, - "type": { - "type": "string", - "default": "response.completed", - "description": "Event type", - "enum": [ - "response.completed" + "$ref": "#/components/schemas/ToolRejectionPlan" + } ] } }, "required": [ - "response", - "type" + "type", + "id", + "orgId", + "createdAt", + "updatedAt" ] }, - "ResponseErrorEvent": { + "SmsTool": { "type": "object", "properties": { + "latestVersion": { + "type": "string", + "nullable": true + }, + "messages": { + "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" + }, + { + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] + } + }, "type": { "type": "string", - "default": "error", - "description": "Event type", "enum": [ - "error" - ] + "sms" + ], + "description": "The type of tool. \"sms\" for Twilio SMS sending tool." }, - "code": { + "id": { "type": "string", - "description": "Error code", - "example": "ERR_SOMETHING" + "description": "This is the unique identifier for the tool." }, - "message": { + "orgId": { "type": "string", - "description": "Error message", - "example": "Something went wrong" + "description": "This is the unique identifier for the organization that this tool belongs to." }, - "param": { + "createdAt": { + "format": "date-time", "type": "string", - "nullable": true, - "description": "Parameter that caused the error" + "description": "This is the ISO 8601 date-time string of when the tool was created." }, - "sequence_number": { - "type": "number", - "description": "Sequence number of the event", - "example": 1 + "updatedAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the tool was last updated." + }, + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "allOf": [ + { + "$ref": "#/components/schemas/ToolRejectionPlan" + } + ] } }, "required": [ "type", - "code", - "message", - "sequence_number" + "id", + "orgId", + "createdAt", + "updatedAt" ] }, - "CreateCampaignDTO": { + "McpTool": { "type": "object", "properties": { - "name": { - "type": "string", - "description": "This is the name of the campaign. This is just for your own reference.", - "example": "Q2 Sales Campaign" - }, - "assistantId": { + "latestVersion": { "type": "string", - "description": "This is the assistant ID that will be used for the campaign calls. Note: Either assistantId or workflowId can be used, but not both." + "nullable": true }, - "workflowId": { - "type": "string", - "description": "This is the workflow ID that will be used for the campaign calls. Note: Either assistantId or workflowId can be used, but not both." + "messages": { + "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" + }, + { + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] + } }, - "phoneNumberId": { + "type": { "type": "string", - "description": "This is the phone number ID that will be used for the campaign calls." + "enum": [ + "mcp" + ], + "description": "The type of tool. \"mcp\" for MCP tool." }, - "schedulePlan": { - "description": "This is the schedule plan for the campaign.", + "server": { + "description": "\n This is the server where a `tool-calls` webhook will be sent.\n\n Notes:\n - Webhook is sent to this server when a tool call is made.\n - Webhook contains the call, assistant, and phone number objects.\n - Webhook contains the variables set on the assistant.\n - Webhook is sent to the first available URL in this order: {{tool.server.url}}, {{assistant.server.url}}, {{phoneNumber.server.url}}, {{org.server.url}}.\n - Webhook expects a response with tool call result.", "allOf": [ { - "$ref": "#/components/schemas/SchedulePlan" + "$ref": "#/components/schemas/Server" } ] }, - "customers": { - "description": "These are the customers that will be called in the campaign.", + "toolMessages": { + "description": "Per-tool message overrides for individual tools loaded from the MCP server. Set messages to an empty array to suppress messages for a specific tool. Tools not listed here will use the default messages from the parent tool.", "type": "array", "items": { - "$ref": "#/components/schemas/CreateCustomerDTO" + "$ref": "#/components/schemas/McpToolMessages" } + }, + "id": { + "type": "string", + "description": "This is the unique identifier for the tool." + }, + "orgId": { + "type": "string", + "description": "This is the unique identifier for the organization that this tool belongs to." + }, + "createdAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the tool was created." + }, + "updatedAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the tool was last updated." + }, + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "allOf": [ + { + "$ref": "#/components/schemas/ToolRejectionPlan" + } + ] + }, + "metadata": { + "$ref": "#/components/schemas/McpToolMetadata" } }, "required": [ - "name", - "phoneNumberId", - "customers" + "type", + "id", + "orgId", + "createdAt", + "updatedAt" ] }, - "Campaign": { + "GoHighLevelCalendarAvailabilityTool": { "type": "object", "properties": { - "status": { + "latestVersion": { "type": "string", - "description": "This is the status of the campaign.", - "enum": [ - "scheduled", - "in-progress", - "ended" - ] + "nullable": true }, - "endedReason": { + "messages": { + "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" + }, + { + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] + } + }, + "type": { "type": "string", - "description": "This is the explanation for how the campaign ended.", "enum": [ - "campaign.scheduled.ended-by-user", - "campaign.in-progress.ended-by-user", - "campaign.ended.success" - ] + "gohighlevel.calendar.availability.check" + ], + "description": "The type of tool. \"gohighlevel.calendar.availability.check\" for GoHighLevel Calendar Availability Check tool." }, - "name": { + "id": { "type": "string", - "description": "This is the name of the campaign. This is just for your own reference.", - "example": "Q2 Sales Campaign" + "description": "This is the unique identifier for the tool." }, - "assistantId": { + "orgId": { "type": "string", - "description": "This is the assistant ID that will be used for the campaign calls. Note: Either assistantId or workflowId can be used, but not both." + "description": "This is the unique identifier for the organization that this tool belongs to." }, - "workflowId": { + "createdAt": { + "format": "date-time", "type": "string", - "description": "This is the workflow ID that will be used for the campaign calls. Note: Either assistantId or workflowId can be used, but not both." + "description": "This is the ISO 8601 date-time string of when the tool was created." }, - "phoneNumberId": { + "updatedAt": { + "format": "date-time", "type": "string", - "description": "This is the phone number ID that will be used for the campaign calls." + "description": "This is the ISO 8601 date-time string of when the tool was last updated." }, - "schedulePlan": { - "description": "This is the schedule plan for the campaign.", + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", "allOf": [ { - "$ref": "#/components/schemas/SchedulePlan" + "$ref": "#/components/schemas/ToolRejectionPlan" } ] + } + }, + "required": [ + "type", + "id", + "orgId", + "createdAt", + "updatedAt" + ] + }, + "GoHighLevelCalendarEventCreateTool": { + "type": "object", + "properties": { + "latestVersion": { + "type": "string", + "nullable": true }, - "customers": { - "description": "These are the customers that will be called in the campaign.", + "messages": { "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", "items": { - "$ref": "#/components/schemas/CreateCustomerDTO" + "oneOf": [ + { + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" + }, + { + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] } }, + "type": { + "type": "string", + "enum": [ + "gohighlevel.calendar.event.create" + ], + "description": "The type of tool. \"gohighlevel.calendar.event.create\" for GoHighLevel Calendar Event Create tool." + }, "id": { "type": "string", - "description": "This is the unique identifier for the campaign." + "description": "This is the unique identifier for the tool." }, "orgId": { "type": "string", - "description": "This is the unique identifier for the org that this campaign belongs to." + "description": "This is the unique identifier for the organization that this tool belongs to." }, "createdAt": { "format": "date-time", "type": "string", - "description": "This is the ISO 8601 date-time string of when the campaign was created." + "description": "This is the ISO 8601 date-time string of when the tool was created." }, "updatedAt": { "format": "date-time", "type": "string", - "description": "This is the ISO 8601 date-time string of when the campaign was last updated." - }, - "calls": { - "type": "object", - "description": "This is a map of call IDs to campaign call details." - }, - "callsCounterScheduled": { - "type": "number", - "description": "This is the number of calls that have been scheduled." - }, - "callsCounterQueued": { - "type": "number", - "description": "This is the number of calls that have been queued." - }, - "callsCounterInProgress": { - "type": "number", - "description": "This is the number of calls that have been in progress." - }, - "callsCounterEndedVoicemail": { - "type": "number", - "description": "This is the number of calls whose ended reason is 'voicemail'." + "description": "This is the ISO 8601 date-time string of when the tool was last updated." }, - "callsCounterEnded": { - "type": "number", - "description": "This is the number of calls that have ended." + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "allOf": [ + { + "$ref": "#/components/schemas/ToolRejectionPlan" + } + ] } }, "required": [ - "status", - "name", - "phoneNumberId", - "customers", + "type", "id", "orgId", "createdAt", - "updatedAt", - "calls", - "callsCounterScheduled", - "callsCounterQueued", - "callsCounterInProgress", - "callsCounterEndedVoicemail", - "callsCounterEnded" + "updatedAt" ] }, - "CampaignPaginatedResponse": { + "GoHighLevelContactCreateTool": { "type": "object", "properties": { - "results": { + "latestVersion": { + "type": "string", + "nullable": true + }, + "messages": { "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", "items": { - "$ref": "#/components/schemas/Campaign" + "oneOf": [ + { + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" + }, + { + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] } }, - "metadata": { - "$ref": "#/components/schemas/PaginationMeta" - } - }, - "required": [ - "results", - "metadata" - ] - }, - "UpdateCampaignDTO": { - "type": "object", - "properties": { - "name": { + "type": { "type": "string", - "description": "This is the name of the campaign. This is just for your own reference." + "enum": [ + "gohighlevel.contact.create" + ], + "description": "The type of tool. \"gohighlevel.contact.create\" for GoHighLevel Contact Create tool." }, - "assistantId": { + "id": { "type": "string", - "description": "This is the assistant ID that will be used for the campaign calls.\nCan only be updated if campaign is not in progress or has ended." + "description": "This is the unique identifier for the tool." }, - "workflowId": { + "orgId": { "type": "string", - "description": "This is the workflow ID that will be used for the campaign calls.\nCan only be updated if campaign is not in progress or has ended." + "description": "This is the unique identifier for the organization that this tool belongs to." }, - "phoneNumberId": { + "createdAt": { + "format": "date-time", "type": "string", - "description": "This is the phone number ID that will be used for the campaign calls.\nCan only be updated if campaign is not in progress or has ended." + "description": "This is the ISO 8601 date-time string of when the tool was created." }, - "schedulePlan": { - "description": "This is the schedule plan for the campaign.\nCan only be updated if campaign is not in progress or has ended.", + "updatedAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the tool was last updated." + }, + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", "allOf": [ { - "$ref": "#/components/schemas/SchedulePlan" + "$ref": "#/components/schemas/ToolRejectionPlan" } ] - }, - "status": { - "type": "string", - "description": "This is the status of the campaign.\nCan only be updated to 'ended' if you want to end the campaign.\nWhen set to 'ended', it will delete all scheduled calls. Calls in progress will be allowed to complete.", - "enum": [ - "ended" - ] } - } + }, + "required": [ + "type", + "id", + "orgId", + "createdAt", + "updatedAt" + ] }, - "Session": { + "GoHighLevelContactGetTool": { "type": "object", "properties": { + "latestVersion": { + "type": "string", + "nullable": true + }, + "messages": { + "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" + }, + { + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] + } + }, + "type": { + "type": "string", + "enum": [ + "gohighlevel.contact.get" + ], + "description": "The type of tool. \"gohighlevel.contact.get\" for GoHighLevel Contact Get tool." + }, "id": { "type": "string", - "description": "This is the unique identifier for the session." + "description": "This is the unique identifier for the tool." }, "orgId": { "type": "string", - "description": "This is the unique identifier for the organization that owns this session." + "description": "This is the unique identifier for the organization that this tool belongs to." }, "createdAt": { "format": "date-time", "type": "string", - "description": "This is the ISO 8601 timestamp indicating when the session was created." + "description": "This is the ISO 8601 date-time string of when the tool was created." }, "updatedAt": { "format": "date-time", "type": "string", - "description": "This is the ISO 8601 timestamp indicating when the session was last updated." - }, - "name": { - "type": "string", - "description": "This is a user-defined name for the session. Maximum length is 40 characters.", - "maxLength": 40 - }, - "status": { - "type": "string", - "description": "This is the current status of the session. Can be either 'active' or 'completed'.", - "enum": [ - "active", - "completed" - ] - }, - "expirationSeconds": { - "type": "number", - "description": "Session expiration time in seconds. Defaults to 24 hours (86400 seconds) if not set.", - "minimum": 60, - "maximum": 2592000, - "example": 86400 - }, - "assistantId": { - "type": "string", - "description": "This is the ID of the assistant associated with this session. Use this when referencing an existing assistant." + "description": "This is the ISO 8601 date-time string of when the tool was last updated." }, - "assistant": { - "description": "This is the assistant configuration for this session. Use this when creating a new assistant configuration.\nIf assistantId is provided, this will be ignored.", + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", "allOf": [ { - "$ref": "#/components/schemas/CreateAssistantDTO" + "$ref": "#/components/schemas/ToolRejectionPlan" } ] + } + }, + "required": [ + "type", + "id", + "orgId", + "createdAt", + "updatedAt" + ] + }, + "SipRequestTool": { + "type": "object", + "properties": { + "latestVersion": { + "type": "string", + "nullable": true }, "messages": { "type": "array", - "description": "This is an array of chat messages in the session.", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", "items": { "oneOf": [ { - "$ref": "#/components/schemas/SystemMessage", - "title": "SystemMessage" - }, - { - "$ref": "#/components/schemas/UserMessage", - "title": "UserMessage" + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" }, { - "$ref": "#/components/schemas/AssistantMessage", - "title": "AssistantMessage" + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" }, { - "$ref": "#/components/schemas/ToolMessage", - "title": "ToolMessage" + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" }, { - "$ref": "#/components/schemas/DeveloperMessage", - "title": "DeveloperMessage" + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" } ] } }, - "customer": { - "description": "This is the customer information associated with this session.", + "type": { + "type": "string", + "enum": [ + "sipRequest" + ], + "description": "The type of tool. \"sipRequest\" for SIP request tool." + }, + "verb": { + "type": "string", + "enum": [ + "INFO", + "MESSAGE", + "NOTIFY" + ], + "description": "The SIP method to send." + }, + "headers": { + "description": "JSON schema for headers the model should populate when sending the SIP request.", "allOf": [ { - "$ref": "#/components/schemas/CreateCustomerDTO" + "$ref": "#/components/schemas/JsonSchema" } ] }, - "phoneNumberId": { + "body": { + "description": "Body to include in the SIP request. Either a literal string body, or a JSON schema describing a structured body that the model should populate.", + "oneOf": [ + { + "type": "string" + }, + { + "$ref": "#/components/schemas/JsonSchema" + } + ] + }, + "id": { "type": "string", - "description": "This is the ID of the phone number associated with this session." + "description": "This is the unique identifier for the tool." }, - "phoneNumber": { - "description": "This is the phone number configuration for this session.", + "orgId": { + "type": "string", + "description": "This is the unique identifier for the organization that this tool belongs to." + }, + "createdAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the tool was created." + }, + "updatedAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the tool was last updated." + }, + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", "allOf": [ { - "$ref": "#/components/schemas/ImportTwilioPhoneNumberDTO" + "$ref": "#/components/schemas/ToolRejectionPlan" } ] } }, "required": [ + "type", + "verb", "id", "orgId", "createdAt", "updatedAt" ] }, - "CreateSessionDTO": { + "VoicemailTool": { "type": "object", "properties": { - "name": { - "type": "string", - "description": "This is a user-defined name for the session. Maximum length is 40 characters.", - "maxLength": 40 - }, - "status": { - "type": "string", - "description": "This is the current status of the session. Can be either 'active' or 'completed'.", - "enum": [ - "active", - "completed" - ] - }, - "expirationSeconds": { - "type": "number", - "description": "Session expiration time in seconds. Defaults to 24 hours (86400 seconds) if not set.", - "minimum": 60, - "maximum": 2592000, - "example": 86400 - }, - "assistantId": { + "latestVersion": { "type": "string", - "description": "This is the ID of the assistant associated with this session. Use this when referencing an existing assistant." - }, - "assistant": { - "description": "This is the assistant configuration for this session. Use this when creating a new assistant configuration.\nIf assistantId is provided, this will be ignored.", - "allOf": [ - { - "$ref": "#/components/schemas/CreateAssistantDTO" - } - ] + "nullable": true }, "messages": { "type": "array", - "description": "This is an array of chat messages in the session.", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", "items": { "oneOf": [ { - "$ref": "#/components/schemas/SystemMessage", - "title": "SystemMessage" - }, - { - "$ref": "#/components/schemas/UserMessage", - "title": "UserMessage" + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" }, { - "$ref": "#/components/schemas/AssistantMessage", - "title": "AssistantMessage" + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" }, { - "$ref": "#/components/schemas/ToolMessage", - "title": "ToolMessage" + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" }, { - "$ref": "#/components/schemas/DeveloperMessage", - "title": "DeveloperMessage" + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" } ] } }, - "customer": { - "description": "This is the customer information associated with this session.", - "allOf": [ - { - "$ref": "#/components/schemas/CreateCustomerDTO" - } + "type": { + "type": "string", + "description": "The type of tool. \"voicemail\" for Voicemail tool.", + "enum": [ + "voicemail" ] }, - "phoneNumberId": { + "beepDetectionEnabled": { + "type": "boolean", + "description": "This is the flag that enables beep detection for voicemail detection and applies only for twilio based calls.\n\n@default false", + "default": false, + "example": false + }, + "id": { "type": "string", - "description": "This is the ID of the phone number associated with this session." + "description": "This is the unique identifier for the tool." }, - "phoneNumber": { - "description": "This is the phone number configuration for this session.", + "orgId": { + "type": "string", + "description": "This is the unique identifier for the organization that this tool belongs to." + }, + "createdAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the tool was created." + }, + "updatedAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the tool was last updated." + }, + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", "allOf": [ { - "$ref": "#/components/schemas/ImportTwilioPhoneNumberDTO" + "$ref": "#/components/schemas/ToolRejectionPlan" } ] } - } + }, + "required": [ + "type", + "id", + "orgId", + "createdAt", + "updatedAt" + ] }, - "UpdateSessionDTO": { + "CreateApiRequestToolDTO": { "type": "object", "properties": { - "name": { - "type": "string", - "description": "This is the new name for the session. Maximum length is 40 characters.", - "maxLength": 40 - }, - "status": { - "type": "string", - "description": "This is the new status for the session.", - "enum": [ - "active", - "completed" - ] - }, - "expirationSeconds": { - "type": "number", - "description": "Session expiration time in seconds. Defaults to 24 hours (86400 seconds) if not set.", - "minimum": 60, - "maximum": 2592000, - "example": 86400 - }, "messages": { "type": "array", - "description": "This is the updated array of chat messages.", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", "items": { "oneOf": [ { - "$ref": "#/components/schemas/SystemMessage", - "title": "SystemMessage" - }, - { - "$ref": "#/components/schemas/UserMessage", - "title": "UserMessage" + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" }, { - "$ref": "#/components/schemas/AssistantMessage", - "title": "AssistantMessage" + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" }, { - "$ref": "#/components/schemas/ToolMessage", - "title": "ToolMessage" + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" }, { - "$ref": "#/components/schemas/DeveloperMessage", - "title": "DeveloperMessage" + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" } ] } - } - } - }, - "GetSessionPaginatedDTO": { - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "This is the name of the session to filter by." }, - "assistantId": { + "type": { "type": "string", - "description": "This is the ID of the assistant to filter sessions by." + "enum": [ + "apiRequest" + ], + "description": "The type of tool. \"apiRequest\" for API request tool." }, - "workflowId": { + "name": { "type": "string", - "description": "This is the ID of the workflow to filter sessions by." - }, - "page": { - "type": "number", - "description": "This is the page number to return. Defaults to 1.", - "minimum": 1 + "description": "This is the name of the tool. This will be passed to the model.\n\nMust be a-z, A-Z, 0-9, or contain underscores and dashes, with a maximum length of 40.", + "maxLength": 40, + "pattern": "/^[a-zA-Z0-9_-]{1,40}$/" }, - "sortOrder": { + "method": { "type": "string", - "description": "This is the sort order for pagination. Defaults to 'DESC'.", "enum": [ - "ASC", - "DESC" + "POST", + "GET", + "PUT", + "PATCH", + "DELETE" ] }, - "limit": { + "timeoutSeconds": { "type": "number", - "description": "This is the maximum number of items to return. Defaults to 100.", - "minimum": 0, - "maximum": 1000 - }, - "createdAtGt": { - "format": "date-time", - "type": "string", - "description": "This will return items where the createdAt is greater than the specified value." - }, - "createdAtLt": { - "format": "date-time", - "type": "string", - "description": "This will return items where the createdAt is less than the specified value." - }, - "createdAtGe": { - "format": "date-time", - "type": "string", - "description": "This will return items where the createdAt is greater than or equal to the specified value." - }, - "createdAtLe": { - "format": "date-time", - "type": "string", - "description": "This will return items where the createdAt is less than or equal to the specified value." - }, - "updatedAtGt": { - "format": "date-time", - "type": "string", - "description": "This will return items where the updatedAt is greater than the specified value." + "description": "This is the timeout in seconds for the request. Defaults to 20 seconds.\n\n@default 20", + "minimum": 1, + "maximum": 300, + "example": 20 }, - "updatedAtLt": { - "format": "date-time", + "credentialId": { "type": "string", - "description": "This will return items where the updatedAt is less than the specified value." + "description": "The credential ID for API request authentication", + "example": "550e8400-e29b-41d4-a716-446655440000" }, - "updatedAtGe": { - "format": "date-time", - "type": "string", - "description": "This will return items where the updatedAt is greater than or equal to the specified value." + "encryptedPaths": { + "type": "array", + "description": "This is the paths to encrypt in the request body if credentialId and encryptionPlan are defined.", + "items": { + "type": "string" + } }, - "updatedAtLe": { - "format": "date-time", - "type": "string", - "description": "This will return items where the updatedAt is less than or equal to the specified value." - } - } - }, - "SessionPaginatedResponse": { - "type": "object", - "properties": { - "results": { + "parameters": { + "description": "Static key-value pairs merged into the request body. Values support Liquid templates.", "type": "array", "items": { - "$ref": "#/components/schemas/Session" + "$ref": "#/components/schemas/ToolParameter" } }, - "metadata": { - "$ref": "#/components/schemas/PaginationMeta" - } - }, - "required": [ - "results", - "metadata" - ] - }, - "Assistant": { - "type": "object", - "properties": { - "transcriber": { - "description": "These are the options for the assistant's transcriber.", - "oneOf": [ - { - "$ref": "#/components/schemas/AssemblyAITranscriber", - "title": "AssemblyAITranscriber" - }, - { - "$ref": "#/components/schemas/AzureSpeechTranscriber", - "title": "AzureSpeechTranscriber" - }, - { - "$ref": "#/components/schemas/CustomTranscriber", - "title": "CustomTranscriber" - }, - { - "$ref": "#/components/schemas/DeepgramTranscriber", - "title": "DeepgramTranscriber" - }, - { - "$ref": "#/components/schemas/ElevenLabsTranscriber", - "title": "ElevenLabsTranscriber" - }, - { - "$ref": "#/components/schemas/GladiaTranscriber", - "title": "GladiaTranscriber" - }, - { - "$ref": "#/components/schemas/GoogleTranscriber", - "title": "GoogleTranscriber" - }, - { - "$ref": "#/components/schemas/SpeechmaticsTranscriber", - "title": "SpeechmaticsTranscriber" - }, - { - "$ref": "#/components/schemas/TalkscriberTranscriber", - "title": "TalkscriberTranscriber" - }, - { - "$ref": "#/components/schemas/OpenAITranscriber", - "title": "OpenAITranscriber" - }, - { - "$ref": "#/components/schemas/CartesiaTranscriber", - "title": "CartesiaTranscriber" - } - ] + "description": { + "type": "string", + "description": "This is the description of the tool. This will be passed to the model." }, - "model": { - "description": "These are the options for the assistant's LLM.", - "oneOf": [ - { - "$ref": "#/components/schemas/AnthropicModel", - "title": "Anthropic" - }, - { - "$ref": "#/components/schemas/AnyscaleModel", - "title": "Anyscale" - }, - { - "$ref": "#/components/schemas/CerebrasModel", - "title": "Cerebras" - }, - { - "$ref": "#/components/schemas/CustomLLMModel", - "title": "CustomLLM" - }, - { - "$ref": "#/components/schemas/DeepInfraModel", - "title": "DeepInfra" - }, - { - "$ref": "#/components/schemas/DeepSeekModel", - "title": "DeepSeek" - }, - { - "$ref": "#/components/schemas/GoogleModel", - "title": "Google" - }, - { - "$ref": "#/components/schemas/GroqModel", - "title": "Groq" - }, - { - "$ref": "#/components/schemas/InflectionAIModel", - "title": "InflectionAI" - }, - { - "$ref": "#/components/schemas/OpenAIModel", - "title": "OpenAI" - }, - { - "$ref": "#/components/schemas/OpenRouterModel", - "title": "OpenRouter" - }, - { - "$ref": "#/components/schemas/PerplexityAIModel", - "title": "PerplexityAI" - }, - { - "$ref": "#/components/schemas/TogetherAIModel", - "title": "Together" - }, + "url": { + "type": "string", + "description": "This is where the request will be sent." + }, + "body": { + "description": "This is the body of the request.", + "allOf": [ { - "$ref": "#/components/schemas/XaiModel", - "title": "XAI" + "$ref": "#/components/schemas/JsonSchema" } ] }, - "voice": { - "description": "These are the options for the assistant's voice.", - "oneOf": [ - { - "$ref": "#/components/schemas/AzureVoice", - "title": "AzureVoice" - }, - { - "$ref": "#/components/schemas/CartesiaVoice", - "title": "CartesiaVoice" - }, - { - "$ref": "#/components/schemas/CustomVoice", - "title": "CustomVoice" - }, - { - "$ref": "#/components/schemas/DeepgramVoice", - "title": "DeepgramVoice" - }, - { - "$ref": "#/components/schemas/ElevenLabsVoice", - "title": "ElevenLabsVoice" - }, - { - "$ref": "#/components/schemas/HumeVoice", - "title": "HumeVoice" - }, - { - "$ref": "#/components/schemas/LMNTVoice", - "title": "LMNTVoice" - }, - { - "$ref": "#/components/schemas/NeuphonicVoice", - "title": "NeuphonicVoice" - }, - { - "$ref": "#/components/schemas/OpenAIVoice", - "title": "OpenAIVoice" - }, - { - "$ref": "#/components/schemas/PlayHTVoice", - "title": "PlayHTVoice" - }, - { - "$ref": "#/components/schemas/RimeAIVoice", - "title": "RimeAIVoice" - }, - { - "$ref": "#/components/schemas/SmallestAIVoice", - "title": "SmallestAIVoice" - }, - { - "$ref": "#/components/schemas/TavusVoice", - "title": "TavusVoice" - }, - { - "$ref": "#/components/schemas/VapiVoice", - "title": "VapiVoice" - }, - { - "$ref": "#/components/schemas/SesameVoice", - "title": "SesameVoice" - }, - { - "$ref": "#/components/schemas/InworldVoice", - "title": "InworldVoice" - }, + "headers": { + "description": "These are the headers to send with the request.", + "allOf": [ { - "$ref": "#/components/schemas/MinimaxVoice", - "title": "MinimaxVoice" + "$ref": "#/components/schemas/JsonSchema" } ] - }, - "firstMessage": { - "type": "string", - "description": "This is the first message that the assistant will say. This can also be a URL to a containerized audio file (mp3, wav, etc.).\n\nIf unspecified, assistant will wait for user to speak and use the model to respond once they speak.", - "example": "Hello! How can I help you today?" - }, - "firstMessageInterruptionsEnabled": { - "type": "boolean", - "default": false - }, - "firstMessageMode": { - "type": "string", - "description": "This is the mode for the first message. Default is 'assistant-speaks-first'.\n\nUse:\n- 'assistant-speaks-first' to have the assistant speak first.\n- 'assistant-waits-for-user' to have the assistant wait for the user to speak first.\n- 'assistant-speaks-first-with-model-generated-message' to have the assistant speak first with a message generated by the model based on the conversation state. (`assistant.model.messages` at call start, `call.messages` at squad transfer points).\n\n@default 'assistant-speaks-first'", - "enum": [ - "assistant-speaks-first", - "assistant-speaks-first-with-model-generated-message", - "assistant-waits-for-user" - ], - "example": "assistant-speaks-first" - }, - "voicemailDetection": { - "description": "These are the settings to configure or disable voicemail detection. Alternatively, voicemail detection can be configured using the model.tools=[VoicemailTool].\nThis uses Twilio's built-in detection while the VoicemailTool relies on the model to detect if a voicemail was reached.\nYou can use neither of them, one of them, or both of them. By default, Twilio built-in detection is enabled while VoicemailTool is not.", - "oneOf": [ - { - "$ref": "#/components/schemas/GoogleVoicemailDetectionPlan", - "title": "Google" - }, - { - "$ref": "#/components/schemas/OpenAIVoicemailDetectionPlan", - "title": "OpenAI" - }, + }, + "backoffPlan": { + "description": "This is the backoff plan if the request fails. Defaults to undefined (the request will not be retried).\n\n@default undefined (the request will not be retried)", + "allOf": [ { - "$ref": "#/components/schemas/TwilioVoicemailDetectionPlan", - "title": "Twilio" - }, + "$ref": "#/components/schemas/BackoffPlan" + } + ] + }, + "variableExtractionPlan": { + "description": "This is the plan to extract variables from the tool's response. These will be accessible during the call and stored in `call.artifact.variableValues` after the call.\n\nUsage:\n1. Use `aliases` to extract variables from the tool's response body. (Most common case)\n\n```json\n{\n \"aliases\": [\n {\n \"key\": \"customerName\",\n \"value\": \"{{customer.name}}\"\n },\n {\n \"key\": \"customerAge\",\n \"value\": \"{{customer.age}}\"\n }\n ]\n}\n```\n\nThe tool response body is made available to the liquid template.\n\n2. Use `aliases` to extract variables from the tool's response body if the response is an array.\n\n```json\n{\n \"aliases\": [\n {\n \"key\": \"customerName\",\n \"value\": \"{{$[0].name}}\"\n },\n {\n \"key\": \"customerAge\",\n \"value\": \"{{$[0].age}}\"\n }\n ]\n}\n```\n\n$ is a shorthand for the tool's response body. `$[0]` is the first item in the array. `$[n]` is the nth item in the array. Note, $ is available regardless of the response body type (both object and array).\n\n3. Use `aliases` to extract variables from the tool's response headers.\n\n```json\n{\n \"aliases\": [\n {\n \"key\": \"customerName\",\n \"value\": \"{{tool.response.headers.customer-name}}\"\n },\n {\n \"key\": \"customerAge\",\n \"value\": \"{{tool.response.headers.customer-age}}\"\n }\n ]\n}\n```\n\n`tool.response` is made available to the liquid template. Particularly, both `tool.response.headers` and `tool.response.body` are available. Note, `tool.response` is available regardless of the response body type (both object and array).\n\n4. Use `schema` to extract a large portion of the tool's response body.\n\n4.1. If you hit example.com and it returns `{\"name\": \"John\", \"age\": 30}`, then you can specify the schema as:\n\n```json\n{\n \"schema\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n },\n \"age\": {\n \"type\": \"number\"\n }\n }\n }\n}\n```\nThese will be extracted as `{{ name }}` and `{{ age }}` respectively. To emphasize, object properties are extracted as direct global variables.\n\n4.2. If you hit example.com and it returns `{\"name\": {\"first\": \"John\", \"last\": \"Doe\"}}`, then you can specify the schema as:\n\n```json\n{\n \"schema\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"object\",\n \"properties\": {\n \"first\": {\n \"type\": \"string\"\n },\n \"last\": {\n \"type\": \"string\"\n }\n }\n }\n }\n }\n}\n```\n\nThese will be extracted as `{{ name }}`. And, `{{ name.first }}` and `{{ name.last }}` will be accessible.\n\n4.3. If you hit example.com and it returns `[\"94123\", \"94124\"]`, then you can specify the schema as:\n\n```json\n{\n \"schema\": {\n \"type\": \"array\",\n \"title\": \"zipCodes\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n}\n```\n\nThis will be extracted as `{{ zipCodes }}`. To access the array items, you can use `{{ zipCodes[0] }}` and `{{ zipCodes[1] }}`.\n\n4.4. If you hit example.com and it returns `[{\"name\": \"John\", \"age\": 30, \"zipCodes\": [\"94123\", \"94124\"]}, {\"name\": \"Jane\", \"age\": 25, \"zipCodes\": [\"94125\", \"94126\"]}]`, then you can specify the schema as:\n\n```json\n{\n \"schema\": {\n \"type\": \"array\",\n \"title\": \"people\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n },\n \"age\": {\n \"type\": \"number\"\n },\n \"zipCodes\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n }\n }\n }\n}\n```\n\nThis will be extracted as `{{ people }}`. To access the array items, you can use `{{ people[n].name }}`, `{{ people[n].age }}`, `{{ people[n].zipCodes }}`, `{{ people[n].zipCodes[0] }}` and `{{ people[n].zipCodes[1] }}`.\n\nNote: Both `aliases` and `schema` can be used together.", + "allOf": [ { - "$ref": "#/components/schemas/VapiVoicemailDetectionPlan", - "title": "Vapi" + "$ref": "#/components/schemas/VariableExtractionPlan" } ] }, - "clientMessages": { + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "allOf": [ + { + "$ref": "#/components/schemas/ToolRejectionPlan" + } + ] + } + }, + "required": [ + "type", + "method", + "url" + ] + }, + "CreateCodeToolDTO": { + "type": "object", + "properties": { + "messages": { "type": "array", - "enum": [ - "conversation-update", - "function-call", - "function-call-result", - "hang", - "language-changed", - "metadata", - "model-output", - "speech-update", - "status-update", - "transcript", - "tool-calls", - "tool-calls-result", - "tool.completed", - "transfer-update", - "user-interrupted", - "voice-input", - "workflow.node.started" - ], - "example": [ - "conversation-update", - "function-call", - "hang", - "model-output", - "speech-update", - "status-update", - "transfer-update", - "transcript", - "tool-calls", - "user-interrupted", - "voice-input", - "workflow.node.started" - ], - "description": "These are the messages that will be sent to your Client SDKs. Default is conversation-update,function-call,hang,model-output,speech-update,status-update,transfer-update,transcript,tool-calls,user-interrupted,voice-input,workflow.node.started. You can check the shape of the messages in ClientMessage schema.", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", "items": { - "type": "string", - "enum": [ - "conversation-update", - "function-call", - "function-call-result", - "hang", - "language-changed", - "metadata", - "model-output", - "speech-update", - "status-update", - "transcript", - "tool-calls", - "tool-calls-result", - "tool.completed", - "transfer-update", - "user-interrupted", - "voice-input", - "workflow.node.started" + "oneOf": [ + { + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" + }, + { + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } ] } }, - "serverMessages": { - "type": "array", + "type": { + "type": "string", "enum": [ - "conversation-update", - "end-of-call-report", - "function-call", - "hang", - "language-changed", - "language-change-detected", - "model-output", - "phone-call-control", - "speech-update", - "status-update", - "transcript", - "transcript[transcriptType=\"final\"]", - "tool-calls", - "transfer-destination-request", - "handoff-destination-request", - "transfer-update", - "user-interrupted", - "voice-input", - "chat.created", - "chat.deleted", - "session.created", - "session.updated", - "session.deleted" - ], - "example": [ - "conversation-update", - "end-of-call-report", - "function-call", - "hang", - "speech-update", - "status-update", - "tool-calls", - "transfer-destination-request", - "handoff-destination-request", - "user-interrupted" + "code" ], - "description": "These are the messages that will be sent to your Server URL. Default is conversation-update,end-of-call-report,function-call,hang,speech-update,status-update,tool-calls,transfer-destination-request,handoff-destination-request,user-interrupted. You can check the shape of the messages in ServerMessage schema.", - "items": { - "type": "string", - "enum": [ - "conversation-update", - "end-of-call-report", - "function-call", - "hang", - "language-changed", - "language-change-detected", - "model-output", - "phone-call-control", - "speech-update", - "status-update", - "transcript", - "transcript[transcriptType=\"final\"]", - "tool-calls", - "transfer-destination-request", - "handoff-destination-request", - "transfer-update", - "user-interrupted", - "voice-input", - "chat.created", - "chat.deleted", - "session.created", - "session.updated", - "session.deleted" - ] - } + "description": "The type of tool. \"code\" for Code tool." }, - "maxDurationSeconds": { - "type": "number", - "description": "This is the maximum number of seconds that the call will last. When the call reaches this duration, it will be ended.\n\n@default 600 (10 minutes)", - "minimum": 10, - "maximum": 43200, - "example": 600 + "async": { + "type": "boolean", + "example": false, + "description": "This determines if the tool is async.\n\n If async, the assistant will move forward without waiting for your server to respond. This is useful if you just want to trigger something on your server.\n\n If sync, the assistant will wait for your server to respond. This is useful if want assistant to respond with the result from your server.\n\n Defaults to synchronous (`false`)." }, - "backgroundSound": { - "description": "This is the background sound in the call. Default for phone calls is 'office' and default for web calls is 'off'.\nYou can also provide a custom sound by providing a URL to an audio file.", - "oneOf": [ - { - "type": "enum", - "enum": [ - "off", - "office" - ], - "example": "office" - }, + "server": { + "description": "\n This is the server where a `tool-calls` webhook will be sent.\n\n Notes:\n - Webhook is sent to this server when a tool call is made.\n - Webhook contains the call, assistant, and phone number objects.\n - Webhook contains the variables set on the assistant.\n - Webhook is sent to the first available URL in this order: {{tool.server.url}}, {{assistant.server.url}}, {{phoneNumber.server.url}}, {{org.server.url}}.\n - Webhook expects a response with tool call result.", + "allOf": [ { - "type": "string", - "format": "uri", - "example": "https://www.soundjay.com/ambient/sounds/people-in-lounge-1.mp3" + "$ref": "#/components/schemas/Server" } ] }, - "modelOutputInMessagesEnabled": { - "type": "boolean", - "description": "This determines whether the model's output is used in conversation history rather than the transcription of assistant's speech.\n\nDefault `false` while in beta.\n\n@default false", - "example": false + "code": { + "type": "string", + "description": "TypeScript code to execute when the tool is called", + "maxLength": 50000 }, - "transportConfigurations": { + "environmentVariables": { + "description": "Environment variables available in code via `env` object", "type": "array", - "description": "These are the configurations to be passed to the transport providers of assistant's calls, like Twilio. You can store multiple configurations for different transport providers. For a call, only the configuration matching the call transport provider is used.", "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/TransportConfigurationTwilio", - "title": "Twilio" - } - ] + "$ref": "#/components/schemas/CodeToolEnvironmentVariable" } }, - "observabilityPlan": { - "description": "This is the plan for observability of assistant's calls.\n\nCurrently, only Langfuse is supported.", - "oneOf": [ + "timeoutSeconds": { + "type": "number", + "description": "This is the timeout in seconds for the code execution. Defaults to 10 seconds.\nMaximum is 30 seconds to prevent abuse.\n\n@default 10", + "minimum": 1, + "maximum": 30, + "example": 10 + }, + "credentialId": { + "type": "string", + "description": "Credential ID containing the Val Town API key", + "example": "550e8400-e29b-41d4-a716-446655440000" + }, + "variableExtractionPlan": { + "description": "Plan to extract variables from the tool response", + "allOf": [ { - "$ref": "#/components/schemas/LangfuseObservabilityPlan", - "title": "Langfuse" + "$ref": "#/components/schemas/VariableExtractionPlan" } - ], + ] + }, + "function": { + "description": "This is the function definition of the tool.\n\nFor the Code tool, this defines the name, description, and parameters that the model\nwill use to understand when and how to call this tool.", "allOf": [ { - "$ref": "#/components/schemas/LangfuseObservabilityPlan" + "$ref": "#/components/schemas/OpenAIFunction" } ] }, - "credentials": { + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "allOf": [ + { + "$ref": "#/components/schemas/ToolRejectionPlan" + } + ] + } + }, + "required": [ + "type", + "code" + ] + }, + "CreateOutputToolDTO": { + "type": "object", + "properties": { + "messages": { "type": "array", - "description": "These are dynamic credentials that will be used for the assistant calls. By default, all the credentials are available for use in the call but you can supplement an additional credentials using this. Dynamic credentials override existing credentials.", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", "items": { "oneOf": [ { - "$ref": "#/components/schemas/CreateAnthropicCredentialDTO", - "title": "AnthropicCredential" - }, - { - "$ref": "#/components/schemas/CreateAnyscaleCredentialDTO", - "title": "AnyscaleCredential" - }, - { - "$ref": "#/components/schemas/CreateAssemblyAICredentialDTO", - "title": "AssemblyAICredential" - }, - { - "$ref": "#/components/schemas/CreateAzureCredentialDTO", - "title": "AzureCredential" - }, - { - "$ref": "#/components/schemas/CreateAzureOpenAICredentialDTO", - "title": "AzureOpenAICredential" - }, - { - "$ref": "#/components/schemas/CreateByoSipTrunkCredentialDTO", - "title": "ByoSipTrunkCredential" - }, - { - "$ref": "#/components/schemas/CreateCartesiaCredentialDTO", - "title": "CartesiaCredential" - }, - { - "$ref": "#/components/schemas/CreateCerebrasCredentialDTO", - "title": "CerebrasCredential" - }, - { - "$ref": "#/components/schemas/CreateCloudflareCredentialDTO", - "title": "CloudflareCredential" - }, - { - "$ref": "#/components/schemas/CreateCustomLLMCredentialDTO", - "title": "CustomLLMCredential" - }, - { - "$ref": "#/components/schemas/CreateDeepgramCredentialDTO", - "title": "DeepgramCredential" - }, - { - "$ref": "#/components/schemas/CreateDeepInfraCredentialDTO", - "title": "DeepInfraCredential" - }, - { - "$ref": "#/components/schemas/CreateDeepSeekCredentialDTO", - "title": "DeepSeekCredential" - }, - { - "$ref": "#/components/schemas/CreateElevenLabsCredentialDTO", - "title": "ElevenLabsCredential" - }, - { - "$ref": "#/components/schemas/CreateGcpCredentialDTO", - "title": "GcpCredential" - }, - { - "$ref": "#/components/schemas/CreateGladiaCredentialDTO", - "title": "GladiaCredential" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelCredentialDTO", - "title": "GhlCredential" - }, - { - "$ref": "#/components/schemas/CreateGoogleCredentialDTO", - "title": "GoogleCredential" - }, - { - "$ref": "#/components/schemas/CreateGroqCredentialDTO", - "title": "GroqCredential" - }, - { - "$ref": "#/components/schemas/CreateHumeCredentialDTO", - "title": "HumeCredential" - }, - { - "$ref": "#/components/schemas/CreateInflectionAICredentialDTO", - "title": "InflectionAICredential" - }, - { - "$ref": "#/components/schemas/CreateLangfuseCredentialDTO", - "title": "LangfuseCredential" - }, - { - "$ref": "#/components/schemas/CreateLmntCredentialDTO", - "title": "LmntCredential" - }, - { - "$ref": "#/components/schemas/CreateMakeCredentialDTO", - "title": "MakeCredential" - }, - { - "$ref": "#/components/schemas/CreateMistralCredentialDTO", - "title": "MistralCredential" - }, - { - "$ref": "#/components/schemas/CreateNeuphonicCredentialDTO", - "title": "NeuphonicCredential" - }, - { - "$ref": "#/components/schemas/CreateOpenAICredentialDTO", - "title": "OpenAICredential" - }, - { - "$ref": "#/components/schemas/CreateOpenRouterCredentialDTO", - "title": "OpenRouterCredential" - }, - { - "$ref": "#/components/schemas/CreatePerplexityAICredentialDTO", - "title": "PerplexityAICredential" - }, - { - "$ref": "#/components/schemas/CreatePlayHTCredentialDTO", - "title": "PlayHTCredential" - }, - { - "$ref": "#/components/schemas/CreateRimeAICredentialDTO", - "title": "RimeAICredential" - }, - { - "$ref": "#/components/schemas/CreateRunpodCredentialDTO", - "title": "RunpodCredential" - }, - { - "$ref": "#/components/schemas/CreateS3CredentialDTO", - "title": "S3Credential" - }, - { - "$ref": "#/components/schemas/CreateSmallestAICredentialDTO", - "title": "SmallestAICredential" - }, - { - "$ref": "#/components/schemas/CreateSpeechmaticsCredentialDTO", - "title": "SpeechmaticsCredential" - }, - { - "$ref": "#/components/schemas/CreateSupabaseCredentialDTO", - "title": "SupabaseCredential" - }, - { - "$ref": "#/components/schemas/CreateTavusCredentialDTO", - "title": "TavusCredential" - }, - { - "$ref": "#/components/schemas/CreateTogetherAICredentialDTO", - "title": "TogetherAICredential" - }, - { - "$ref": "#/components/schemas/CreateTrieveCredentialDTO", - "title": "TrieveCredential" - }, - { - "$ref": "#/components/schemas/CreateTwilioCredentialDTO", - "title": "TwilioCredential" - }, - { - "$ref": "#/components/schemas/CreateVonageCredentialDTO", - "title": "VonageCredential" - }, - { - "$ref": "#/components/schemas/CreateWebhookCredentialDTO", - "title": "WebhookCredential" - }, - { - "$ref": "#/components/schemas/CreateXAiCredentialDTO", - "title": "XAiCredential" - }, - { - "$ref": "#/components/schemas/CreateGoogleCalendarOAuth2ClientCredentialDTO", - "title": "GoogleCalendarOAuth2ClientCredential" - }, - { - "$ref": "#/components/schemas/CreateGoogleCalendarOAuth2AuthorizationCredentialDTO", - "title": "GoogleCalendarOAuth2AuthorizationCredential" - }, - { - "$ref": "#/components/schemas/CreateGoogleSheetsOAuth2AuthorizationCredentialDTO", - "title": "GoogleSheetsOAuth2AuthorizationCredential" + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" }, { - "$ref": "#/components/schemas/CreateSlackOAuth2AuthorizationCredentialDTO", - "title": "SlackOAuth2AuthorizationCredential" + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" }, { - "$ref": "#/components/schemas/CreateGoHighLevelMCPCredentialDTO", - "title": "GoHighLevelMCPCredential" + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" }, { - "$ref": "#/components/schemas/CreateInworldCredentialDTO", - "title": "InworldCredential" - } - ], - "discriminator": { - "propertyName": "provider", - "mapping": { - "11labs": "#/components/schemas/CreateElevenLabsCredentialDTO", - "anthropic": "#/components/schemas/CreateAnthropicCredentialDTO", - "anyscale": "#/components/schemas/CreateAnyscaleCredentialDTO", - "assembly-ai": "#/components/schemas/CreateAssemblyAICredentialDTO", - "azure-openai": "#/components/schemas/CreateAzureOpenAICredentialDTO", - "azure": "#/components/schemas/CreateAzureCredentialDTO", - "byo-sip-trunk": "#/components/schemas/CreateByoSipTrunkCredentialDTO", - "cartesia": "#/components/schemas/CreateCartesiaCredentialDTO", - "cerebras": "#/components/schemas/CreateCerebrasCredentialDTO", - "cloudflare": "#/components/schemas/CreateCloudflareCredentialDTO", - "custom-llm": "#/components/schemas/CreateCustomLLMCredentialDTO", - "deepgram": "#/components/schemas/CreateDeepgramCredentialDTO", - "deepinfra": "#/components/schemas/CreateDeepInfraCredentialDTO", - "deep-seek": "#/components/schemas/CreateDeepSeekCredentialDTO", - "gcp": "#/components/schemas/CreateGcpCredentialDTO", - "gladia": "#/components/schemas/CreateGladiaCredentialDTO", - "gohighlevel": "#/components/schemas/CreateGoHighLevelCredentialDTO", - "google": "#/components/schemas/CreateGoogleCredentialDTO", - "groq": "#/components/schemas/CreateGroqCredentialDTO", - "inflection-ai": "#/components/schemas/CreateInflectionAICredentialDTO", - "langfuse": "#/components/schemas/CreateLangfuseCredentialDTO", - "lmnt": "#/components/schemas/CreateLmntCredentialDTO", - "make": "#/components/schemas/CreateMakeCredentialDTO", - "openai": "#/components/schemas/CreateOpenAICredentialDTO", - "openrouter": "#/components/schemas/CreateOpenRouterCredentialDTO", - "perplexity-ai": "#/components/schemas/CreatePerplexityAICredentialDTO", - "playht": "#/components/schemas/CreatePlayHTCredentialDTO", - "rime-ai": "#/components/schemas/CreateRimeAICredentialDTO", - "runpod": "#/components/schemas/CreateRunpodCredentialDTO", - "s3": "#/components/schemas/CreateS3CredentialDTO", - "supabase": "#/components/schemas/CreateSupabaseCredentialDTO", - "smallest-ai": "#/components/schemas/CreateSmallestAICredentialDTO", - "tavus": "#/components/schemas/CreateTavusCredentialDTO", - "together-ai": "#/components/schemas/CreateTogetherAICredentialDTO", - "twilio": "#/components/schemas/CreateTwilioCredentialDTO", - "vonage": "#/components/schemas/CreateVonageCredentialDTO", - "webhook": "#/components/schemas/CreateWebhookCredentialDTO", - "xai": "#/components/schemas/CreateXAiCredentialDTO", - "neuphonic": "#/components/schemas/CreateNeuphonicCredentialDTO", - "hume": "#/components/schemas/CreateHumeCredentialDTO", - "mistral": "#/components/schemas/CreateMistralCredentialDTO", - "speechmatics": "#/components/schemas/CreateSpeechmaticsCredentialDTO", - "trieve": "#/components/schemas/CreateTrieveCredentialDTO", - "google.calendar.oauth2-client": "#/components/schemas/CreateGoogleCalendarOAuth2ClientCredentialDTO", - "google.calendar.oauth2-authorization": "#/components/schemas/CreateGoogleCalendarOAuth2AuthorizationCredentialDTO", - "google.sheets.oauth2-authorization": "#/components/schemas/CreateGoogleSheetsOAuth2AuthorizationCredentialDTO", - "slack.oauth2-authorization": "#/components/schemas/CreateSlackOAuth2AuthorizationCredentialDTO", - "ghl.oauth2-authorization": "#/components/schemas/CreateGoHighLevelMCPCredentialDTO", - "inworld": "#/components/schemas/CreateInworldCredentialDTO", - "minimax": "#/components/schemas/CreateMinimaxCredentialDTO" + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" } + ] + } + }, + "type": { + "type": "string", + "enum": [ + "output" + ], + "description": "The type of tool. \"output\" for Output tool." + }, + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "allOf": [ + { + "$ref": "#/components/schemas/ToolRejectionPlan" } - } - }, - "hooks": { + ] + } + }, + "required": [ + "type" + ] + }, + "CreateBashToolDTO": { + "type": "object", + "properties": { + "messages": { "type": "array", - "description": "This is a set of actions that will be performed on certain events.", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", "items": { "oneOf": [ { - "$ref": "#/components/schemas/CallHookCallEnding", - "title": "CallHookCallEnding" + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" }, { - "$ref": "#/components/schemas/CallHookAssistantSpeechInterrupted", - "title": "CallHookAssistantSpeechInterrupted" + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" }, { - "$ref": "#/components/schemas/CallHookCustomerSpeechInterrupted", - "title": "CallHookCustomerSpeechInterrupted" + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" }, { - "$ref": "#/components/schemas/CallHookCustomerSpeechTimeout", - "title": "CallHookCustomerSpeechTimeout" + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" } ] } }, - "name": { - "type": "string", - "description": "This is the name of the assistant.\n\nThis is required when you want to transfer between assistants in a call.", - "maxLength": 40 - }, - "voicemailMessage": { + "type": { "type": "string", - "description": "This is the message that the assistant will say if the call is forwarded to voicemail.\n\nIf unspecified, it will hang up.", - "maxLength": 1000 + "enum": [ + "bash" + ], + "description": "The type of tool. \"bash\" for Bash tool." }, - "endCallMessage": { + "subType": { "type": "string", - "description": "This is the message that the assistant will say if it ends the call.\n\nIf unspecified, it will hang up without saying anything.", - "maxLength": 1000 - }, - "endCallPhrases": { - "description": "This list contains phrases that, if spoken by the assistant, will trigger the call to be hung up. Case insensitive.", - "type": "array", - "items": { - "type": "string", - "maxLength": 140, - "minLength": 2 - } - }, - "compliancePlan": { - "$ref": "#/components/schemas/CompliancePlan" - }, - "metadata": { - "type": "object", - "description": "This is for metadata you want to store on the assistant." + "enum": [ + "bash_20241022" + ], + "description": "The sub type of tool." }, - "backgroundSpeechDenoisingPlan": { - "description": "This enables filtering of noise and background speech while the user is talking.\n\nFeatures:\n- Smart denoising using Krisp\n- Fourier denoising\n\nSmart denoising can be combined with or used independently of Fourier denoising.\n\nOrder of precedence:\n- Smart denoising\n- Fourier denoising", + "server": { + "description": "\n This is the server where a `tool-calls` webhook will be sent.\n\n Notes:\n - Webhook is sent to this server when a tool call is made.\n - Webhook contains the call, assistant, and phone number objects.\n - Webhook contains the variables set on the assistant.\n - Webhook is sent to the first available URL in this order: {{tool.server.url}}, {{assistant.server.url}}, {{phoneNumber.server.url}}, {{org.server.url}}.\n - Webhook expects a response with tool call result.", "allOf": [ { - "$ref": "#/components/schemas/BackgroundSpeechDenoisingPlan" + "$ref": "#/components/schemas/Server" } ] }, - "analysisPlan": { - "description": "This is the plan for analysis of assistant's calls. Stored in `call.analysis`.", - "allOf": [ - { - "$ref": "#/components/schemas/AnalysisPlan" - } + "name": { + "type": "string", + "description": "The name of the tool, fixed to 'bash'", + "default": "bash", + "enum": [ + "bash" ] }, - "artifactPlan": { - "description": "This is the plan for artifacts generated during assistant's calls. Stored in `call.artifact`.", + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", "allOf": [ { - "$ref": "#/components/schemas/ArtifactPlan" + "$ref": "#/components/schemas/ToolRejectionPlan" } ] + } + }, + "required": [ + "type", + "subType", + "name" + ] + }, + "CreateComputerToolDTO": { + "type": "object", + "properties": { + "messages": { + "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" + }, + { + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] + } }, - "startSpeakingPlan": { - "description": "This is the plan for when the assistant should start talking.\n\nYou should configure this if you're running into these issues:\n- The assistant is too slow to start talking after the customer is done speaking.\n- The assistant is too fast to start talking after the customer is done speaking.\n- The assistant is so fast that it's actually interrupting the customer.", + "type": { + "type": "string", + "enum": [ + "computer" + ], + "description": "The type of tool. \"computer\" for Computer tool." + }, + "subType": { + "type": "string", + "enum": [ + "computer_20241022" + ], + "description": "The sub type of tool." + }, + "server": { + "description": "\n This is the server where a `tool-calls` webhook will be sent.\n\n Notes:\n - Webhook is sent to this server when a tool call is made.\n - Webhook contains the call, assistant, and phone number objects.\n - Webhook contains the variables set on the assistant.\n - Webhook is sent to the first available URL in this order: {{tool.server.url}}, {{assistant.server.url}}, {{phoneNumber.server.url}}, {{org.server.url}}.\n - Webhook expects a response with tool call result.", "allOf": [ { - "$ref": "#/components/schemas/StartSpeakingPlan" + "$ref": "#/components/schemas/Server" } ] }, - "stopSpeakingPlan": { - "description": "This is the plan for when assistant should stop talking on customer interruption.\n\nYou should configure this if you're running into these issues:\n- The assistant is too slow to recognize customer's interruption.\n- The assistant is too fast to recognize customer's interruption.\n- The assistant is getting interrupted by phrases that are just acknowledgments.\n- The assistant is getting interrupted by background noises.\n- The assistant is not properly stopping -- it starts talking right after getting interrupted.", - "allOf": [ - { - "$ref": "#/components/schemas/StopSpeakingPlan" - } + "name": { + "type": "string", + "description": "The name of the tool, fixed to 'computer'", + "default": "computer", + "enum": [ + "computer" ] }, - "monitorPlan": { - "description": "This is the plan for real-time monitoring of the assistant's calls.\n\nUsage:\n- To enable live listening of the assistant's calls, set `monitorPlan.listenEnabled` to `true`.\n- To enable live control of the assistant's calls, set `monitorPlan.controlEnabled` to `true`.", + "displayWidthPx": { + "type": "number", + "description": "The display width in pixels" + }, + "displayHeightPx": { + "type": "number", + "description": "The display height in pixels" + }, + "displayNumber": { + "type": "number", + "description": "Optional display number" + }, + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", "allOf": [ { - "$ref": "#/components/schemas/MonitorPlan" + "$ref": "#/components/schemas/ToolRejectionPlan" } ] - }, - "credentialIds": { - "description": "These are the credentials that will be used for the assistant calls. By default, all the credentials are available for use in the call but you can provide a subset using this.", + } + }, + "required": [ + "type", + "subType", + "name", + "displayWidthPx", + "displayHeightPx" + ] + }, + "CreateTextEditorToolDTO": { + "type": "object", + "properties": { + "messages": { "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", "items": { - "type": "string" + "oneOf": [ + { + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" + }, + { + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] } }, + "type": { + "type": "string", + "enum": [ + "textEditor" + ], + "description": "The type of tool. \"textEditor\" for Text Editor tool." + }, + "subType": { + "type": "string", + "enum": [ + "text_editor_20241022" + ], + "description": "The sub type of tool." + }, "server": { - "description": "This is where Vapi will send webhooks. You can find all webhooks available along with their shape in ServerMessage schema.\n\nThe order of precedence is:\n\n1. assistant.server.url\n2. phoneNumber.serverUrl\n3. org.serverUrl", + "description": "\n This is the server where a `tool-calls` webhook will be sent.\n\n Notes:\n - Webhook is sent to this server when a tool call is made.\n - Webhook contains the call, assistant, and phone number objects.\n - Webhook contains the variables set on the assistant.\n - Webhook is sent to the first available URL in this order: {{tool.server.url}}, {{assistant.server.url}}, {{phoneNumber.server.url}}, {{org.server.url}}.\n - Webhook expects a response with tool call result.", "allOf": [ { "$ref": "#/components/schemas/Server" } ] }, - "keypadInputPlan": { - "$ref": "#/components/schemas/KeypadInputPlan" - }, - "id": { - "type": "string", - "description": "This is the unique identifier for the assistant." - }, - "orgId": { - "type": "string", - "description": "This is the unique identifier for the org that this assistant belongs to." - }, - "createdAt": { - "format": "date-time", + "name": { "type": "string", - "description": "This is the ISO 8601 date-time string of when the assistant was created." + "description": "The name of the tool, fixed to 'str_replace_editor'", + "default": "str_replace_editor", + "enum": [ + "str_replace_editor" + ] }, - "updatedAt": { - "format": "date-time", - "type": "string", - "description": "This is the ISO 8601 date-time string of when the assistant was last updated." + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "allOf": [ + { + "$ref": "#/components/schemas/ToolRejectionPlan" + } + ] } }, "required": [ - "id", - "orgId", - "createdAt", - "updatedAt" + "type", + "subType", + "name" ] }, - "AssistantPaginatedResponse": { + "CreateSmsToolDTO": { "type": "object", "properties": { - "results": { + "messages": { "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", "items": { - "$ref": "#/components/schemas/Assistant" + "oneOf": [ + { + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" + }, + { + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] } }, - "metadata": { - "$ref": "#/components/schemas/PaginationMeta" - } - }, - "required": [ - "results", - "metadata" - ] - }, - "AssistantVersionPaginatedResponse": { - "type": "object", - "properties": { - "results": { - "type": "array" - }, - "metadata": { - "$ref": "#/components/schemas/PaginationMeta" + "type": { + "type": "string", + "enum": [ + "sms" + ], + "description": "The type of tool. \"sms\" for Twilio SMS sending tool." }, - "nextPageState": { - "type": "string" + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "allOf": [ + { + "$ref": "#/components/schemas/ToolRejectionPlan" + } + ] } }, "required": [ - "results", - "metadata" + "type" ] }, - "UpdateAssistantDTO": { + "CreateSipRequestToolDTO": { "type": "object", "properties": { - "transcriber": { - "description": "These are the options for the assistant's transcriber.", - "oneOf": [ - { - "$ref": "#/components/schemas/AssemblyAITranscriber", - "title": "AssemblyAITranscriber" - }, - { - "$ref": "#/components/schemas/AzureSpeechTranscriber", - "title": "AzureSpeechTranscriber" - }, - { - "$ref": "#/components/schemas/CustomTranscriber", - "title": "CustomTranscriber" - }, - { - "$ref": "#/components/schemas/DeepgramTranscriber", - "title": "DeepgramTranscriber" - }, - { - "$ref": "#/components/schemas/ElevenLabsTranscriber", - "title": "ElevenLabsTranscriber" - }, - { - "$ref": "#/components/schemas/GladiaTranscriber", - "title": "GladiaTranscriber" - }, - { - "$ref": "#/components/schemas/GoogleTranscriber", - "title": "GoogleTranscriber" - }, - { - "$ref": "#/components/schemas/SpeechmaticsTranscriber", - "title": "SpeechmaticsTranscriber" - }, - { - "$ref": "#/components/schemas/TalkscriberTranscriber", - "title": "TalkscriberTranscriber" - }, - { - "$ref": "#/components/schemas/OpenAITranscriber", - "title": "OpenAITranscriber" - }, - { - "$ref": "#/components/schemas/CartesiaTranscriber", - "title": "CartesiaTranscriber" - } - ] + "messages": { + "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" + }, + { + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] + } }, - "model": { - "description": "These are the options for the assistant's LLM.", - "oneOf": [ - { - "$ref": "#/components/schemas/AnthropicModel", - "title": "Anthropic" - }, - { - "$ref": "#/components/schemas/AnyscaleModel", - "title": "Anyscale" - }, - { - "$ref": "#/components/schemas/CerebrasModel", - "title": "Cerebras" - }, - { - "$ref": "#/components/schemas/CustomLLMModel", - "title": "CustomLLM" - }, - { - "$ref": "#/components/schemas/DeepInfraModel", - "title": "DeepInfra" - }, - { - "$ref": "#/components/schemas/DeepSeekModel", - "title": "DeepSeek" - }, - { - "$ref": "#/components/schemas/GoogleModel", - "title": "Google" - }, - { - "$ref": "#/components/schemas/GroqModel", - "title": "Groq" - }, - { - "$ref": "#/components/schemas/InflectionAIModel", - "title": "InflectionAI" - }, - { - "$ref": "#/components/schemas/OpenAIModel", - "title": "OpenAI" - }, - { - "$ref": "#/components/schemas/OpenRouterModel", - "title": "OpenRouter" - }, - { - "$ref": "#/components/schemas/PerplexityAIModel", - "title": "PerplexityAI" - }, - { - "$ref": "#/components/schemas/TogetherAIModel", - "title": "Together" - }, - { - "$ref": "#/components/schemas/XaiModel", - "title": "XAI" - } - ] + "type": { + "type": "string", + "enum": [ + "sipRequest" + ], + "description": "The type of tool. \"sipRequest\" for SIP request tool." }, - "voice": { - "description": "These are the options for the assistant's voice.", - "oneOf": [ - { - "$ref": "#/components/schemas/AzureVoice", - "title": "AzureVoice" - }, - { - "$ref": "#/components/schemas/CartesiaVoice", - "title": "CartesiaVoice" - }, - { - "$ref": "#/components/schemas/CustomVoice", - "title": "CustomVoice" - }, - { - "$ref": "#/components/schemas/DeepgramVoice", - "title": "DeepgramVoice" - }, - { - "$ref": "#/components/schemas/ElevenLabsVoice", - "title": "ElevenLabsVoice" - }, - { - "$ref": "#/components/schemas/HumeVoice", - "title": "HumeVoice" - }, - { - "$ref": "#/components/schemas/LMNTVoice", - "title": "LMNTVoice" - }, - { - "$ref": "#/components/schemas/NeuphonicVoice", - "title": "NeuphonicVoice" - }, - { - "$ref": "#/components/schemas/OpenAIVoice", - "title": "OpenAIVoice" - }, - { - "$ref": "#/components/schemas/PlayHTVoice", - "title": "PlayHTVoice" - }, - { - "$ref": "#/components/schemas/RimeAIVoice", - "title": "RimeAIVoice" - }, - { - "$ref": "#/components/schemas/SmallestAIVoice", - "title": "SmallestAIVoice" - }, - { - "$ref": "#/components/schemas/TavusVoice", - "title": "TavusVoice" - }, + "verb": { + "type": "string", + "enum": [ + "INFO", + "MESSAGE", + "NOTIFY" + ], + "description": "The SIP method to send." + }, + "headers": { + "description": "JSON schema for headers the model should populate when sending the SIP request.", + "allOf": [ { - "$ref": "#/components/schemas/VapiVoice", - "title": "VapiVoice" - }, + "$ref": "#/components/schemas/JsonSchema" + } + ] + }, + "body": { + "description": "Body to include in the SIP request. Either a literal string body, or a JSON schema describing a structured body that the model should populate.", + "oneOf": [ { - "$ref": "#/components/schemas/SesameVoice", - "title": "SesameVoice" + "type": "string" }, { - "$ref": "#/components/schemas/InworldVoice", - "title": "InworldVoice" - }, + "$ref": "#/components/schemas/JsonSchema" + } + ] + }, + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "allOf": [ { - "$ref": "#/components/schemas/MinimaxVoice", - "title": "MinimaxVoice" + "$ref": "#/components/schemas/ToolRejectionPlan" } ] + } + }, + "required": [ + "type", + "verb" + ] + }, + "UpdateApiRequestToolDTO": { + "type": "object", + "properties": { + "messages": { + "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" + }, + { + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] + } }, - "firstMessage": { + "type": { "type": "string", - "description": "This is the first message that the assistant will say. This can also be a URL to a containerized audio file (mp3, wav, etc.).\n\nIf unspecified, assistant will wait for user to speak and use the model to respond once they speak.", - "example": "Hello! How can I help you today?" + "enum": [ + "apiRequest" + ], + "description": "The type of tool. \"apiRequest\" for API request tool." }, - "firstMessageInterruptionsEnabled": { - "type": "boolean", - "default": false + "name": { + "type": "string", + "description": "This is the name of the tool. This will be passed to the model.\n\nMust be a-z, A-Z, 0-9, or contain underscores and dashes, with a maximum length of 40.", + "maxLength": 40, + "pattern": "/^[a-zA-Z0-9_-]{1,40}$/" }, - "firstMessageMode": { + "method": { "type": "string", - "description": "This is the mode for the first message. Default is 'assistant-speaks-first'.\n\nUse:\n- 'assistant-speaks-first' to have the assistant speak first.\n- 'assistant-waits-for-user' to have the assistant wait for the user to speak first.\n- 'assistant-speaks-first-with-model-generated-message' to have the assistant speak first with a message generated by the model based on the conversation state. (`assistant.model.messages` at call start, `call.messages` at squad transfer points).\n\n@default 'assistant-speaks-first'", "enum": [ - "assistant-speaks-first", - "assistant-speaks-first-with-model-generated-message", - "assistant-waits-for-user" - ], - "example": "assistant-speaks-first" + "POST", + "GET", + "PUT", + "PATCH", + "DELETE" + ] }, - "voicemailDetection": { - "description": "These are the settings to configure or disable voicemail detection. Alternatively, voicemail detection can be configured using the model.tools=[VoicemailTool].\nThis uses Twilio's built-in detection while the VoicemailTool relies on the model to detect if a voicemail was reached.\nYou can use neither of them, one of them, or both of them. By default, Twilio built-in detection is enabled while VoicemailTool is not.", - "oneOf": [ + "timeoutSeconds": { + "type": "number", + "description": "This is the timeout in seconds for the request. Defaults to 20 seconds.\n\n@default 20", + "minimum": 1, + "maximum": 300, + "example": 20 + }, + "credentialId": { + "type": "string", + "description": "The credential ID for API request authentication", + "example": "550e8400-e29b-41d4-a716-446655440000" + }, + "encryptedPaths": { + "type": "array", + "description": "This is the paths to encrypt in the request body if credentialId and encryptionPlan are defined.", + "items": { + "type": "string" + } + }, + "parameters": { + "description": "Static key-value pairs merged into the request body. Values support Liquid templates.", + "type": "array", + "items": { + "$ref": "#/components/schemas/ToolParameter" + } + }, + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "allOf": [ { - "$ref": "#/components/schemas/GoogleVoicemailDetectionPlan", - "title": "Google" - }, + "$ref": "#/components/schemas/ToolRejectionPlan" + } + ] + }, + "description": { + "type": "string", + "description": "This is the description of the tool. This will be passed to the model." + }, + "url": { + "type": "string", + "description": "This is where the request will be sent." + }, + "body": { + "description": "This is the body of the request.", + "allOf": [ { - "$ref": "#/components/schemas/OpenAIVoicemailDetectionPlan", - "title": "OpenAI" - }, + "$ref": "#/components/schemas/JsonSchema" + } + ] + }, + "headers": { + "description": "These are the headers to send with the request.", + "allOf": [ { - "$ref": "#/components/schemas/TwilioVoicemailDetectionPlan", - "title": "Twilio" - }, + "$ref": "#/components/schemas/JsonSchema" + } + ] + }, + "backoffPlan": { + "description": "This is the backoff plan if the request fails. Defaults to undefined (the request will not be retried).\n\n@default undefined (the request will not be retried)", + "allOf": [ { - "$ref": "#/components/schemas/VapiVoicemailDetectionPlan", - "title": "Vapi" + "$ref": "#/components/schemas/BackoffPlan" } ] }, - "clientMessages": { + "variableExtractionPlan": { + "description": "This is the plan to extract variables from the tool's response. These will be accessible during the call and stored in `call.artifact.variableValues` after the call.\n\nUsage:\n1. Use `aliases` to extract variables from the tool's response body. (Most common case)\n\n```json\n{\n \"aliases\": [\n {\n \"key\": \"customerName\",\n \"value\": \"{{customer.name}}\"\n },\n {\n \"key\": \"customerAge\",\n \"value\": \"{{customer.age}}\"\n }\n ]\n}\n```\n\nThe tool response body is made available to the liquid template.\n\n2. Use `aliases` to extract variables from the tool's response body if the response is an array.\n\n```json\n{\n \"aliases\": [\n {\n \"key\": \"customerName\",\n \"value\": \"{{$[0].name}}\"\n },\n {\n \"key\": \"customerAge\",\n \"value\": \"{{$[0].age}}\"\n }\n ]\n}\n```\n\n$ is a shorthand for the tool's response body. `$[0]` is the first item in the array. `$[n]` is the nth item in the array. Note, $ is available regardless of the response body type (both object and array).\n\n3. Use `aliases` to extract variables from the tool's response headers.\n\n```json\n{\n \"aliases\": [\n {\n \"key\": \"customerName\",\n \"value\": \"{{tool.response.headers.customer-name}}\"\n },\n {\n \"key\": \"customerAge\",\n \"value\": \"{{tool.response.headers.customer-age}}\"\n }\n ]\n}\n```\n\n`tool.response` is made available to the liquid template. Particularly, both `tool.response.headers` and `tool.response.body` are available. Note, `tool.response` is available regardless of the response body type (both object and array).\n\n4. Use `schema` to extract a large portion of the tool's response body.\n\n4.1. If you hit example.com and it returns `{\"name\": \"John\", \"age\": 30}`, then you can specify the schema as:\n\n```json\n{\n \"schema\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n },\n \"age\": {\n \"type\": \"number\"\n }\n }\n }\n}\n```\nThese will be extracted as `{{ name }}` and `{{ age }}` respectively. To emphasize, object properties are extracted as direct global variables.\n\n4.2. If you hit example.com and it returns `{\"name\": {\"first\": \"John\", \"last\": \"Doe\"}}`, then you can specify the schema as:\n\n```json\n{\n \"schema\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"object\",\n \"properties\": {\n \"first\": {\n \"type\": \"string\"\n },\n \"last\": {\n \"type\": \"string\"\n }\n }\n }\n }\n }\n}\n```\n\nThese will be extracted as `{{ name }}`. And, `{{ name.first }}` and `{{ name.last }}` will be accessible.\n\n4.3. If you hit example.com and it returns `[\"94123\", \"94124\"]`, then you can specify the schema as:\n\n```json\n{\n \"schema\": {\n \"type\": \"array\",\n \"title\": \"zipCodes\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n}\n```\n\nThis will be extracted as `{{ zipCodes }}`. To access the array items, you can use `{{ zipCodes[0] }}` and `{{ zipCodes[1] }}`.\n\n4.4. If you hit example.com and it returns `[{\"name\": \"John\", \"age\": 30, \"zipCodes\": [\"94123\", \"94124\"]}, {\"name\": \"Jane\", \"age\": 25, \"zipCodes\": [\"94125\", \"94126\"]}]`, then you can specify the schema as:\n\n```json\n{\n \"schema\": {\n \"type\": \"array\",\n \"title\": \"people\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n },\n \"age\": {\n \"type\": \"number\"\n },\n \"zipCodes\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n }\n }\n }\n}\n```\n\nThis will be extracted as `{{ people }}`. To access the array items, you can use `{{ people[n].name }}`, `{{ people[n].age }}`, `{{ people[n].zipCodes }}`, `{{ people[n].zipCodes[0] }}` and `{{ people[n].zipCodes[1] }}`.\n\nNote: Both `aliases` and `schema` can be used together.", + "allOf": [ + { + "$ref": "#/components/schemas/VariableExtractionPlan" + } + ] + } + } + }, + "UpdateCodeToolDTO": { + "type": "object", + "properties": { + "messages": { "type": "array", - "enum": [ - "conversation-update", - "function-call", - "function-call-result", - "hang", - "language-changed", - "metadata", - "model-output", - "speech-update", - "status-update", - "transcript", - "tool-calls", - "tool-calls-result", - "tool.completed", - "transfer-update", - "user-interrupted", - "voice-input", - "workflow.node.started" - ], - "example": [ - "conversation-update", - "function-call", - "hang", - "model-output", - "speech-update", - "status-update", - "transfer-update", - "transcript", - "tool-calls", - "user-interrupted", - "voice-input", - "workflow.node.started" - ], - "description": "These are the messages that will be sent to your Client SDKs. Default is conversation-update,function-call,hang,model-output,speech-update,status-update,transfer-update,transcript,tool-calls,user-interrupted,voice-input,workflow.node.started. You can check the shape of the messages in ClientMessage schema.", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", "items": { - "type": "string", - "enum": [ - "conversation-update", - "function-call", - "function-call-result", - "hang", - "language-changed", - "metadata", - "model-output", - "speech-update", - "status-update", - "transcript", - "tool-calls", - "tool-calls-result", - "tool.completed", - "transfer-update", - "user-interrupted", - "voice-input", - "workflow.node.started" + "oneOf": [ + { + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" + }, + { + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } ] } }, - "serverMessages": { - "type": "array", + "type": { + "type": "string", "enum": [ - "conversation-update", - "end-of-call-report", - "function-call", - "hang", - "language-changed", - "language-change-detected", - "model-output", - "phone-call-control", - "speech-update", - "status-update", - "transcript", - "transcript[transcriptType=\"final\"]", - "tool-calls", - "transfer-destination-request", - "handoff-destination-request", - "transfer-update", - "user-interrupted", - "voice-input", - "chat.created", - "chat.deleted", - "session.created", - "session.updated", - "session.deleted" - ], - "example": [ - "conversation-update", - "end-of-call-report", - "function-call", - "hang", - "speech-update", - "status-update", - "tool-calls", - "transfer-destination-request", - "handoff-destination-request", - "user-interrupted" + "code" ], - "description": "These are the messages that will be sent to your Server URL. Default is conversation-update,end-of-call-report,function-call,hang,speech-update,status-update,tool-calls,transfer-destination-request,handoff-destination-request,user-interrupted. You can check the shape of the messages in ServerMessage schema.", + "description": "The type of tool. \"code\" for Code tool." + }, + "async": { + "type": "boolean", + "example": false, + "description": "This determines if the tool is async.\n\n If async, the assistant will move forward without waiting for your server to respond. This is useful if you just want to trigger something on your server.\n\n If sync, the assistant will wait for your server to respond. This is useful if want assistant to respond with the result from your server.\n\n Defaults to synchronous (`false`)." + }, + "server": { + "description": "\n This is the server where a `tool-calls` webhook will be sent.\n\n Notes:\n - Webhook is sent to this server when a tool call is made.\n - Webhook contains the call, assistant, and phone number objects.\n - Webhook contains the variables set on the assistant.\n - Webhook is sent to the first available URL in this order: {{tool.server.url}}, {{assistant.server.url}}, {{phoneNumber.server.url}}, {{org.server.url}}.\n - Webhook expects a response with tool call result.", + "allOf": [ + { + "$ref": "#/components/schemas/Server" + } + ] + }, + "code": { + "type": "string", + "description": "TypeScript code to execute when the tool is called", + "maxLength": 50000 + }, + "environmentVariables": { + "description": "Environment variables available in code via `env` object", + "type": "array", "items": { - "type": "string", - "enum": [ - "conversation-update", - "end-of-call-report", - "function-call", - "hang", - "language-changed", - "language-change-detected", - "model-output", - "phone-call-control", - "speech-update", - "status-update", - "transcript", - "transcript[transcriptType=\"final\"]", - "tool-calls", - "transfer-destination-request", - "handoff-destination-request", - "transfer-update", - "user-interrupted", - "voice-input", - "chat.created", - "chat.deleted", - "session.created", - "session.updated", - "session.deleted" - ] + "$ref": "#/components/schemas/CodeToolEnvironmentVariable" } }, - "maxDurationSeconds": { + "timeoutSeconds": { "type": "number", - "description": "This is the maximum number of seconds that the call will last. When the call reaches this duration, it will be ended.\n\n@default 600 (10 minutes)", - "minimum": 10, - "maximum": 43200, - "example": 600 + "description": "This is the timeout in seconds for the code execution. Defaults to 10 seconds.\nMaximum is 30 seconds to prevent abuse.\n\n@default 10", + "minimum": 1, + "maximum": 30, + "example": 10 }, - "backgroundSound": { - "description": "This is the background sound in the call. Default for phone calls is 'office' and default for web calls is 'off'.\nYou can also provide a custom sound by providing a URL to an audio file.", - "oneOf": [ + "credentialId": { + "type": "string", + "description": "Credential ID containing the Val Town API key", + "example": "550e8400-e29b-41d4-a716-446655440000" + }, + "variableExtractionPlan": { + "description": "Plan to extract variables from the tool response", + "allOf": [ { - "type": "enum", - "enum": [ - "off", - "office" - ], - "example": "office" - }, + "$ref": "#/components/schemas/VariableExtractionPlan" + } + ] + }, + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "allOf": [ { - "type": "string", - "format": "uri", - "example": "https://www.soundjay.com/ambient/sounds/people-in-lounge-1.mp3" + "$ref": "#/components/schemas/ToolRejectionPlan" } ] }, - "modelOutputInMessagesEnabled": { + "function": { + "description": "This is the function definition of the tool.\n\nFor the Code tool, this defines the name, description, and parameters that the model\nwill use to understand when and how to call this tool.", + "allOf": [ + { + "$ref": "#/components/schemas/OpenAIFunction" + } + ] + } + } + }, + "UpdateDtmfToolDTO": { + "type": "object", + "properties": { + "messages": { + "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" + }, + { + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] + } + }, + "type": { + "type": "string", + "enum": [ + "dtmf" + ], + "description": "The type of tool. \"dtmf\" for DTMF tool." + }, + "sipInfoDtmfEnabled": { "type": "boolean", - "description": "This determines whether the model's output is used in conversation history rather than the transcription of assistant's speech.\n\nDefault `false` while in beta.\n\n@default false", - "example": false + "description": "This enables sending DTMF tones via SIP INFO messages instead of RFC 2833 (RTP events). When enabled, DTMF digits will be sent using the SIP INFO method, which can be more reliable in some network configurations. Only relevant when using the `vapi.sip` transport.", + "default": false }, - "transportConfigurations": { + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "allOf": [ + { + "$ref": "#/components/schemas/ToolRejectionPlan" + } + ] + } + } + }, + "UpdateEndCallToolDTO": { + "type": "object", + "properties": { + "messages": { "type": "array", - "description": "These are the configurations to be passed to the transport providers of assistant's calls, like Twilio. You can store multiple configurations for different transport providers. For a call, only the configuration matching the call transport provider is used.", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", "items": { "oneOf": [ { - "$ref": "#/components/schemas/TransportConfigurationTwilio", - "title": "Twilio" + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" + }, + { + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" } ] } }, - "observabilityPlan": { - "description": "This is the plan for observability of assistant's calls.\n\nCurrently, only Langfuse is supported.", - "oneOf": [ + "type": { + "type": "string", + "enum": [ + "endCall" + ], + "description": "The type of tool. \"endCall\" for End Call tool." + }, + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "allOf": [ + { + "$ref": "#/components/schemas/ToolRejectionPlan" + } + ] + } + } + }, + "UpdateFunctionToolDTO": { + "type": "object", + "properties": { + "messages": { + "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" + }, + { + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] + } + }, + "type": { + "type": "string", + "enum": [ + "function" + ], + "description": "The type of tool. \"function\" for Function tool." + }, + "async": { + "type": "boolean", + "example": false, + "description": "This determines if the tool is async.\n\n If async, the assistant will move forward without waiting for your server to respond. This is useful if you just want to trigger something on your server.\n\n If sync, the assistant will wait for your server to respond. This is useful if want assistant to respond with the result from your server.\n\n Defaults to synchronous (`false`)." + }, + "server": { + "description": "\n This is the server where a `tool-calls` webhook will be sent.\n\n Notes:\n - Webhook is sent to this server when a tool call is made.\n - Webhook contains the call, assistant, and phone number objects.\n - Webhook contains the variables set on the assistant.\n - Webhook is sent to the first available URL in this order: {{tool.server.url}}, {{assistant.server.url}}, {{phoneNumber.server.url}}, {{org.server.url}}.\n - Webhook expects a response with tool call result.", + "allOf": [ + { + "$ref": "#/components/schemas/Server" + } + ] + }, + "variableExtractionPlan": { + "description": "Plan to extract variables from the tool response", + "allOf": [ + { + "$ref": "#/components/schemas/VariableExtractionPlan" + } + ] + }, + "parameters": { + "description": "Static key-value pairs merged into the request body. Values support Liquid templates.", + "type": "array", + "items": { + "$ref": "#/components/schemas/ToolParameter" + } + }, + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "allOf": [ { - "$ref": "#/components/schemas/LangfuseObservabilityPlan", - "title": "Langfuse" + "$ref": "#/components/schemas/ToolRejectionPlan" } - ], + ] + }, + "function": { + "description": "This is the function definition of the tool.", "allOf": [ { - "$ref": "#/components/schemas/LangfuseObservabilityPlan" + "$ref": "#/components/schemas/OpenAIFunction" } ] - }, - "credentials": { + } + } + }, + "UpdateKnowledgeBaseToolDTO": { + "type": "object", + "properties": { + "messages": { "type": "array", - "description": "These are dynamic credentials that will be used for the assistant calls. By default, all the credentials are available for use in the call but you can supplement an additional credentials using this. Dynamic credentials override existing credentials.", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", "items": { "oneOf": [ { - "$ref": "#/components/schemas/CreateAnthropicCredentialDTO", - "title": "AnthropicCredential" - }, - { - "$ref": "#/components/schemas/CreateAnyscaleCredentialDTO", - "title": "AnyscaleCredential" - }, - { - "$ref": "#/components/schemas/CreateAssemblyAICredentialDTO", - "title": "AssemblyAICredential" - }, - { - "$ref": "#/components/schemas/CreateAzureCredentialDTO", - "title": "AzureCredential" - }, - { - "$ref": "#/components/schemas/CreateAzureOpenAICredentialDTO", - "title": "AzureOpenAICredential" - }, - { - "$ref": "#/components/schemas/CreateByoSipTrunkCredentialDTO", - "title": "ByoSipTrunkCredential" - }, - { - "$ref": "#/components/schemas/CreateCartesiaCredentialDTO", - "title": "CartesiaCredential" - }, - { - "$ref": "#/components/schemas/CreateCerebrasCredentialDTO", - "title": "CerebrasCredential" - }, - { - "$ref": "#/components/schemas/CreateCloudflareCredentialDTO", - "title": "CloudflareCredential" - }, - { - "$ref": "#/components/schemas/CreateCustomLLMCredentialDTO", - "title": "CustomLLMCredential" - }, - { - "$ref": "#/components/schemas/CreateDeepgramCredentialDTO", - "title": "DeepgramCredential" - }, - { - "$ref": "#/components/schemas/CreateDeepInfraCredentialDTO", - "title": "DeepInfraCredential" - }, - { - "$ref": "#/components/schemas/CreateDeepSeekCredentialDTO", - "title": "DeepSeekCredential" - }, - { - "$ref": "#/components/schemas/CreateElevenLabsCredentialDTO", - "title": "ElevenLabsCredential" - }, - { - "$ref": "#/components/schemas/CreateGcpCredentialDTO", - "title": "GcpCredential" - }, - { - "$ref": "#/components/schemas/CreateGladiaCredentialDTO", - "title": "GladiaCredential" + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" }, { - "$ref": "#/components/schemas/CreateGoHighLevelCredentialDTO", - "title": "GhlCredential" + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" }, { - "$ref": "#/components/schemas/CreateGoogleCredentialDTO", - "title": "GoogleCredential" + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" }, { - "$ref": "#/components/schemas/CreateGroqCredentialDTO", - "title": "GroqCredential" - }, + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] + } + }, + "type": { + "type": "string", + "enum": [ + "knowledgeBase" + ], + "description": "A Vapi-hosted knowledge base retrieval tool." + }, + "knowledgeBaseId": { + "type": "string", + "nullable": true, + "format": "uuid", + "description": "The knowledge base this tool searches. At most one search tool references a knowledge base. Deleting the base also deletes its generated tool; null references are retained only for backward compatibility and are inert." + }, + "function": { + "$ref": "#/components/schemas/KnowledgeBaseToolFunction" + }, + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "allOf": [ + { + "$ref": "#/components/schemas/ToolRejectionPlan" + } + ] + } + } + }, + "UpdateGhlToolDTO": { + "type": "object", + "properties": { + "messages": { + "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", + "items": { + "oneOf": [ { - "$ref": "#/components/schemas/CreateHumeCredentialDTO", - "title": "HumeCredential" + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" }, { - "$ref": "#/components/schemas/CreateInflectionAICredentialDTO", - "title": "InflectionAICredential" + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" }, { - "$ref": "#/components/schemas/CreateLangfuseCredentialDTO", - "title": "LangfuseCredential" + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" }, { - "$ref": "#/components/schemas/CreateLmntCredentialDTO", - "title": "LmntCredential" - }, + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] + } + }, + "type": { + "type": "string", + "enum": [ + "ghl" + ], + "description": "The type of tool. \"ghl\" for GHL tool." + }, + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "allOf": [ + { + "$ref": "#/components/schemas/ToolRejectionPlan" + } + ] + }, + "metadata": { + "$ref": "#/components/schemas/GhlToolMetadata" + } + } + }, + "UpdateMakeToolDTO": { + "type": "object", + "properties": { + "messages": { + "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", + "items": { + "oneOf": [ { - "$ref": "#/components/schemas/CreateMakeCredentialDTO", - "title": "MakeCredential" + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" }, { - "$ref": "#/components/schemas/CreateMistralCredentialDTO", - "title": "MistralCredential" + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" }, { - "$ref": "#/components/schemas/CreateNeuphonicCredentialDTO", - "title": "NeuphonicCredential" + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" }, { - "$ref": "#/components/schemas/CreateOpenAICredentialDTO", - "title": "OpenAICredential" - }, + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] + } + }, + "type": { + "type": "string", + "enum": [ + "make" + ], + "description": "The type of tool. \"make\" for Make tool." + }, + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "allOf": [ + { + "$ref": "#/components/schemas/ToolRejectionPlan" + } + ] + }, + "metadata": { + "$ref": "#/components/schemas/MakeToolMetadata" + } + } + }, + "UpdateHandoffToolDTO": { + "type": "object", + "properties": { + "messages": { + "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", + "items": { + "oneOf": [ { - "$ref": "#/components/schemas/CreateOpenRouterCredentialDTO", - "title": "OpenRouterCredential" + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" }, { - "$ref": "#/components/schemas/CreatePerplexityAICredentialDTO", - "title": "PerplexityAICredential" + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" }, { - "$ref": "#/components/schemas/CreatePlayHTCredentialDTO", - "title": "PlayHTCredential" + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" }, { - "$ref": "#/components/schemas/CreateRimeAICredentialDTO", - "title": "RimeAICredential" - }, + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] + } + }, + "type": { + "type": "string", + "description": "This is the type of the tool.\nWhen you're using handoff tool, we recommend adding this to your system prompt\n---\n# System context\n\nYou are part of a multi-agent system designed to make agent coordination and execution easy. Agents uses two primary abstraction: **Agents** and **Handoffs**. An agent encompasses instructions and tools and can hand off a conversation to another agent when appropriate. Handoffs are achieved by calling a handoff function, generally named `handoff_to_`. Handoffs between agents are handled seamlessly in the background; do not mention or draw attention to these handoffs in your conversation with the user.\n\n# Agent context\n\n{put your agent system prompt here}\n---", + "enum": [ + "handoff" + ] + }, + "defaultResult": { + "type": "string", + "description": "This is the default local tool result message used when no runtime handoff result override is returned." + }, + "destinations": { + "type": "array", + "description": "These are the destinations that the call can be handed off to.\n\nUsage:\n1. Single destination\n\nUse `assistantId` to handoff the call to a saved assistant, or `assistantName` to handoff the call to an assistant in the same squad.\n\n```json\n{\n \"tools\": [\n {\n \"type\": \"handoff\",\n \"destinations\": [\n {\n \"type\": \"assistant\",\n \"assistantId\": \"assistant-123\", // or \"assistantName\": \"Assistant123\"\n \"description\": \"customer wants to be handed off to assistant-123\",\n \"contextEngineeringPlan\": {\n \"type\": \"all\"\n }\n }\n ],\n }\n ]\n}\n```\n\n2. Multiple destinations\n\n2.1. Multiple Tools, Each With One Destination (OpenAI recommended)\n\n```json\n{\n \"tools\": [\n {\n \"type\": \"handoff\",\n \"destinations\": [\n {\n \"type\": \"assistant\",\n \"assistantId\": \"assistant-123\",\n \"description\": \"customer wants to be handed off to assistant-123\",\n \"contextEngineeringPlan\": {\n \"type\": \"all\"\n }\n },\n ],\n },\n {\n \"type\": \"handoff\",\n \"destinations\": [\n {\n \"type\": \"assistant\",\n \"assistantId\": \"assistant-456\",\n \"description\": \"customer wants to be handed off to assistant-456\",\n \"contextEngineeringPlan\": {\n \"type\": \"all\"\n }\n }\n ],\n }\n ]\n}\n```\n\n2.2. One Tool, Multiple Destinations (Anthropic recommended)\n\n```json\n{\n \"tools\": [\n {\n \"type\": \"handoff\",\n \"destinations\": [\n {\n \"type\": \"assistant\",\n \"assistantId\": \"assistant-123\",\n \"description\": \"customer wants to be handed off to assistant-123\",\n \"contextEngineeringPlan\": {\n \"type\": \"all\"\n }\n },\n {\n \"type\": \"assistant\",\n \"assistantId\": \"assistant-456\",\n \"description\": \"customer wants to be handed off to assistant-456\",\n \"contextEngineeringPlan\": {\n \"type\": \"all\"\n }\n }\n ],\n }\n ]\n}\n```\n\n3. Dynamic destination\n\n3.1 To determine the destination dynamically, supply a `dynamic` handoff destination type and a `server` object.\n VAPI will send a handoff-destination-request webhook to the `server.url`.\n The response from the server will be used as the destination (if valid).\n\n```json\n{\n \"tools\": [\n {\n \"type\": \"handoff\",\n \"destinations\": [\n {\n \"type\": \"dynamic\",\n \"server\": {\n \"url\": \"https://example.com\"\n }\n }\n ],\n }\n ]\n}\n```\n\n3.2. To pass custom parameters to the server, you can use the `function` object.\n\n```json\n{\n \"tools\": [\n {\n \"type\": \"handoff\",\n \"destinations\": [\n {\n \"type\": \"dynamic\",\n \"server\": {\n \"url\": \"https://example.com\"\n },\n }\n ],\n \"function\": {\n \"name\": \"handoff\",\n \"description\": \"Call this function when the customer is ready to be handed off to the next assistant\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"destination\": {\n \"type\": \"string\",\n \"description\": \"Use dynamic when customer is ready to be handed off to the next assistant\",\n \"enum\": [\"dynamic\"]\n },\n \"customerAreaCode\": {\n \"type\": \"number\",\n \"description\": \"Area code of the customer\"\n },\n \"customerIntent\": {\n \"type\": \"string\",\n \"enum\": [\"new-customer\", \"existing-customer\"],\n \"description\": \"Use new-customer when customer is a new customer, existing-customer when customer is an existing customer\"\n },\n \"customerSentiment\": {\n \"type\": \"string\",\n \"enum\": [\"positive\", \"negative\", \"neutral\"],\n \"description\": \"Use positive when customer is happy, negative when customer is unhappy, neutral when customer is neutral\"\n }\n }\n }\n }\n }\n ]\n}\n```\n\nThe properties `customerAreaCode`, `customerIntent`, and `customerSentiment` will be passed to the server in the webhook request body.", + "items": { + "oneOf": [ { - "$ref": "#/components/schemas/CreateRunpodCredentialDTO", - "title": "RunpodCredential" + "$ref": "#/components/schemas/HandoffDestinationAssistant", + "title": "Assistant" }, { - "$ref": "#/components/schemas/CreateS3CredentialDTO", - "title": "S3Credential" + "$ref": "#/components/schemas/HandoffDestinationDynamic", + "title": "Dynamic" }, { - "$ref": "#/components/schemas/CreateSmallestAICredentialDTO", - "title": "SmallestAICredential" - }, + "$ref": "#/components/schemas/HandoffDestinationSquad", + "title": "Squad" + } + ] + } + }, + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "allOf": [ + { + "$ref": "#/components/schemas/ToolRejectionPlan" + } + ] + }, + "function": { + "description": "This is the optional function definition that will be passed to the LLM.\nIf this is not defined, we will construct this based on the other properties.\n\nFor example, given the following tools definition:\n```json\n{\n \"tools\": [\n {\n \"type\": \"handoff\",\n \"destinations\": [\n {\n \"type\": \"assistant\",\n \"assistantId\": \"assistant-123\",\n \"description\": \"customer wants to be handed off to assistant-123\",\n \"contextEngineeringPlan\": {\n \"type\": \"all\"\n }\n },\n {\n \"type\": \"assistant\",\n \"assistantId\": \"assistant-456\",\n \"description\": \"customer wants to be handed off to assistant-456\",\n \"contextEngineeringPlan\": {\n \"type\": \"all\"\n }\n }\n ],\n }\n ]\n}\n```\n\nWe will construct the following function definition:\n```json\n{\n \"function\": {\n \"name\": \"handoff_to_assistant-123\",\n \"description\": \"\n Use this function to handoff the call to the next assistant.\n Only use it when instructions explicitly ask you to use the handoff_to_assistant function.\n DO NOT call this function unless you are instructed to do so.\n Here are the destinations you can handoff the call to:\n 1. assistant-123. When: customer wants to be handed off to assistant-123\n 2. assistant-456. When: customer wants to be handed off to assistant-456\n \",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"destination\": {\n \"type\": \"string\",\n \"description\": \"Options: assistant-123 (customer wants to be handed off to assistant-123), assistant-456 (customer wants to be handed off to assistant-456)\",\n \"enum\": [\"assistant-123\", \"assistant-456\"]\n },\n },\n \"required\": [\"destination\"]\n }\n }\n}\n```\n\nTo override this function, please provide an OpenAI function definition and refer to it in the system prompt.\nYou may override parts of the function definition (i.e. you may only want to change the function name for your prompt).\nIf you choose to override the function parameters, it must include `destination` as a required parameter, and it must evaluate to either an assistantId, assistantName, or a the string literal `dynamic`.\n\nTo pass custom parameters to the server in a dynamic handoff, you can use the function parameters, with `dynamic` as the destination.\n```json\n{\n \"function\": {\n \"name\": \"dynamic_handoff\",\n \"description\": \"\n Call this function when the customer is ready to be handed off to the next assistant\n \",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"destination\": {\n \"type\": \"string\",\n \"enum\": [\"dynamic\"]\n },\n \"customerAreaCode\": {\n \"type\": \"number\",\n \"description\": \"Area code of the customer\"\n },\n \"customerIntent\": {\n \"type\": \"string\",\n \"enum\": [\"new-customer\", \"existing-customer\"],\n \"description\": \"Use new-customer when customer is a new customer, existing-customer when customer is an existing customer\"\n },\n \"customerSentiment\": {\n \"type\": \"string\",\n \"enum\": [\"positive\", \"negative\", \"neutral\"],\n \"description\": \"Use positive when customer is happy, negative when customer is unhappy, neutral when customer is neutral\"\n }\n },\n \"required\": [\"destination\", \"customerAreaCode\", \"customerIntent\", \"customerSentiment\"]\n }\n }\n}\n```", + "allOf": [ + { + "$ref": "#/components/schemas/OpenAIFunction" + } + ] + } + } + }, + "UpdateTransferCallToolDTO": { + "type": "object", + "properties": { + "messages": { + "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", + "items": { + "oneOf": [ { - "$ref": "#/components/schemas/CreateSpeechmaticsCredentialDTO", - "title": "SpeechmaticsCredential" + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" }, { - "$ref": "#/components/schemas/CreateSupabaseCredentialDTO", - "title": "SupabaseCredential" + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" }, { - "$ref": "#/components/schemas/CreateTavusCredentialDTO", - "title": "TavusCredential" + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" }, { - "$ref": "#/components/schemas/CreateTogetherAICredentialDTO", - "title": "TogetherAICredential" - }, + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] + } + }, + "type": { + "type": "string", + "enum": [ + "transferCall" + ] + }, + "destinations": { + "type": "array", + "description": "These are the destinations that the call can be transferred to. If no destinations are provided, server.url will be used to get the transfer destination once the tool is called.", + "items": { + "oneOf": [ { - "$ref": "#/components/schemas/CreateTrieveCredentialDTO", - "title": "TrieveCredential" + "$ref": "#/components/schemas/TransferDestinationAssistant", + "title": "Assistant" }, { - "$ref": "#/components/schemas/CreateTwilioCredentialDTO", - "title": "TwilioCredential" + "$ref": "#/components/schemas/TransferDestinationNumber", + "title": "Number" }, { - "$ref": "#/components/schemas/CreateVonageCredentialDTO", - "title": "VonageCredential" - }, + "$ref": "#/components/schemas/TransferDestinationSip", + "title": "Sip" + } + ] + } + }, + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "allOf": [ + { + "$ref": "#/components/schemas/ToolRejectionPlan" + } + ] + } + } + }, + "UpdateOutputToolDTO": { + "type": "object", + "properties": { + "messages": { + "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", + "items": { + "oneOf": [ { - "$ref": "#/components/schemas/CreateWebhookCredentialDTO", - "title": "WebhookCredential" + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" }, { - "$ref": "#/components/schemas/CreateXAiCredentialDTO", - "title": "XAiCredential" + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" }, { - "$ref": "#/components/schemas/CreateGoogleCalendarOAuth2ClientCredentialDTO", - "title": "GoogleCalendarOAuth2ClientCredential" + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" }, { - "$ref": "#/components/schemas/CreateGoogleCalendarOAuth2AuthorizationCredentialDTO", - "title": "GoogleCalendarOAuth2AuthorizationCredential" - }, + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] + } + }, + "type": { + "type": "string", + "enum": [ + "output" + ], + "description": "The type of tool. \"output\" for Output tool." + }, + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "allOf": [ + { + "$ref": "#/components/schemas/ToolRejectionPlan" + } + ] + } + } + }, + "UpdateBashToolDTO": { + "type": "object", + "properties": { + "messages": { + "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", + "items": { + "oneOf": [ { - "$ref": "#/components/schemas/CreateGoogleSheetsOAuth2AuthorizationCredentialDTO", - "title": "GoogleSheetsOAuth2AuthorizationCredential" + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" }, { - "$ref": "#/components/schemas/CreateSlackOAuth2AuthorizationCredentialDTO", - "title": "SlackOAuth2AuthorizationCredential" + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" }, { - "$ref": "#/components/schemas/CreateGoHighLevelMCPCredentialDTO", - "title": "GoHighLevelMCPCredential" + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" }, { - "$ref": "#/components/schemas/CreateInworldCredentialDTO", - "title": "InworldCredential" - } - ], - "discriminator": { - "propertyName": "provider", - "mapping": { - "11labs": "#/components/schemas/CreateElevenLabsCredentialDTO", - "anthropic": "#/components/schemas/CreateAnthropicCredentialDTO", - "anyscale": "#/components/schemas/CreateAnyscaleCredentialDTO", - "assembly-ai": "#/components/schemas/CreateAssemblyAICredentialDTO", - "azure-openai": "#/components/schemas/CreateAzureOpenAICredentialDTO", - "azure": "#/components/schemas/CreateAzureCredentialDTO", - "byo-sip-trunk": "#/components/schemas/CreateByoSipTrunkCredentialDTO", - "cartesia": "#/components/schemas/CreateCartesiaCredentialDTO", - "cerebras": "#/components/schemas/CreateCerebrasCredentialDTO", - "cloudflare": "#/components/schemas/CreateCloudflareCredentialDTO", - "custom-llm": "#/components/schemas/CreateCustomLLMCredentialDTO", - "deepgram": "#/components/schemas/CreateDeepgramCredentialDTO", - "deepinfra": "#/components/schemas/CreateDeepInfraCredentialDTO", - "deep-seek": "#/components/schemas/CreateDeepSeekCredentialDTO", - "gcp": "#/components/schemas/CreateGcpCredentialDTO", - "gladia": "#/components/schemas/CreateGladiaCredentialDTO", - "gohighlevel": "#/components/schemas/CreateGoHighLevelCredentialDTO", - "google": "#/components/schemas/CreateGoogleCredentialDTO", - "groq": "#/components/schemas/CreateGroqCredentialDTO", - "inflection-ai": "#/components/schemas/CreateInflectionAICredentialDTO", - "langfuse": "#/components/schemas/CreateLangfuseCredentialDTO", - "lmnt": "#/components/schemas/CreateLmntCredentialDTO", - "make": "#/components/schemas/CreateMakeCredentialDTO", - "openai": "#/components/schemas/CreateOpenAICredentialDTO", - "openrouter": "#/components/schemas/CreateOpenRouterCredentialDTO", - "perplexity-ai": "#/components/schemas/CreatePerplexityAICredentialDTO", - "playht": "#/components/schemas/CreatePlayHTCredentialDTO", - "rime-ai": "#/components/schemas/CreateRimeAICredentialDTO", - "runpod": "#/components/schemas/CreateRunpodCredentialDTO", - "s3": "#/components/schemas/CreateS3CredentialDTO", - "supabase": "#/components/schemas/CreateSupabaseCredentialDTO", - "smallest-ai": "#/components/schemas/CreateSmallestAICredentialDTO", - "tavus": "#/components/schemas/CreateTavusCredentialDTO", - "together-ai": "#/components/schemas/CreateTogetherAICredentialDTO", - "twilio": "#/components/schemas/CreateTwilioCredentialDTO", - "vonage": "#/components/schemas/CreateVonageCredentialDTO", - "webhook": "#/components/schemas/CreateWebhookCredentialDTO", - "xai": "#/components/schemas/CreateXAiCredentialDTO", - "neuphonic": "#/components/schemas/CreateNeuphonicCredentialDTO", - "hume": "#/components/schemas/CreateHumeCredentialDTO", - "mistral": "#/components/schemas/CreateMistralCredentialDTO", - "speechmatics": "#/components/schemas/CreateSpeechmaticsCredentialDTO", - "trieve": "#/components/schemas/CreateTrieveCredentialDTO", - "google.calendar.oauth2-client": "#/components/schemas/CreateGoogleCalendarOAuth2ClientCredentialDTO", - "google.calendar.oauth2-authorization": "#/components/schemas/CreateGoogleCalendarOAuth2AuthorizationCredentialDTO", - "google.sheets.oauth2-authorization": "#/components/schemas/CreateGoogleSheetsOAuth2AuthorizationCredentialDTO", - "slack.oauth2-authorization": "#/components/schemas/CreateSlackOAuth2AuthorizationCredentialDTO", - "ghl.oauth2-authorization": "#/components/schemas/CreateGoHighLevelMCPCredentialDTO", - "inworld": "#/components/schemas/CreateInworldCredentialDTO", - "minimax": "#/components/schemas/CreateMinimaxCredentialDTO" + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" } - } + ] } }, - "hooks": { + "type": { + "type": "string", + "enum": [ + "bash" + ], + "description": "The type of tool. \"bash\" for Bash tool." + }, + "subType": { + "type": "string", + "enum": [ + "bash_20241022" + ], + "description": "The sub type of tool." + }, + "server": { + "description": "\n This is the server where a `tool-calls` webhook will be sent.\n\n Notes:\n - Webhook is sent to this server when a tool call is made.\n - Webhook contains the call, assistant, and phone number objects.\n - Webhook contains the variables set on the assistant.\n - Webhook is sent to the first available URL in this order: {{tool.server.url}}, {{assistant.server.url}}, {{phoneNumber.server.url}}, {{org.server.url}}.\n - Webhook expects a response with tool call result.", + "allOf": [ + { + "$ref": "#/components/schemas/Server" + } + ] + }, + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "allOf": [ + { + "$ref": "#/components/schemas/ToolRejectionPlan" + } + ] + }, + "name": { + "type": "string", + "description": "The name of the tool, fixed to 'bash'", + "default": "bash", + "enum": [ + "bash" + ] + } + } + }, + "UpdateComputerToolDTO": { + "type": "object", + "properties": { + "messages": { "type": "array", - "description": "This is a set of actions that will be performed on certain events.", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", "items": { "oneOf": [ { - "$ref": "#/components/schemas/CallHookCallEnding", - "title": "CallHookCallEnding" + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" }, { - "$ref": "#/components/schemas/CallHookAssistantSpeechInterrupted", - "title": "CallHookAssistantSpeechInterrupted" + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" }, { - "$ref": "#/components/schemas/CallHookCustomerSpeechInterrupted", - "title": "CallHookCustomerSpeechInterrupted" + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" }, { - "$ref": "#/components/schemas/CallHookCustomerSpeechTimeout", - "title": "CallHookCustomerSpeechTimeout" + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" } ] } }, - "name": { - "type": "string", - "description": "This is the name of the assistant.\n\nThis is required when you want to transfer between assistants in a call.", - "maxLength": 40 - }, - "voicemailMessage": { + "type": { "type": "string", - "description": "This is the message that the assistant will say if the call is forwarded to voicemail.\n\nIf unspecified, it will hang up.", - "maxLength": 1000 + "enum": [ + "computer" + ], + "description": "The type of tool. \"computer\" for Computer tool." }, - "endCallMessage": { + "subType": { "type": "string", - "description": "This is the message that the assistant will say if it ends the call.\n\nIf unspecified, it will hang up without saying anything.", - "maxLength": 1000 - }, - "endCallPhrases": { - "description": "This list contains phrases that, if spoken by the assistant, will trigger the call to be hung up. Case insensitive.", - "type": "array", - "items": { - "type": "string", - "maxLength": 140, - "minLength": 2 - } - }, - "compliancePlan": { - "$ref": "#/components/schemas/CompliancePlan" - }, - "metadata": { - "type": "object", - "description": "This is for metadata you want to store on the assistant." + "enum": [ + "computer_20241022" + ], + "description": "The sub type of tool." }, - "backgroundSpeechDenoisingPlan": { - "description": "This enables filtering of noise and background speech while the user is talking.\n\nFeatures:\n- Smart denoising using Krisp\n- Fourier denoising\n\nSmart denoising can be combined with or used independently of Fourier denoising.\n\nOrder of precedence:\n- Smart denoising\n- Fourier denoising", + "server": { + "description": "\n This is the server where a `tool-calls` webhook will be sent.\n\n Notes:\n - Webhook is sent to this server when a tool call is made.\n - Webhook contains the call, assistant, and phone number objects.\n - Webhook contains the variables set on the assistant.\n - Webhook is sent to the first available URL in this order: {{tool.server.url}}, {{assistant.server.url}}, {{phoneNumber.server.url}}, {{org.server.url}}.\n - Webhook expects a response with tool call result.", "allOf": [ { - "$ref": "#/components/schemas/BackgroundSpeechDenoisingPlan" + "$ref": "#/components/schemas/Server" } ] }, - "analysisPlan": { - "description": "This is the plan for analysis of assistant's calls. Stored in `call.analysis`.", + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", "allOf": [ { - "$ref": "#/components/schemas/AnalysisPlan" + "$ref": "#/components/schemas/ToolRejectionPlan" } ] }, - "artifactPlan": { - "description": "This is the plan for artifacts generated during assistant's calls. Stored in `call.artifact`.", - "allOf": [ - { - "$ref": "#/components/schemas/ArtifactPlan" - } + "name": { + "type": "string", + "description": "The name of the tool, fixed to 'computer'", + "default": "computer", + "enum": [ + "computer" ] }, - "startSpeakingPlan": { - "description": "This is the plan for when the assistant should start talking.\n\nYou should configure this if you're running into these issues:\n- The assistant is too slow to start talking after the customer is done speaking.\n- The assistant is too fast to start talking after the customer is done speaking.\n- The assistant is so fast that it's actually interrupting the customer.", + "displayWidthPx": { + "type": "number", + "description": "The display width in pixels" + }, + "displayHeightPx": { + "type": "number", + "description": "The display height in pixels" + }, + "displayNumber": { + "type": "number", + "description": "Optional display number" + } + } + }, + "UpdateTextEditorToolDTO": { + "type": "object", + "properties": { + "messages": { + "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" + }, + { + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] + } + }, + "type": { + "type": "string", + "enum": [ + "textEditor" + ], + "description": "The type of tool. \"textEditor\" for Text Editor tool." + }, + "subType": { + "type": "string", + "enum": [ + "text_editor_20241022" + ], + "description": "The sub type of tool." + }, + "server": { + "description": "\n This is the server where a `tool-calls` webhook will be sent.\n\n Notes:\n - Webhook is sent to this server when a tool call is made.\n - Webhook contains the call, assistant, and phone number objects.\n - Webhook contains the variables set on the assistant.\n - Webhook is sent to the first available URL in this order: {{tool.server.url}}, {{assistant.server.url}}, {{phoneNumber.server.url}}, {{org.server.url}}.\n - Webhook expects a response with tool call result.", "allOf": [ { - "$ref": "#/components/schemas/StartSpeakingPlan" + "$ref": "#/components/schemas/Server" } ] }, - "stopSpeakingPlan": { - "description": "This is the plan for when assistant should stop talking on customer interruption.\n\nYou should configure this if you're running into these issues:\n- The assistant is too slow to recognize customer's interruption.\n- The assistant is too fast to recognize customer's interruption.\n- The assistant is getting interrupted by phrases that are just acknowledgments.\n- The assistant is getting interrupted by background noises.\n- The assistant is not properly stopping -- it starts talking right after getting interrupted.", + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", "allOf": [ { - "$ref": "#/components/schemas/StopSpeakingPlan" + "$ref": "#/components/schemas/ToolRejectionPlan" } ] }, - "monitorPlan": { - "description": "This is the plan for real-time monitoring of the assistant's calls.\n\nUsage:\n- To enable live listening of the assistant's calls, set `monitorPlan.listenEnabled` to `true`.\n- To enable live control of the assistant's calls, set `monitorPlan.controlEnabled` to `true`.", - "allOf": [ - { - "$ref": "#/components/schemas/MonitorPlan" - } + "name": { + "type": "string", + "description": "The name of the tool, fixed to 'str_replace_editor'", + "default": "str_replace_editor", + "enum": [ + "str_replace_editor" ] + } + } + }, + "UpdateQueryToolDTO": { + "type": "object", + "properties": { + "messages": { + "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" + }, + { + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] + } }, - "credentialIds": { - "description": "These are the credentials that will be used for the assistant calls. By default, all the credentials are available for use in the call but you can provide a subset using this.", + "type": { + "type": "string", + "enum": [ + "query" + ], + "description": "The type of tool. \"query\" for Query tool." + }, + "knowledgeBases": { + "description": "The knowledge bases to query", "type": "array", "items": { - "type": "string" + "$ref": "#/components/schemas/KnowledgeBase" } }, - "server": { - "description": "This is where Vapi will send webhooks. You can find all webhooks available along with their shape in ServerMessage schema.\n\nThe order of precedence is:\n\n1. assistant.server.url\n2. phoneNumber.serverUrl\n3. org.serverUrl", + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", "allOf": [ { - "$ref": "#/components/schemas/Server" + "$ref": "#/components/schemas/ToolRejectionPlan" } ] - }, - "keypadInputPlan": { - "$ref": "#/components/schemas/KeypadInputPlan" } } }, - "ByoPhoneNumber": { + "UpdateGoogleCalendarCreateEventToolDTO": { "type": "object", "properties": { - "fallbackDestination": { - "description": "This is the fallback destination an inbound call will be transferred to if:\n1. `assistantId` is not set\n2. `squadId` is not set\n3. and, `assistant-request` message to the `serverUrl` fails\n\nIf this is not set and above conditions are met, the inbound call is hung up with an error message.", - "oneOf": [ - { - "$ref": "#/components/schemas/TransferDestinationNumber", - "title": "NumberTransferDestination" - }, - { - "$ref": "#/components/schemas/TransferDestinationSip", - "title": "SipTransferDestination" - } - ] - }, - "hooks": { + "messages": { "type": "array", - "description": "This is the hooks that will be used for incoming calls to this phone number.", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", "items": { "oneOf": [ { - "$ref": "#/components/schemas/PhoneNumberHookCallRinging", - "title": "PhoneNumberHookCallRinging" + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" }, { - "$ref": "#/components/schemas/PhoneNumberHookCallEnding", - "title": "PhoneNumberHookCallEnding" + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" } ] } }, - "provider": { - "type": "string", - "description": "This is to bring your own phone numbers from your own SIP trunks or Carriers.", - "enum": [ - "byo-phone-number" - ] - }, - "numberE164CheckEnabled": { - "type": "boolean", - "description": "This is the flag to toggle the E164 check for the `number` field. This is an advanced property which should be used if you know your use case requires it.\n\nUse cases:\n- `false`: To allow non-E164 numbers like `+001234567890`, `1234`, or `abc`. This is useful for dialing out to non-E164 numbers on your SIP trunks.\n- `true` (default): To allow only E164 numbers like `+14155551234`. This is standard for PSTN calls.\n\nIf `false`, the `number` is still required to only contain alphanumeric characters (regex: `/^\\+?[a-zA-Z0-9]+$/`).\n\n@default true (E164 check is enabled)", - "default": true - }, - "id": { - "type": "string", - "description": "This is the unique identifier for the phone number." - }, - "orgId": { - "type": "string", - "description": "This is the unique identifier for the org that this phone number belongs to." - }, - "createdAt": { - "format": "date-time", - "type": "string", - "description": "This is the ISO 8601 date-time string of when the phone number was created." - }, - "updatedAt": { - "format": "date-time", - "type": "string", - "description": "This is the ISO 8601 date-time string of when the phone number was last updated." - }, - "status": { + "type": { "type": "string", - "description": "This is the status of the phone number.", "enum": [ - "active", - "activating", - "blocked" - ] - }, - "name": { - "type": "string", - "description": "This is the name of the phone number. This is just for your own reference.", - "maxLength": 40 - }, - "assistantId": { - "type": "string", - "description": "This is the assistant that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId` nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." - }, - "workflowId": { - "type": "string", - "description": "This is the workflow that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." - }, - "squadId": { - "type": "string", - "description": "This is the squad that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + "google.calendar.event.create" + ], + "description": "The type of tool. \"google.calendar.event.create\" for Google Calendar Create Event tool." }, - "server": { - "description": "This is where Vapi will send webhooks. You can find all webhooks available along with their shape in ServerMessage schema.\n\nThe order of precedence is:\n\n1. assistant.server\n2. phoneNumber.server\n3. org.server", + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", "allOf": [ { - "$ref": "#/components/schemas/Server" + "$ref": "#/components/schemas/ToolRejectionPlan" } ] - }, - "number": { - "type": "string", - "description": "This is the number of the customer.", - "minLength": 3, - "maxLength": 40 - }, - "credentialId": { - "type": "string", - "description": "This is the credential of your own SIP trunk or Carrier (type `byo-sip-trunk`) which can be used to make calls to this phone number.\n\nYou can add the SIP trunk or Carrier credential in the Provider Credentials page on the Dashboard to get the credentialId." } - }, - "required": [ - "provider", - "id", - "orgId", - "createdAt", - "updatedAt", - "credentialId" - ] + } }, - "TwilioPhoneNumber": { + "UpdateGoogleSheetsRowAppendToolDTO": { "type": "object", "properties": { - "fallbackDestination": { - "description": "This is the fallback destination an inbound call will be transferred to if:\n1. `assistantId` is not set\n2. `squadId` is not set\n3. and, `assistant-request` message to the `serverUrl` fails\n\nIf this is not set and above conditions are met, the inbound call is hung up with an error message.", - "oneOf": [ - { - "$ref": "#/components/schemas/TransferDestinationNumber", - "title": "NumberTransferDestination" - }, - { - "$ref": "#/components/schemas/TransferDestinationSip", - "title": "SipTransferDestination" - } - ] - }, - "hooks": { + "messages": { "type": "array", - "description": "This is the hooks that will be used for incoming calls to this phone number.", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", "items": { "oneOf": [ { - "$ref": "#/components/schemas/PhoneNumberHookCallRinging", - "title": "PhoneNumberHookCallRinging" + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" }, { - "$ref": "#/components/schemas/PhoneNumberHookCallEnding", - "title": "PhoneNumberHookCallEnding" + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" } ] } }, - "provider": { - "type": "string", - "description": "This is to use numbers bought on Twilio.", - "enum": [ - "twilio" - ] - }, - "smsEnabled": { - "type": "boolean", - "description": "Controls whether Vapi sets the messaging webhook URL on the Twilio number during import.\n\nIf set to `false`, Vapi will not update the Twilio messaging URL, leaving it as is.\nIf `true` or omitted (default), Vapi will configure both the voice and messaging URLs.\n\n@default true", - "default": true - }, - "id": { - "type": "string", - "description": "This is the unique identifier for the phone number." - }, - "orgId": { - "type": "string", - "description": "This is the unique identifier for the org that this phone number belongs to." - }, - "createdAt": { - "format": "date-time", - "type": "string", - "description": "This is the ISO 8601 date-time string of when the phone number was created." - }, - "updatedAt": { - "format": "date-time", - "type": "string", - "description": "This is the ISO 8601 date-time string of when the phone number was last updated." - }, - "status": { + "type": { "type": "string", - "description": "This is the status of the phone number.", "enum": [ - "active", - "activating", - "blocked" - ] - }, - "twilioAuthToken": { - "type": "string", - "description": "This is the Twilio Auth Token for the phone number." - }, - "twilioApiKey": { - "type": "string", - "description": "This is the Twilio API Key for the phone number." - }, - "twilioApiSecret": { - "type": "string", - "description": "This is the Twilio API Secret for the phone number." - }, - "name": { - "type": "string", - "description": "This is the name of the phone number. This is just for your own reference.", - "maxLength": 40 - }, - "assistantId": { - "type": "string", - "description": "This is the assistant that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId` nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." - }, - "workflowId": { - "type": "string", - "description": "This is the workflow that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." - }, - "squadId": { - "type": "string", - "description": "This is the squad that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + "google.sheets.row.append" + ], + "description": "The type of tool. \"google.sheets.row.append\" for Google Sheets Row Append tool." }, - "server": { - "description": "This is where Vapi will send webhooks. You can find all webhooks available along with their shape in ServerMessage schema.\n\nThe order of precedence is:\n\n1. assistant.server\n2. phoneNumber.server\n3. org.server", + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", "allOf": [ { - "$ref": "#/components/schemas/Server" + "$ref": "#/components/schemas/ToolRejectionPlan" } ] - }, - "number": { - "type": "string", - "description": "These are the digits of the phone number you own on your Twilio." - }, - "twilioAccountSid": { - "type": "string", - "description": "This is the Twilio Account SID for the phone number." } - }, - "required": [ - "provider", - "id", - "orgId", - "createdAt", - "updatedAt", - "number", - "twilioAccountSid" - ] + } }, - "VonagePhoneNumber": { + "UpdateGoogleCalendarCheckAvailabilityToolDTO": { "type": "object", "properties": { - "fallbackDestination": { - "description": "This is the fallback destination an inbound call will be transferred to if:\n1. `assistantId` is not set\n2. `squadId` is not set\n3. and, `assistant-request` message to the `serverUrl` fails\n\nIf this is not set and above conditions are met, the inbound call is hung up with an error message.", - "oneOf": [ - { - "$ref": "#/components/schemas/TransferDestinationNumber", - "title": "NumberTransferDestination" - }, + "messages": { + "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" + }, + { + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] + } + }, + "type": { + "type": "string", + "enum": [ + "google.calendar.availability.check" + ], + "description": "The type of tool. \"google.calendar.availability.check\" for Google Calendar Check Availability tool." + }, + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "allOf": [ { - "$ref": "#/components/schemas/TransferDestinationSip", - "title": "SipTransferDestination" + "$ref": "#/components/schemas/ToolRejectionPlan" } ] - }, - "hooks": { + } + } + }, + "UpdateSlackSendMessageToolDTO": { + "type": "object", + "properties": { + "messages": { "type": "array", - "description": "This is the hooks that will be used for incoming calls to this phone number.", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", "items": { "oneOf": [ { - "$ref": "#/components/schemas/PhoneNumberHookCallRinging", - "title": "PhoneNumberHookCallRinging" + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" }, { - "$ref": "#/components/schemas/PhoneNumberHookCallEnding", - "title": "PhoneNumberHookCallEnding" + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" } ] } }, - "provider": { - "type": "string", - "description": "This is to use numbers bought on Vonage.", - "enum": [ - "vonage" - ] - }, - "id": { - "type": "string", - "description": "This is the unique identifier for the phone number." - }, - "orgId": { - "type": "string", - "description": "This is the unique identifier for the org that this phone number belongs to." - }, - "createdAt": { - "format": "date-time", - "type": "string", - "description": "This is the ISO 8601 date-time string of when the phone number was created." - }, - "updatedAt": { - "format": "date-time", - "type": "string", - "description": "This is the ISO 8601 date-time string of when the phone number was last updated." - }, - "status": { + "type": { "type": "string", - "description": "This is the status of the phone number.", "enum": [ - "active", - "activating", - "blocked" - ] - }, - "name": { - "type": "string", - "description": "This is the name of the phone number. This is just for your own reference.", - "maxLength": 40 - }, - "assistantId": { - "type": "string", - "description": "This is the assistant that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId` nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." - }, - "workflowId": { - "type": "string", - "description": "This is the workflow that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." - }, - "squadId": { - "type": "string", - "description": "This is the squad that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + "slack.message.send" + ], + "description": "The type of tool. \"slack.message.send\" for Slack Send Message tool." }, - "server": { - "description": "This is where Vapi will send webhooks. You can find all webhooks available along with their shape in ServerMessage schema.\n\nThe order of precedence is:\n\n1. assistant.server\n2. phoneNumber.server\n3. org.server", + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", "allOf": [ { - "$ref": "#/components/schemas/Server" + "$ref": "#/components/schemas/ToolRejectionPlan" } ] - }, - "number": { - "type": "string", - "description": "These are the digits of the phone number you own on your Vonage." - }, - "credentialId": { - "type": "string", - "description": "This is the credential you added in dashboard.vapi.ai/keys. This is used to configure the number to send inbound calls to Vapi, make outbound calls and do live call updates like transfers and hangups." } - }, - "required": [ - "provider", - "id", - "orgId", - "createdAt", - "updatedAt", - "number", - "credentialId" - ] + } }, - "SipAuthentication": { + "UpdateSmsToolDTO": { "type": "object", "properties": { - "realm": { - "type": "string", - "description": "This will be expected in the `realm` field of the `authorization` header of the SIP INVITE. Defaults to sip.vapi.ai." + "messages": { + "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" + }, + { + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] + } }, - "username": { + "type": { "type": "string", - "description": "This will be expected in the `username` field of the `authorization` header of the SIP INVITE.", - "minLength": 20, - "maxLength": 40 + "enum": [ + "sms" + ], + "description": "The type of tool. \"sms\" for Twilio SMS sending tool." }, - "password": { - "type": "string", - "description": "This will be expected to generate the `response` field of the `authorization` header of the SIP INVITE, through digest authentication.", - "minLength": 20, - "maxLength": 40 + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "allOf": [ + { + "$ref": "#/components/schemas/ToolRejectionPlan" + } + ] } - }, - "required": [ - "username", - "password" - ] + } }, - "VapiPhoneNumber": { + "UpdateMcpToolDTO": { "type": "object", "properties": { - "fallbackDestination": { - "description": "This is the fallback destination an inbound call will be transferred to if:\n1. `assistantId` is not set\n2. `squadId` is not set\n3. and, `assistant-request` message to the `serverUrl` fails\n\nIf this is not set and above conditions are met, the inbound call is hung up with an error message.", - "oneOf": [ - { - "$ref": "#/components/schemas/TransferDestinationNumber", - "title": "NumberTransferDestination" - }, - { - "$ref": "#/components/schemas/TransferDestinationSip", - "title": "SipTransferDestination" - } - ] - }, - "hooks": { + "messages": { "type": "array", - "description": "This is the hooks that will be used for incoming calls to this phone number.", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", "items": { "oneOf": [ { - "$ref": "#/components/schemas/PhoneNumberHookCallRinging", - "title": "PhoneNumberHookCallRinging" + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" }, { - "$ref": "#/components/schemas/PhoneNumberHookCallEnding", - "title": "PhoneNumberHookCallEnding" + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" } ] } }, - "provider": { - "type": "string", - "description": "This is to create free SIP phone numbers on Vapi.", - "enum": [ - "vapi" - ] - }, - "id": { - "type": "string", - "description": "This is the unique identifier for the phone number." - }, - "orgId": { - "type": "string", - "description": "This is the unique identifier for the org that this phone number belongs to." - }, - "createdAt": { - "format": "date-time", - "type": "string", - "description": "This is the ISO 8601 date-time string of when the phone number was created." - }, - "updatedAt": { - "format": "date-time", - "type": "string", - "description": "This is the ISO 8601 date-time string of when the phone number was last updated." - }, - "status": { + "type": { "type": "string", - "description": "This is the status of the phone number.", "enum": [ - "active", - "activating", - "blocked" - ] - }, - "number": { - "type": "string", - "description": "These are the digits of the phone number you purchased from Vapi." - }, - "name": { - "type": "string", - "description": "This is the name of the phone number. This is just for your own reference.", - "maxLength": 40 - }, - "assistantId": { - "type": "string", - "description": "This is the assistant that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId` nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." - }, - "workflowId": { - "type": "string", - "description": "This is the workflow that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." - }, - "squadId": { - "type": "string", - "description": "This is the squad that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + "mcp" + ], + "description": "The type of tool. \"mcp\" for MCP tool." }, "server": { - "description": "This is where Vapi will send webhooks. You can find all webhooks available along with their shape in ServerMessage schema.\n\nThe order of precedence is:\n\n1. assistant.server\n2. phoneNumber.server\n3. org.server", + "description": "\n This is the server where a `tool-calls` webhook will be sent.\n\n Notes:\n - Webhook is sent to this server when a tool call is made.\n - Webhook contains the call, assistant, and phone number objects.\n - Webhook contains the variables set on the assistant.\n - Webhook is sent to the first available URL in this order: {{tool.server.url}}, {{assistant.server.url}}, {{phoneNumber.server.url}}, {{org.server.url}}.\n - Webhook expects a response with tool call result.", "allOf": [ { "$ref": "#/components/schemas/Server" } ] }, - "numberDesiredAreaCode": { - "type": "string", - "description": "This is the area code of the phone number to purchase.", - "minLength": 3, - "maxLength": 3 - }, - "sipUri": { - "type": "string", - "description": "This is the SIP URI of the phone number. You can SIP INVITE this. The assistant attached to this number will answer.\n\nThis is case-insensitive." + "toolMessages": { + "description": "Per-tool message overrides for individual tools loaded from the MCP server. Set messages to an empty array to suppress messages for a specific tool. Tools not listed here will use the default messages from the parent tool.", + "type": "array", + "items": { + "$ref": "#/components/schemas/McpToolMessages" + } }, - "authentication": { - "description": "This enables authentication for incoming SIP INVITE requests to the `sipUri`.\n\nIf not set, any username/password to the 401 challenge of the SIP INVITE will be accepted.", + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", "allOf": [ { - "$ref": "#/components/schemas/SipAuthentication" + "$ref": "#/components/schemas/ToolRejectionPlan" } ] + }, + "metadata": { + "$ref": "#/components/schemas/McpToolMetadata" } - }, - "required": [ - "provider", - "id", - "orgId", - "createdAt", - "updatedAt" - ] + } }, - "TelnyxPhoneNumber": { + "UpdateGoHighLevelCalendarAvailabilityToolDTO": { "type": "object", "properties": { - "fallbackDestination": { - "description": "This is the fallback destination an inbound call will be transferred to if:\n1. `assistantId` is not set\n2. `squadId` is not set\n3. and, `assistant-request` message to the `serverUrl` fails\n\nIf this is not set and above conditions are met, the inbound call is hung up with an error message.", - "oneOf": [ - { - "$ref": "#/components/schemas/TransferDestinationNumber", - "title": "NumberTransferDestination" - }, - { - "$ref": "#/components/schemas/TransferDestinationSip", - "title": "SipTransferDestination" - } - ] - }, - "hooks": { + "messages": { "type": "array", - "description": "This is the hooks that will be used for incoming calls to this phone number.", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", "items": { "oneOf": [ { - "$ref": "#/components/schemas/PhoneNumberHookCallRinging", - "title": "PhoneNumberHookCallRinging" + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" }, { - "$ref": "#/components/schemas/PhoneNumberHookCallEnding", - "title": "PhoneNumberHookCallEnding" + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" } ] } }, - "provider": { + "type": { "type": "string", - "description": "This is to use numbers bought on Telnyx.", "enum": [ - "telnyx" - ] - }, - "id": { - "type": "string", - "description": "This is the unique identifier for the phone number." - }, - "orgId": { - "type": "string", - "description": "This is the unique identifier for the org that this phone number belongs to." - }, - "createdAt": { - "format": "date-time", - "type": "string", - "description": "This is the ISO 8601 date-time string of when the phone number was created." - }, - "updatedAt": { - "format": "date-time", - "type": "string", - "description": "This is the ISO 8601 date-time string of when the phone number was last updated." + "gohighlevel.calendar.availability.check" + ], + "description": "The type of tool. \"gohighlevel.calendar.availability.check\" for GoHighLevel Calendar Availability Check tool." }, - "status": { - "type": "string", - "description": "This is the status of the phone number.", - "enum": [ - "active", - "activating", - "blocked" + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "allOf": [ + { + "$ref": "#/components/schemas/ToolRejectionPlan" + } ] + } + } + }, + "UpdateGoHighLevelCalendarEventCreateToolDTO": { + "type": "object", + "properties": { + "messages": { + "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" + }, + { + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] + } }, - "name": { - "type": "string", - "description": "This is the name of the phone number. This is just for your own reference.", - "maxLength": 40 - }, - "assistantId": { - "type": "string", - "description": "This is the assistant that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId` nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." - }, - "workflowId": { - "type": "string", - "description": "This is the workflow that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." - }, - "squadId": { + "type": { "type": "string", - "description": "This is the squad that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + "enum": [ + "gohighlevel.calendar.event.create" + ], + "description": "The type of tool. \"gohighlevel.calendar.event.create\" for GoHighLevel Calendar Event Create tool." }, - "server": { - "description": "This is where Vapi will send webhooks. You can find all webhooks available along with their shape in ServerMessage schema.\n\nThe order of precedence is:\n\n1. assistant.server\n2. phoneNumber.server\n3. org.server", + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", "allOf": [ { - "$ref": "#/components/schemas/Server" + "$ref": "#/components/schemas/ToolRejectionPlan" } ] - }, - "number": { - "type": "string", - "description": "These are the digits of the phone number you own on your Telnyx." - }, - "credentialId": { - "type": "string", - "description": "This is the credential you added in dashboard.vapi.ai/keys. This is used to configure the number to send inbound calls to Vapi, make outbound calls and do live call updates like transfers and hangups." } - }, - "required": [ - "provider", - "id", - "orgId", - "createdAt", - "updatedAt", - "number", - "credentialId" - ] + } }, - "CreateByoPhoneNumberDTO": { + "UpdateGoHighLevelContactCreateToolDTO": { "type": "object", "properties": { - "fallbackDestination": { - "description": "This is the fallback destination an inbound call will be transferred to if:\n1. `assistantId` is not set\n2. `squadId` is not set\n3. and, `assistant-request` message to the `serverUrl` fails\n\nIf this is not set and above conditions are met, the inbound call is hung up with an error message.", - "oneOf": [ - { - "$ref": "#/components/schemas/TransferDestinationNumber", - "title": "NumberTransferDestination" - }, - { - "$ref": "#/components/schemas/TransferDestinationSip", - "title": "SipTransferDestination" - } - ] - }, - "hooks": { + "messages": { "type": "array", - "description": "This is the hooks that will be used for incoming calls to this phone number.", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", "items": { "oneOf": [ { - "$ref": "#/components/schemas/PhoneNumberHookCallRinging", - "title": "PhoneNumberHookCallRinging" + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" }, { - "$ref": "#/components/schemas/PhoneNumberHookCallEnding", - "title": "PhoneNumberHookCallEnding" + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" } ] } }, - "provider": { + "type": { "type": "string", - "description": "This is to bring your own phone numbers from your own SIP trunks or Carriers.", "enum": [ - "byo-phone-number" - ] - }, - "numberE164CheckEnabled": { - "type": "boolean", - "description": "This is the flag to toggle the E164 check for the `number` field. This is an advanced property which should be used if you know your use case requires it.\n\nUse cases:\n- `false`: To allow non-E164 numbers like `+001234567890`, `1234`, or `abc`. This is useful for dialing out to non-E164 numbers on your SIP trunks.\n- `true` (default): To allow only E164 numbers like `+14155551234`. This is standard for PSTN calls.\n\nIf `false`, the `number` is still required to only contain alphanumeric characters (regex: `/^\\+?[a-zA-Z0-9]+$/`).\n\n@default true (E164 check is enabled)", - "default": true - }, - "number": { - "type": "string", - "description": "This is the number of the customer.", - "minLength": 3, - "maxLength": 40 - }, - "credentialId": { - "type": "string", - "description": "This is the credential of your own SIP trunk or Carrier (type `byo-sip-trunk`) which can be used to make calls to this phone number.\n\nYou can add the SIP trunk or Carrier credential in the Provider Credentials page on the Dashboard to get the credentialId." - }, - "name": { - "type": "string", - "description": "This is the name of the phone number. This is just for your own reference.", - "maxLength": 40 - }, - "assistantId": { - "type": "string", - "description": "This is the assistant that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId` nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + "gohighlevel.contact.create" + ], + "description": "The type of tool. \"gohighlevel.contact.create\" for GoHighLevel Contact Create tool." }, - "workflowId": { - "type": "string", - "description": "This is the workflow that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "allOf": [ + { + "$ref": "#/components/schemas/ToolRejectionPlan" + } + ] + } + } + }, + "UpdateGoHighLevelContactGetToolDTO": { + "type": "object", + "properties": { + "messages": { + "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" + }, + { + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" + } + ] + } }, - "squadId": { + "type": { "type": "string", - "description": "This is the squad that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + "enum": [ + "gohighlevel.contact.get" + ], + "description": "The type of tool. \"gohighlevel.contact.get\" for GoHighLevel Contact Get tool." }, - "server": { - "description": "This is where Vapi will send webhooks. You can find all webhooks available along with their shape in ServerMessage schema.\n\nThe order of precedence is:\n\n1. assistant.server\n2. phoneNumber.server\n3. org.server", + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", "allOf": [ { - "$ref": "#/components/schemas/Server" + "$ref": "#/components/schemas/ToolRejectionPlan" } ] } - }, - "required": [ - "provider", - "credentialId" - ] + } }, - "CreateTwilioPhoneNumberDTO": { + "UpdateSipRequestToolDTO": { "type": "object", "properties": { - "fallbackDestination": { - "description": "This is the fallback destination an inbound call will be transferred to if:\n1. `assistantId` is not set\n2. `squadId` is not set\n3. and, `assistant-request` message to the `serverUrl` fails\n\nIf this is not set and above conditions are met, the inbound call is hung up with an error message.", - "oneOf": [ - { - "$ref": "#/components/schemas/TransferDestinationNumber", - "title": "NumberTransferDestination" - }, - { - "$ref": "#/components/schemas/TransferDestinationSip", - "title": "SipTransferDestination" - } - ] - }, - "hooks": { + "messages": { "type": "array", - "description": "This is the hooks that will be used for incoming calls to this phone number.", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", "items": { "oneOf": [ { - "$ref": "#/components/schemas/PhoneNumberHookCallRinging", - "title": "PhoneNumberHookCallRinging" + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" }, { - "$ref": "#/components/schemas/PhoneNumberHookCallEnding", - "title": "PhoneNumberHookCallEnding" + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" } ] } }, - "provider": { + "type": { "type": "string", - "description": "This is to use numbers bought on Twilio.", "enum": [ - "twilio" - ] - }, - "smsEnabled": { - "type": "boolean", - "description": "Controls whether Vapi sets the messaging webhook URL on the Twilio number during import.\n\nIf set to `false`, Vapi will not update the Twilio messaging URL, leaving it as is.\nIf `true` or omitted (default), Vapi will configure both the voice and messaging URLs.\n\n@default true", - "default": true - }, - "number": { - "type": "string", - "description": "These are the digits of the phone number you own on your Twilio." - }, - "twilioAccountSid": { - "type": "string", - "description": "This is the Twilio Account SID for the phone number." - }, - "twilioAuthToken": { - "type": "string", - "description": "This is the Twilio Auth Token for the phone number." - }, - "twilioApiKey": { - "type": "string", - "description": "This is the Twilio API Key for the phone number." - }, - "twilioApiSecret": { - "type": "string", - "description": "This is the Twilio API Secret for the phone number." - }, - "name": { - "type": "string", - "description": "This is the name of the phone number. This is just for your own reference.", - "maxLength": 40 - }, - "assistantId": { - "type": "string", - "description": "This is the assistant that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId` nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." - }, - "workflowId": { - "type": "string", - "description": "This is the workflow that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + "sipRequest" + ], + "description": "The type of tool. \"sipRequest\" for SIP request tool." }, - "squadId": { + "verb": { "type": "string", - "description": "This is the squad that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + "enum": [ + "INFO", + "MESSAGE", + "NOTIFY" + ], + "description": "The SIP method to send." }, - "server": { - "description": "This is where Vapi will send webhooks. You can find all webhooks available along with their shape in ServerMessage schema.\n\nThe order of precedence is:\n\n1. assistant.server\n2. phoneNumber.server\n3. org.server", + "headers": { + "description": "JSON schema for headers the model should populate when sending the SIP request.", "allOf": [ { - "$ref": "#/components/schemas/Server" + "$ref": "#/components/schemas/JsonSchema" } ] - } - }, - "required": [ - "provider", - "number", - "twilioAccountSid" - ] - }, - "CreateVonagePhoneNumberDTO": { - "type": "object", - "properties": { - "fallbackDestination": { - "description": "This is the fallback destination an inbound call will be transferred to if:\n1. `assistantId` is not set\n2. `squadId` is not set\n3. and, `assistant-request` message to the `serverUrl` fails\n\nIf this is not set and above conditions are met, the inbound call is hung up with an error message.", + }, + "body": { + "description": "Body to include in the SIP request. Either a literal string body, or a JSON schema describing a structured body that the model should populate.", "oneOf": [ { - "$ref": "#/components/schemas/TransferDestinationNumber", - "title": "NumberTransferDestination" + "type": "string" }, { - "$ref": "#/components/schemas/TransferDestinationSip", - "title": "SipTransferDestination" + "$ref": "#/components/schemas/JsonSchema" } ] }, - "hooks": { + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "allOf": [ + { + "$ref": "#/components/schemas/ToolRejectionPlan" + } + ] + } + } + }, + "UpdateVoicemailToolDTO": { + "type": "object", + "properties": { + "messages": { "type": "array", - "description": "This is the hooks that will be used for incoming calls to this phone number.", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", "items": { "oneOf": [ { - "$ref": "#/components/schemas/PhoneNumberHookCallRinging", - "title": "PhoneNumberHookCallRinging" + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" }, { - "$ref": "#/components/schemas/PhoneNumberHookCallEnding", - "title": "PhoneNumberHookCallEnding" + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" } ] } }, - "provider": { + "type": { "type": "string", - "description": "This is to use numbers bought on Vonage.", + "description": "The type of tool. \"voicemail\" for Voicemail tool.", "enum": [ - "vonage" + "voicemail" ] }, - "number": { - "type": "string", - "description": "These are the digits of the phone number you own on your Vonage." + "beepDetectionEnabled": { + "type": "boolean", + "description": "This is the flag that enables beep detection for voicemail detection and applies only for twilio based calls.\n\n@default false", + "default": false, + "example": false }, - "credentialId": { + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "allOf": [ + { + "$ref": "#/components/schemas/ToolRejectionPlan" + } + ] + } + } + }, + "ToolVersion": { + "type": "object", + "properties": { + "versionName": { "type": "string", - "description": "This is the credential you added in dashboard.vapi.ai/keys. This is used to configure the number to send inbound calls to Vapi, make outbound calls and do live call updates like transfers and hangups." + "nullable": true, + "description": "Optional human-readable label for this version. Pass `null` to clear.", + "maxLength": 80 }, - "name": { + "versionDescription": { "type": "string", - "description": "This is the name of the phone number. This is just for your own reference.", - "maxLength": 40 + "nullable": true, + "description": "Optional description for this version. Pass `null` to clear.", + "maxLength": 500 }, - "assistantId": { - "type": "string", - "description": "This is the assistant that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId` nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + "type": { + "type": "object" }, - "workflowId": { - "type": "string", - "description": "This is the workflow that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + "function": { + "type": "object", + "nullable": true }, - "squadId": { + "messages": { + "type": "array", + "nullable": true, + "items": { + "type": "object" + } + }, + "metadata": { + "type": "object", + "nullable": true + }, + "templateId": { "type": "string", - "description": "This is the squad that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + "nullable": true }, "server": { - "description": "This is where Vapi will send webhooks. You can find all webhooks available along with their shape in ServerMessage schema.\n\nThe order of precedence is:\n\n1. assistant.server\n2. phoneNumber.server\n3. org.server", + "nullable": true, "allOf": [ { "$ref": "#/components/schemas/Server" } ] - } - }, - "required": [ - "provider", - "number", - "credentialId" - ] - }, - "CreateVapiPhoneNumberDTO": { - "type": "object", - "properties": { - "fallbackDestination": { - "description": "This is the fallback destination an inbound call will be transferred to if:\n1. `assistantId` is not set\n2. `squadId` is not set\n3. and, `assistant-request` message to the `serverUrl` fails\n\nIf this is not set and above conditions are met, the inbound call is hung up with an error message.", - "oneOf": [ - { - "$ref": "#/components/schemas/TransferDestinationNumber", - "title": "NumberTransferDestination" - }, - { - "$ref": "#/components/schemas/TransferDestinationSip", - "title": "SipTransferDestination" - } - ] }, - "hooks": { + "async": { + "type": "boolean", + "nullable": true + }, + "destinations": { "type": "array", - "description": "This is the hooks that will be used for incoming calls to this phone number.", + "nullable": true, "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/PhoneNumberHookCallRinging", - "title": "PhoneNumberHookCallRinging" - }, - { - "$ref": "#/components/schemas/PhoneNumberHookCallEnding", - "title": "PhoneNumberHookCallEnding" - } - ] + "type": "object" } }, - "provider": { + "name": { "type": "string", - "description": "This is to create free SIP phone numbers on Vapi.", - "enum": [ - "vapi" - ] + "nullable": true }, - "numberDesiredAreaCode": { + "subType": { "type": "string", - "description": "This is the area code of the phone number to purchase.", - "minLength": 3, - "maxLength": 3 + "nullable": true }, - "sipUri": { + "displayWidthPx": { + "type": "number", + "nullable": true + }, + "displayHeightPx": { + "type": "number", + "nullable": true + }, + "displayNumber": { + "type": "number", + "nullable": true + }, + "knowledgeBases": { + "type": "array", + "nullable": true, + "items": { + "type": "object" + } + }, + "url": { "type": "string", - "description": "This is the SIP URI of the phone number. You can SIP INVITE this. The assistant attached to this number will answer.\n\nThis is case-insensitive." + "nullable": true }, - "authentication": { - "description": "This enables authentication for incoming SIP INVITE requests to the `sipUri`.\n\nIf not set, any username/password to the 401 challenge of the SIP INVITE will be accepted.", - "allOf": [ - { - "$ref": "#/components/schemas/SipAuthentication" - } - ] + "method": { + "type": "string", + "nullable": true }, - "name": { + "headers": { + "type": "object", + "nullable": true + }, + "body": { + "type": "object" + }, + "backoffPlan": { + "type": "object", + "nullable": true + }, + "timeoutSeconds": { + "type": "number", + "nullable": true + }, + "description": { "type": "string", - "description": "This is the name of the phone number. This is just for your own reference.", - "maxLength": 40 + "nullable": true }, - "assistantId": { + "variableExtractionPlan": { + "type": "object", + "nullable": true + }, + "rejectionPlan": { + "type": "object", + "nullable": true + }, + "credentialId": { "type": "string", - "description": "This is the assistant that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId` nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + "nullable": true }, - "workflowId": { + "extendedDelayWhenPrecededByTextEnabled": { + "type": "boolean", + "nullable": true + }, + "beepDetectionEnabled": { + "type": "boolean", + "nullable": true + }, + "code": { "type": "string", - "description": "This is the workflow that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + "nullable": true }, - "squadId": { + "environmentVariables": { + "type": "array", + "nullable": true, + "items": { + "type": "object" + } + }, + "parameters": { + "type": "array", + "nullable": true, + "items": { + "type": "object" + } + }, + "encryptedPaths": { + "type": "array", + "nullable": true, + "items": { + "type": "string" + } + }, + "sipInfoDtmfEnabled": { + "type": "boolean", + "nullable": true + }, + "verb": { "type": "string", - "description": "This is the squad that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + "nullable": true }, - "server": { - "description": "This is where Vapi will send webhooks. You can find all webhooks available along with their shape in ServerMessage schema.\n\nThe order of precedence is:\n\n1. assistant.server\n2. phoneNumber.server\n3. org.server", - "allOf": [ - { - "$ref": "#/components/schemas/Server" - } - ] - } - }, - "required": [ - "provider" - ] - }, - "CreateTelnyxPhoneNumberDTO": { - "type": "object", - "properties": { - "fallbackDestination": { - "description": "This is the fallback destination an inbound call will be transferred to if:\n1. `assistantId` is not set\n2. `squadId` is not set\n3. and, `assistant-request` message to the `serverUrl` fails\n\nIf this is not set and above conditions are met, the inbound call is hung up with an error message.", - "oneOf": [ - { - "$ref": "#/components/schemas/TransferDestinationNumber", - "title": "NumberTransferDestination" - }, - { - "$ref": "#/components/schemas/TransferDestinationSip", - "title": "SipTransferDestination" - } - ] + "defaultResult": { + "type": "string", + "nullable": true }, - "hooks": { + "toolMessages": { "type": "array", - "description": "This is the hooks that will be used for incoming calls to this phone number.", + "nullable": true, "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/PhoneNumberHookCallRinging", - "title": "PhoneNumberHookCallRinging" - }, - { - "$ref": "#/components/schemas/PhoneNumberHookCallEnding", - "title": "PhoneNumberHookCallEnding" - } - ] + "type": "object" } }, - "provider": { + "id": { "type": "string", - "description": "This is to use numbers bought on Telnyx.", - "enum": [ - "telnyx" - ] + "description": "This is the unique identifier for the version row." }, - "number": { + "orgId": { "type": "string", - "description": "These are the digits of the phone number you own on your Telnyx." + "description": "This is the unique identifier for the org that owns this version." }, - "credentialId": { + "toolId": { "type": "string", - "description": "This is the credential you added in dashboard.vapi.ai/keys. This is used to configure the number to send inbound calls to Vapi, make outbound calls and do live call updates like transfers and hangups." + "description": "This is the unique identifier for the tool this version was snapshotted from." }, - "name": { + "version": { "type": "string", - "description": "This is the name of the phone number. This is just for your own reference.", - "maxLength": 40 + "description": "This is the public monotonic version label, e.g. \"v1\".\nSystem-owned and incremented per tool; never user-supplied." }, - "assistantId": { + "configHash": { "type": "string", - "description": "This is the assistant that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId` nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + "description": "This is the SHA-256 hex of the snapshotted content used for no-op detection." }, - "workflowId": { + "parentVersion": { "type": "string", - "description": "This is the workflow that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + "nullable": true, + "description": "This is the prior version label (vN-1). Null on v1 or for branch roots." }, - "squadId": { + "createdBy": { "type": "string", - "description": "This is the squad that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + "nullable": true, + "description": "This is the actor that wrote this version. Email when created via JWT, null when created via API." }, - "server": { - "description": "This is where Vapi will send webhooks. You can find all webhooks available along with their shape in ServerMessage schema.\n\nThe order of precedence is:\n\n1. assistant.server\n2. phoneNumber.server\n3. org.server", - "allOf": [ - { - "$ref": "#/components/schemas/Server" - } - ] + "deletedAt": { + "format": "date-time", + "type": "string", + "nullable": true, + "description": "This is the soft-delete timestamp. Null when active." + }, + "createdAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the version was created." } }, "required": [ - "provider", - "number", - "credentialId" + "id", + "orgId", + "toolId", + "version", + "configHash", + "createdAt" ] }, - "UpdateByoPhoneNumberDTO": { + "ToolVersionPaginatedMetadata": { "type": "object", "properties": { - "fallbackDestination": { - "description": "This is the fallback destination an inbound call will be transferred to if:\n1. `assistantId` is not set\n2. `squadId` is not set\n3. and, `assistant-request` message to the `serverUrl` fails\n\nIf this is not set and above conditions are met, the inbound call is hung up with an error message.", - "oneOf": [ - { - "$ref": "#/components/schemas/TransferDestinationNumber", - "title": "NumberTransferDestination" - }, - { - "$ref": "#/components/schemas/TransferDestinationSip", - "title": "SipTransferDestination" - } - ] + "nextCursor": { + "type": "string", + "nullable": true }, - "hooks": { + "hasNextPage": { + "type": "boolean" + }, + "limit": { + "type": "number" + } + }, + "required": [ + "hasNextPage", + "limit" + ] + }, + "ToolVersionPaginatedResponse": { + "type": "object", + "properties": { + "results": { "type": "array", - "description": "This is the hooks that will be used for incoming calls to this phone number.", + "items": { + "$ref": "#/components/schemas/ToolVersion" + } + }, + "metadata": { + "$ref": "#/components/schemas/ToolVersionPaginatedMetadata" + } + }, + "required": [ + "results", + "metadata" + ] + }, + "ToolDraft": { + "type": "object", + "properties": { + "messages": { + "type": "array", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", "items": { "oneOf": [ { - "$ref": "#/components/schemas/PhoneNumberHookCallRinging", - "title": "PhoneNumberHookCallRinging" + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" }, { - "$ref": "#/components/schemas/PhoneNumberHookCallEnding", - "title": "PhoneNumberHookCallEnding" + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" } ] } }, - "numberE164CheckEnabled": { - "type": "boolean", - "description": "This is the flag to toggle the E164 check for the `number` field. This is an advanced property which should be used if you know your use case requires it.\n\nUse cases:\n- `false`: To allow non-E164 numbers like `+001234567890`, `1234`, or `abc`. This is useful for dialing out to non-E164 numbers on your SIP trunks.\n- `true` (default): To allow only E164 numbers like `+14155551234`. This is standard for PSTN calls.\n\nIf `false`, the `number` is still required to only contain alphanumeric characters (regex: `/^\\+?[a-zA-Z0-9]+$/`).\n\n@default true (E164 check is enabled)", - "default": true + "type": { + "type": "string", + "description": "This is the type of the tool.", + "enum": [ + "dtmf", + "endCall", + "knowledgeBase", + "transferCall", + "transferCancel", + "transferSuccessful", + "handoff", + "output", + "voicemail", + "query", + "sms", + "sipRequest", + "function", + "mcp", + "apiRequest", + "code", + "bash", + "computer", + "textEditor", + "google.calendar.event.create", + "google.calendar.availability.check", + "google.sheets.row.append", + "slack.message.send", + "gohighlevel.calendar.event.create", + "gohighlevel.calendar.availability.check", + "gohighlevel.contact.create", + "gohighlevel.contact.get", + "make", + "ghl" + ] + }, + "id": { + "type": "string", + "description": "Key used as `draftId` in URLs." + }, + "orgId": { + "type": "string", + "description": "This is the unique identifier for the org that owns this draft." }, - "name": { + "toolId": { "type": "string", - "description": "This is the name of the phone number. This is just for your own reference.", - "maxLength": 40 + "description": "This is the unique identifier for the tool this draft was forked from.\nIntentionally NOT a FK — `tool_draft` mirrors `tool_version` / `version_pin`'s\nno-FK / app-cleanup philosophy, so there is no `ON DELETE CASCADE`. Drafts\nmust be cleaned up explicitly (`toolDraftDelete({ orgId, toolId })`) on a\nparent tool hard-delete; nothing reaps them automatically." }, - "assistantId": { + "baseVersion": { "type": "string", - "description": "This is the assistant that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId` nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + "description": "The published version this draft was forked from. Server defaults to\n`tool.latestVersion` on POST if omitted. Immutable for the draft's lifetime." }, - "workflowId": { + "createdBy": { "type": "string", - "description": "This is the workflow that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + "nullable": true, + "description": "Email when JWT, null when API or external JWT. Set on POST, never rewritten on PATCH." }, - "squadId": { + "createdAt": { + "format": "date-time", "type": "string", - "description": "This is the squad that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + "description": "This is the ISO 8601 date-time string of when the draft was created." }, - "server": { - "description": "This is where Vapi will send webhooks. You can find all webhooks available along with their shape in ServerMessage schema.\n\nThe order of precedence is:\n\n1. assistant.server\n2. phoneNumber.server\n3. org.server", + "updatedAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the draft was last updated." + }, + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", "allOf": [ { - "$ref": "#/components/schemas/Server" + "$ref": "#/components/schemas/ToolRejectionPlan" } ] }, - "number": { - "type": "string", - "description": "This is the number of the customer.", - "minLength": 3, - "maxLength": 40 - }, - "credentialId": { - "type": "string", - "description": "This is the credential of your own SIP trunk or Carrier (type `byo-sip-trunk`) which can be used to make calls to this phone number.\n\nYou can add the SIP trunk or Carrier credential in the Provider Credentials page on the Dashboard to get the credentialId." - } - } - }, - "UpdateTwilioPhoneNumberDTO": { - "type": "object", - "properties": { - "fallbackDestination": { - "description": "This is the fallback destination an inbound call will be transferred to if:\n1. `assistantId` is not set\n2. `squadId` is not set\n3. and, `assistant-request` message to the `serverUrl` fails\n\nIf this is not set and above conditions are met, the inbound call is hung up with an error message.", - "oneOf": [ - { - "$ref": "#/components/schemas/TransferDestinationNumber", - "title": "NumberTransferDestination" - }, + "function": { + "description": "This is the function definition of the tool.", + "allOf": [ { - "$ref": "#/components/schemas/TransferDestinationSip", - "title": "SipTransferDestination" + "$ref": "#/components/schemas/OpenAIFunction" } ] }, - "hooks": { + "metadata": { + "type": "object", + "description": "Provider-specific metadata. Polymorphic across tool variants with no shared\ndiscriminator, so it is validated as a plain object (mirrors how\n`ToolCallResult.metadata` is typed)." + }, + "templateId": { + "type": "string", + "description": "This is the unique identifier for the template this tool was created from." + }, + "server": { + "$ref": "#/components/schemas/Server" + }, + "async": { + "type": "boolean" + }, + "destinations": { + "description": "These are the destinations that the call can be transferred to.", "type": "array", - "description": "This is the hooks that will be used for incoming calls to this phone number.", "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/PhoneNumberHookCallRinging", - "title": "PhoneNumberHookCallRinging" - }, - { - "$ref": "#/components/schemas/PhoneNumberHookCallEnding", - "title": "PhoneNumberHookCallEnding" - } - ] + "type": "object" } }, - "smsEnabled": { - "type": "boolean", - "description": "Controls whether Vapi sets the messaging webhook URL on the Twilio number during import.\n\nIf set to `false`, Vapi will not update the Twilio messaging URL, leaving it as is.\nIf `true` or omitted (default), Vapi will configure both the voice and messaging URLs.\n\n@default true", - "default": true - }, "name": { "type": "string", - "description": "This is the name of the phone number. This is just for your own reference.", - "maxLength": 40 + "description": "This is the name of the tool. This will be passed to the model." }, - "assistantId": { + "subType": { "type": "string", - "description": "This is the assistant that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId` nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + "description": "This is the sub type of the tool (e.g. for computer, bash and text-editor tools)." }, - "workflowId": { + "displayWidthPx": { + "type": "number", + "description": "The display width in pixels (computer tool)." + }, + "displayHeightPx": { + "type": "number", + "description": "The display height in pixels (computer tool)." + }, + "displayNumber": { + "type": "number", + "description": "Optional display number (computer tool)." + }, + "knowledgeBases": { + "description": "The knowledge bases to query (query tool).", + "type": "array", + "items": { + "$ref": "#/components/schemas/KnowledgeBase" + } + }, + "url": { "type": "string", - "description": "This is the workflow that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + "description": "This is where the request will be sent (api-request tool)." }, - "squadId": { + "method": { "type": "string", - "description": "This is the squad that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + "description": "This is the HTTP method for the request (api-request tool).", + "enum": [ + "POST", + "GET", + "PUT", + "PATCH", + "DELETE" + ] }, - "server": { - "description": "This is where Vapi will send webhooks. You can find all webhooks available along with their shape in ServerMessage schema.\n\nThe order of precedence is:\n\n1. assistant.server\n2. phoneNumber.server\n3. org.server", + "headers": { + "description": "These are the headers to send with the request (api-request / sip-request tool).", "allOf": [ { - "$ref": "#/components/schemas/Server" + "$ref": "#/components/schemas/JsonSchema" } ] }, - "number": { - "type": "string", - "description": "These are the digits of the phone number you own on your Twilio." + "body": { + "type": "object", + "description": "This is the body of the request. Either a JSON schema (api-request) or a\nliteral string / schema (sip-request)." }, - "twilioAccountSid": { - "type": "string", - "description": "This is the Twilio Account SID for the phone number." + "backoffPlan": { + "description": "This is the backoff plan if the request fails.", + "allOf": [ + { + "$ref": "#/components/schemas/BackoffPlan" + } + ] }, - "twilioAuthToken": { - "type": "string", - "description": "This is the Twilio Auth Token for the phone number." + "timeoutSeconds": { + "type": "number", + "description": "This is the timeout in seconds for the request.", + "minimum": 1, + "maximum": 300 }, - "twilioApiKey": { + "description": { "type": "string", - "description": "This is the Twilio API Key for the phone number." + "description": "This is the description of the tool. This will be passed to the model." }, - "twilioApiSecret": { - "type": "string", - "description": "This is the Twilio API Secret for the phone number." - } - } - }, - "UpdateVonagePhoneNumberDTO": { - "type": "object", - "properties": { - "fallbackDestination": { - "description": "This is the fallback destination an inbound call will be transferred to if:\n1. `assistantId` is not set\n2. `squadId` is not set\n3. and, `assistant-request` message to the `serverUrl` fails\n\nIf this is not set and above conditions are met, the inbound call is hung up with an error message.", - "oneOf": [ - { - "$ref": "#/components/schemas/TransferDestinationNumber", - "title": "NumberTransferDestination" - }, + "variableExtractionPlan": { + "description": "This is the plan to extract variables from the tool's response.", + "allOf": [ { - "$ref": "#/components/schemas/TransferDestinationSip", - "title": "SipTransferDestination" + "$ref": "#/components/schemas/VariableExtractionPlan" } ] }, - "hooks": { + "credentialId": { + "type": "string", + "description": "This is the credential ID that will be used for authorization." + }, + "extendedDelayWhenPrecededByTextEnabled": { + "type": "boolean" + }, + "beepDetectionEnabled": { + "type": "boolean" + }, + "code": { + "type": "string", + "description": "This is the TypeScript code that will be executed when the tool is called (code tool).", + "maxLength": 50000 + }, + "environmentVariables": { + "description": "These are the environment variables available in the code via the `env` object (code tool).", "type": "array", - "description": "This is the hooks that will be used for incoming calls to this phone number.", "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/PhoneNumberHookCallRinging", - "title": "PhoneNumberHookCallRinging" - }, - { - "$ref": "#/components/schemas/PhoneNumberHookCallEnding", - "title": "PhoneNumberHookCallEnding" - } - ] + "$ref": "#/components/schemas/CodeToolEnvironmentVariable" } }, - "name": { - "type": "string", - "description": "This is the name of the phone number. This is just for your own reference.", - "maxLength": 40 + "parameters": { + "description": "These are the static parameters to merge into the tool's request body.", + "type": "array", + "items": { + "$ref": "#/components/schemas/ToolParameter" + } }, - "assistantId": { - "type": "string", - "description": "This is the assistant that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId` nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + "encryptedPaths": { + "description": "This is the paths to encrypt in the request body.", + "type": "array", + "items": { + "type": "string" + } }, - "workflowId": { - "type": "string", - "description": "This is the workflow that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + "sipInfoDtmfEnabled": { + "type": "boolean", + "description": "This enables sending DTMF tones via SIP INFO messages instead of RFC 2833." }, - "squadId": { + "verb": { "type": "string", - "description": "This is the squad that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." - }, - "server": { - "description": "This is where Vapi will send webhooks. You can find all webhooks available along with their shape in ServerMessage schema.\n\nThe order of precedence is:\n\n1. assistant.server\n2. phoneNumber.server\n3. org.server", - "allOf": [ - { - "$ref": "#/components/schemas/Server" - } + "description": "This is the SIP method to send (sip-request tool).", + "enum": [ + "INFO", + "MESSAGE", + "NOTIFY" ] }, - "number": { + "defaultResult": { "type": "string", - "description": "These are the digits of the phone number you own on your Vonage." + "description": "This is the default local tool result message used when no runtime override is returned (handoff tool)." }, - "credentialId": { - "type": "string", - "description": "This is the credential you added in dashboard.vapi.ai/keys. This is used to configure the number to send inbound calls to Vapi, make outbound calls and do live call updates like transfers and hangups." + "toolMessages": { + "description": "Per-tool message overrides for individual tools loaded from the MCP server (mcp tool).", + "type": "array", + "items": { + "$ref": "#/components/schemas/McpToolMessages" + } } - } + }, + "required": [ + "id", + "orgId", + "toolId", + "baseVersion", + "createdAt", + "updatedAt" + ] }, - "UpdateVapiPhoneNumberDTO": { + "CreateToolDraftDTO": { "type": "object", "properties": { - "fallbackDestination": { - "description": "This is the fallback destination an inbound call will be transferred to if:\n1. `assistantId` is not set\n2. `squadId` is not set\n3. and, `assistant-request` message to the `serverUrl` fails\n\nIf this is not set and above conditions are met, the inbound call is hung up with an error message.", - "oneOf": [ - { - "$ref": "#/components/schemas/TransferDestinationNumber", - "title": "NumberTransferDestination" - }, - { - "$ref": "#/components/schemas/TransferDestinationSip", - "title": "SipTransferDestination" - } - ] - }, - "hooks": { + "messages": { "type": "array", - "description": "This is the hooks that will be used for incoming calls to this phone number.", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", "items": { "oneOf": [ { - "$ref": "#/components/schemas/PhoneNumberHookCallRinging", - "title": "PhoneNumberHookCallRinging" + "$ref": "#/components/schemas/ToolMessageStart", + "title": "ToolMessageStart" }, { - "$ref": "#/components/schemas/PhoneNumberHookCallEnding", - "title": "PhoneNumberHookCallEnding" + "$ref": "#/components/schemas/ToolMessageComplete", + "title": "ToolMessageComplete" + }, + { + "$ref": "#/components/schemas/ToolMessageFailed", + "title": "ToolMessageFailed" + }, + { + "$ref": "#/components/schemas/ToolMessageDelayed", + "title": "ToolMessageDelayed" } ] } }, - "name": { - "type": "string", - "description": "This is the name of the phone number. This is just for your own reference.", - "maxLength": 40 - }, - "assistantId": { - "type": "string", - "description": "This is the assistant that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId` nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." - }, - "workflowId": { + "type": { "type": "string", - "description": "This is the workflow that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + "description": "This is the type of the tool.", + "enum": [ + "dtmf", + "endCall", + "knowledgeBase", + "transferCall", + "transferCancel", + "transferSuccessful", + "handoff", + "output", + "voicemail", + "query", + "sms", + "sipRequest", + "function", + "mcp", + "apiRequest", + "code", + "bash", + "computer", + "textEditor", + "google.calendar.event.create", + "google.calendar.availability.check", + "google.sheets.row.append", + "slack.message.send", + "gohighlevel.calendar.event.create", + "gohighlevel.calendar.availability.check", + "gohighlevel.contact.create", + "gohighlevel.contact.get", + "make", + "ghl" + ] }, - "squadId": { + "baseVersion": { "type": "string", - "description": "This is the squad that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + "description": "Optional pointer to the published version this draft was forked from.\nWhen omitted, defaults server-side to the parent tool's current\n`latestVersion` (lazy-created via `toolBaselineVersionEnsureInTx` if the\ntool has never been versioned). Immutable for the lifetime of the draft." }, - "server": { - "description": "This is where Vapi will send webhooks. You can find all webhooks available along with their shape in ServerMessage schema.\n\nThe order of precedence is:\n\n1. assistant.server\n2. phoneNumber.server\n3. org.server", + "function": { + "description": "This is the function definition of the tool.", "allOf": [ { - "$ref": "#/components/schemas/Server" + "$ref": "#/components/schemas/OpenAIFunction" } ] }, - "sipUri": { + "metadata": { + "type": "object", + "description": "Provider-specific metadata. Polymorphic across tool variants with no shared\ndiscriminator, so it is validated as a plain object (mirrors how\n`ToolCallResult.metadata` is typed)." + }, + "templateId": { "type": "string", - "description": "This is the SIP URI of the phone number. You can SIP INVITE this. The assistant attached to this number will answer.\n\nThis is case-insensitive." + "description": "This is the unique identifier for the template this tool was created from." }, - "authentication": { - "description": "This enables authentication for incoming SIP INVITE requests to the `sipUri`.\n\nIf not set, any username/password to the 401 challenge of the SIP INVITE will be accepted.", - "allOf": [ - { - "$ref": "#/components/schemas/SipAuthentication" - } - ] - } - } - }, - "UpdateTelnyxPhoneNumberDTO": { - "type": "object", - "properties": { - "fallbackDestination": { - "description": "This is the fallback destination an inbound call will be transferred to if:\n1. `assistantId` is not set\n2. `squadId` is not set\n3. and, `assistant-request` message to the `serverUrl` fails\n\nIf this is not set and above conditions are met, the inbound call is hung up with an error message.", - "oneOf": [ - { - "$ref": "#/components/schemas/TransferDestinationNumber", - "title": "NumberTransferDestination" - }, - { - "$ref": "#/components/schemas/TransferDestinationSip", - "title": "SipTransferDestination" - } - ] + "server": { + "$ref": "#/components/schemas/Server" }, - "hooks": { + "async": { + "type": "boolean" + }, + "destinations": { + "description": "These are the destinations that the call can be transferred to.", "type": "array", - "description": "This is the hooks that will be used for incoming calls to this phone number.", "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/PhoneNumberHookCallRinging", - "title": "PhoneNumberHookCallRinging" - }, - { - "$ref": "#/components/schemas/PhoneNumberHookCallEnding", - "title": "PhoneNumberHookCallEnding" - } - ] + "type": "object" } }, "name": { "type": "string", - "description": "This is the name of the phone number. This is just for your own reference.", - "maxLength": 40 + "description": "This is the name of the tool. This will be passed to the model." }, - "assistantId": { + "subType": { "type": "string", - "description": "This is the assistant that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId` nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + "description": "This is the sub type of the tool (e.g. for computer, bash and text-editor tools)." }, - "workflowId": { + "displayWidthPx": { + "type": "number", + "description": "The display width in pixels (computer tool)." + }, + "displayHeightPx": { + "type": "number", + "description": "The display height in pixels (computer tool)." + }, + "displayNumber": { + "type": "number", + "description": "Optional display number (computer tool)." + }, + "knowledgeBases": { + "description": "The knowledge bases to query (query tool).", + "type": "array", + "items": { + "$ref": "#/components/schemas/KnowledgeBase" + } + }, + "url": { "type": "string", - "description": "This is the workflow that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + "description": "This is where the request will be sent (api-request tool)." }, - "squadId": { + "method": { "type": "string", - "description": "This is the squad that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + "description": "This is the HTTP method for the request (api-request tool).", + "enum": [ + "POST", + "GET", + "PUT", + "PATCH", + "DELETE" + ] }, - "server": { - "description": "This is where Vapi will send webhooks. You can find all webhooks available along with their shape in ServerMessage schema.\n\nThe order of precedence is:\n\n1. assistant.server\n2. phoneNumber.server\n3. org.server", + "headers": { + "description": "These are the headers to send with the request (api-request / sip-request tool).", "allOf": [ { - "$ref": "#/components/schemas/Server" + "$ref": "#/components/schemas/JsonSchema" } ] }, - "number": { - "type": "string", - "description": "These are the digits of the phone number you own on your Telnyx." + "body": { + "type": "object", + "description": "This is the body of the request. Either a JSON schema (api-request) or a\nliteral string / schema (sip-request)." }, - "credentialId": { - "type": "string", - "description": "This is the credential you added in dashboard.vapi.ai/keys. This is used to configure the number to send inbound calls to Vapi, make outbound calls and do live call updates like transfers and hangups." - } - } - }, - "ImportVonagePhoneNumberDTO": { - "type": "object", - "properties": { - "fallbackDestination": { - "description": "This is the fallback destination an inbound call will be transferred to if:\n1. `assistantId` is not set\n2. `squadId` is not set\n3. and, `assistant-request` message to the `serverUrl` fails\n\nIf this is not set and above conditions are met, the inbound call is hung up with an error message.", - "oneOf": [ - { - "$ref": "#/components/schemas/TransferDestinationNumber", - "title": "NumberTransferDestination" - }, + "backoffPlan": { + "description": "This is the backoff plan if the request fails.", + "allOf": [ { - "$ref": "#/components/schemas/TransferDestinationSip", - "title": "SipTransferDestination" + "$ref": "#/components/schemas/BackoffPlan" } ] }, - "hooks": { - "type": "array", - "description": "This is the hooks that will be used for incoming calls to this phone number.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/PhoneNumberHookCallRinging", - "title": "PhoneNumberHookCallRinging" - }, - { - "$ref": "#/components/schemas/PhoneNumberHookCallEnding", - "title": "PhoneNumberHookCallEnding" - } - ] - } + "timeoutSeconds": { + "type": "number", + "description": "This is the timeout in seconds for the request.", + "minimum": 1, + "maximum": 300 }, - "vonagePhoneNumber": { + "description": { "type": "string", - "description": "These are the digits of the phone number you own on your Vonage.", - "deprecated": true + "description": "This is the description of the tool. This will be passed to the model." + }, + "variableExtractionPlan": { + "description": "This is the plan to extract variables from the tool's response.", + "allOf": [ + { + "$ref": "#/components/schemas/VariableExtractionPlan" + } + ] }, "credentialId": { "type": "string", - "description": "This is the credential you added in dashboard.vapi.ai/keys. This is used to configure the number to send inbound calls to Vapi, make outbound calls and do live call updates like transfers and hangups." + "description": "This is the credential ID that will be used for authorization." }, - "name": { - "type": "string", - "description": "This is the name of the phone number. This is just for your own reference.", - "maxLength": 40 + "extendedDelayWhenPrecededByTextEnabled": { + "type": "boolean" }, - "assistantId": { + "beepDetectionEnabled": { + "type": "boolean" + }, + "code": { "type": "string", - "description": "This is the assistant that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId` nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + "description": "This is the TypeScript code that will be executed when the tool is called (code tool).", + "maxLength": 50000 }, - "workflowId": { + "environmentVariables": { + "description": "These are the environment variables available in the code via the `env` object (code tool).", + "type": "array", + "items": { + "$ref": "#/components/schemas/CodeToolEnvironmentVariable" + } + }, + "parameters": { + "description": "These are the static parameters to merge into the tool's request body.", + "type": "array", + "items": { + "$ref": "#/components/schemas/ToolParameter" + } + }, + "encryptedPaths": { + "description": "This is the paths to encrypt in the request body.", + "type": "array", + "items": { + "type": "string" + } + }, + "sipInfoDtmfEnabled": { + "type": "boolean", + "description": "This enables sending DTMF tones via SIP INFO messages instead of RFC 2833." + }, + "verb": { "type": "string", - "description": "This is the workflow that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + "description": "This is the SIP method to send (sip-request tool).", + "enum": [ + "INFO", + "MESSAGE", + "NOTIFY" + ] }, - "squadId": { + "defaultResult": { "type": "string", - "description": "This is the squad that will be used for incoming calls to this phone number.\n\nIf neither `assistantId`, `squadId`, nor `workflowId` is set, `assistant-request` will be sent to your Server URL. Check `ServerMessage` and `ServerMessageResponse` for the shape of the message and response that is expected." + "description": "This is the default local tool result message used when no runtime override is returned (handoff tool)." }, - "server": { - "description": "This is where Vapi will send webhooks. You can find all webhooks available along with their shape in ServerMessage schema.\n\nThe order of precedence is:\n\n1. assistant.server\n2. phoneNumber.server\n3. org.server", - "allOf": [ - { - "$ref": "#/components/schemas/Server" - } - ] - } - }, - "required": [ - "vonagePhoneNumber", - "credentialId" - ] - }, - "PhoneNumberPaginatedResponse": { - "type": "object", - "properties": { - "results": { + "toolMessages": { + "description": "Per-tool message overrides for individual tools loaded from the MCP server (mcp tool).", "type": "array", - "description": "A list of phone numbers, which can be of any provider type.", "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ByoPhoneNumber" - }, - { - "$ref": "#/components/schemas/TwilioPhoneNumber" - }, - { - "$ref": "#/components/schemas/VonagePhoneNumber" - }, - { - "$ref": "#/components/schemas/VapiPhoneNumber" - }, - { - "$ref": "#/components/schemas/TelnyxPhoneNumber" - } - ] + "$ref": "#/components/schemas/McpToolMessages" } - }, - "metadata": { - "description": "Metadata about the pagination.", + }, + "rejectionPlan": { + "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", "allOf": [ { - "$ref": "#/components/schemas/PaginationMeta" + "$ref": "#/components/schemas/ToolRejectionPlan" } ] } - }, - "required": [ - "results", - "metadata" - ] + } }, - "ApiRequestTool": { + "UpdateToolDraftDTO": { "type": "object", "properties": { "messages": { "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", "items": { "oneOf": [ { @@ -33058,163 +57105,207 @@ }, "type": { "type": "string", - "enum": [ - "apiRequest" - ], - "description": "The type of tool. \"apiRequest\" for API request tool." - }, - "method": { - "type": "string", - "enum": [ - "POST", - "GET", - "PUT", - "PATCH", - "DELETE" + "description": "This is the type of the tool.", + "enum": [ + "dtmf", + "endCall", + "knowledgeBase", + "transferCall", + "transferCancel", + "transferSuccessful", + "handoff", + "output", + "voicemail", + "query", + "sms", + "sipRequest", + "function", + "mcp", + "apiRequest", + "code", + "bash", + "computer", + "textEditor", + "google.calendar.event.create", + "google.calendar.availability.check", + "google.sheets.row.append", + "slack.message.send", + "gohighlevel.calendar.event.create", + "gohighlevel.calendar.availability.check", + "gohighlevel.contact.create", + "gohighlevel.contact.get", + "make", + "ghl" ] }, - "timeoutSeconds": { - "type": "number", - "description": "This is the timeout in seconds for the request. Defaults to 20 seconds.\n\n@default 20", - "minimum": 1, - "maximum": 300, - "example": 20 + "function": { + "description": "This is the function definition of the tool.", + "allOf": [ + { + "$ref": "#/components/schemas/OpenAIFunction" + } + ] }, - "id": { - "type": "string", - "description": "This is the unique identifier for the tool." + "metadata": { + "type": "object", + "description": "Provider-specific metadata. Polymorphic across tool variants with no shared\ndiscriminator, so it is validated as a plain object (mirrors how\n`ToolCallResult.metadata` is typed)." }, - "orgId": { + "templateId": { "type": "string", - "description": "This is the unique identifier for the organization that this tool belongs to." + "description": "This is the unique identifier for the template this tool was created from." }, - "createdAt": { - "format": "date-time", - "type": "string", - "description": "This is the ISO 8601 date-time string of when the tool was created." + "server": { + "$ref": "#/components/schemas/Server" }, - "updatedAt": { - "format": "date-time", - "type": "string", - "description": "This is the ISO 8601 date-time string of when the tool was last updated." + "async": { + "type": "boolean" }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", - "allOf": [ - { - "$ref": "#/components/schemas/ToolRejectionPlan" - } - ] + "destinations": { + "description": "These are the destinations that the call can be transferred to.", + "type": "array", + "items": { + "type": "object" + } }, "name": { "type": "string", - "description": "This is the name of the tool. This will be passed to the model.\n\nMust be a-z, A-Z, 0-9, or contain underscores and dashes, with a maximum length of 40.", - "maxLength": 40, - "pattern": "/^[a-zA-Z0-9_-]{1,40}$/" + "description": "This is the name of the tool. This will be passed to the model." }, - "description": { + "subType": { "type": "string", - "description": "This is the description of the tool. This will be passed to the model.", - "maxLength": 1000 + "description": "This is the sub type of the tool (e.g. for computer, bash and text-editor tools)." + }, + "displayWidthPx": { + "type": "number", + "description": "The display width in pixels (computer tool)." + }, + "displayHeightPx": { + "type": "number", + "description": "The display height in pixels (computer tool)." + }, + "displayNumber": { + "type": "number", + "description": "Optional display number (computer tool)." + }, + "knowledgeBases": { + "description": "The knowledge bases to query (query tool).", + "type": "array", + "items": { + "$ref": "#/components/schemas/KnowledgeBase" + } }, "url": { "type": "string", - "description": "This is where the request will be sent." + "description": "This is where the request will be sent (api-request tool)." }, - "body": { - "description": "This is the body of the request.", - "allOf": [ - { - "$ref": "#/components/schemas/JsonSchema" - } + "method": { + "type": "string", + "description": "This is the HTTP method for the request (api-request tool).", + "enum": [ + "POST", + "GET", + "PUT", + "PATCH", + "DELETE" ] }, "headers": { - "description": "These are the headers to send with the request.", + "description": "These are the headers to send with the request (api-request / sip-request tool).", "allOf": [ { "$ref": "#/components/schemas/JsonSchema" } ] }, + "body": { + "type": "object", + "description": "This is the body of the request. Either a JSON schema (api-request) or a\nliteral string / schema (sip-request)." + }, "backoffPlan": { - "description": "This is the backoff plan if the request fails. Defaults to undefined (the request will not be retried).\n\n@default undefined (the request will not be retried)", + "description": "This is the backoff plan if the request fails.", "allOf": [ { "$ref": "#/components/schemas/BackoffPlan" } ] }, + "timeoutSeconds": { + "type": "number", + "description": "This is the timeout in seconds for the request.", + "minimum": 1, + "maximum": 300 + }, + "description": { + "type": "string", + "description": "This is the description of the tool. This will be passed to the model." + }, "variableExtractionPlan": { - "description": "This is the plan to extract variables from the tool's response. These will be accessible during the call and stored in `call.artifact.variableValues` after the call.\n\nUsage:\n1. Use `aliases` to extract variables from the tool's response body. (Most common case)\n\n```json\n{\n \"aliases\": [\n {\n \"key\": \"customerName\",\n \"value\": \"{{customer.name}}\"\n },\n {\n \"key\": \"customerAge\",\n \"value\": \"{{customer.age}}\"\n }\n ]\n}\n```\n\nThe tool response body is made available to the liquid template.\n\n2. Use `aliases` to extract variables from the tool's response body if the response is an array.\n\n```json\n{\n \"aliases\": [\n {\n \"key\": \"customerName\",\n \"value\": \"{{$[0].name}}\"\n },\n {\n \"key\": \"customerAge\",\n \"value\": \"{{$[0].age}}\"\n }\n ]\n}\n```\n\n$ is a shorthand for the tool's response body. `$[0]` is the first item in the array. `$[n]` is the nth item in the array. Note, $ is available regardless of the response body type (both object and array).\n\n3. Use `aliases` to extract variables from the tool's response headers.\n\n```json\n{\n \"aliases\": [\n {\n \"key\": \"customerName\",\n \"value\": \"{{tool.response.headers.customer-name}}\"\n },\n {\n \"key\": \"customerAge\",\n \"value\": \"{{tool.response.headers.customer-age}}\"\n }\n ]\n}\n```\n\n`tool.response` is made available to the liquid template. Particularly, both `tool.response.headers` and `tool.response.body` are available. Note, `tool.response` is available regardless of the response body type (both object and array).\n\n4. Use `schema` to extract a large portion of the tool's response body.\n\n4.1. If you hit example.com and it returns `{\"name\": \"John\", \"age\": 30}`, then you can specify the schema as:\n\n```json\n{\n \"schema\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n },\n \"age\": {\n \"type\": \"number\"\n }\n }\n }\n}\n```\nThese will be extracted as `{{ name }}` and `{{ age }}` respectively. To emphasize, object properties are extracted as direct global variables.\n\n4.2. If you hit example.com and it returns `{\"name\": {\"first\": \"John\", \"last\": \"Doe\"}}`, then you can specify the schema as:\n\n```json\n{\n \"schema\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"object\",\n \"properties\": {\n \"first\": {\n \"type\": \"string\"\n },\n \"last\": {\n \"type\": \"string\"\n }\n }\n }\n }\n }\n}\n```\n\nThese will be extracted as `{{ name }}`. And, `{{ name.first }}` and `{{ name.last }}` will be accessible.\n\n4.3. If you hit example.com and it returns `[\"94123\", \"94124\"]`, then you can specify the schema as:\n\n```json\n{\n \"schema\": {\n \"type\": \"array\",\n \"title\": \"zipCodes\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n}\n```\n\nThis will be extracted as `{{ zipCodes }}`. To access the array items, you can use `{{ zipCodes[0] }}` and `{{ zipCodes[1] }}`.\n\n4.4. If you hit example.com and it returns `[{\"name\": \"John\", \"age\": 30, \"zipCodes\": [\"94123\", \"94124\"]}, {\"name\": \"Jane\", \"age\": 25, \"zipCodes\": [\"94125\", \"94126\"]}]`, then you can specify the schema as:\n\n```json\n{\n \"schema\": {\n \"type\": \"array\",\n \"title\": \"people\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n },\n \"age\": {\n \"type\": \"number\"\n },\n \"zipCodes\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n }\n }\n }\n}\n```\n\nThis will be extracted as `{{ people }}`. To access the array items, you can use `{{ people[n].name }}`, `{{ people[n].age }}`, `{{ people[n].zipCodes }}`, `{{ people[n].zipCodes[0] }}` and `{{ people[n].zipCodes[1] }}`.\n\nNote: Both `aliases` and `schema` can be used together.", + "description": "This is the plan to extract variables from the tool's response.", "allOf": [ { "$ref": "#/components/schemas/VariableExtractionPlan" } ] - } - }, - "required": [ - "type", - "method", - "id", - "orgId", - "createdAt", - "updatedAt", - "url" - ] - }, - "DtmfTool": { - "type": "object", - "properties": { - "messages": { + }, + "credentialId": { + "type": "string", + "description": "This is the credential ID that will be used for authorization." + }, + "extendedDelayWhenPrecededByTextEnabled": { + "type": "boolean" + }, + "beepDetectionEnabled": { + "type": "boolean" + }, + "code": { + "type": "string", + "description": "This is the TypeScript code that will be executed when the tool is called (code tool).", + "maxLength": 50000 + }, + "environmentVariables": { + "description": "These are the environment variables available in the code via the `env` object (code tool).", "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" - } - ] + "$ref": "#/components/schemas/CodeToolEnvironmentVariable" } }, - "type": { - "type": "string", - "enum": [ - "dtmf" - ], - "description": "The type of tool. \"dtmf\" for DTMF tool." + "parameters": { + "description": "These are the static parameters to merge into the tool's request body.", + "type": "array", + "items": { + "$ref": "#/components/schemas/ToolParameter" + } }, - "id": { - "type": "string", - "description": "This is the unique identifier for the tool." + "encryptedPaths": { + "description": "This is the paths to encrypt in the request body.", + "type": "array", + "items": { + "type": "string" + } }, - "orgId": { - "type": "string", - "description": "This is the unique identifier for the organization that this tool belongs to." + "sipInfoDtmfEnabled": { + "type": "boolean", + "description": "This enables sending DTMF tones via SIP INFO messages instead of RFC 2833." }, - "createdAt": { - "format": "date-time", + "verb": { "type": "string", - "description": "This is the ISO 8601 date-time string of when the tool was created." + "description": "This is the SIP method to send (sip-request tool).", + "enum": [ + "INFO", + "MESSAGE", + "NOTIFY" + ] }, - "updatedAt": { - "format": "date-time", + "defaultResult": { "type": "string", - "description": "This is the ISO 8601 date-time string of when the tool was last updated." + "description": "This is the default local tool result message used when no runtime override is returned (handoff tool)." + }, + "toolMessages": { + "description": "Per-tool message overrides for individual tools loaded from the MCP server (mcp tool).", + "type": "array", + "items": { + "$ref": "#/components/schemas/McpToolMessages" + } }, "rejectionPlan": { "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", @@ -33224,125 +57315,251 @@ } ] } + } + }, + "ToolDraftPaginatedMetadata": { + "type": "object", + "properties": { + "nextCursor": { + "type": "string", + "nullable": true + }, + "hasNextPage": { + "type": "boolean" + }, + "limit": { + "type": "number" + } }, "required": [ - "type", - "id", - "orgId", - "createdAt", - "updatedAt" + "nextCursor", + "hasNextPage", + "limit" ] }, - "EndCallTool": { + "ToolDraftPaginatedResponse": { "type": "object", "properties": { - "messages": { + "results": { "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" - } - ] + "$ref": "#/components/schemas/ToolDraft" } }, - "type": { + "metadata": { + "$ref": "#/components/schemas/ToolDraftPaginatedMetadata" + } + }, + "required": [ + "results", + "metadata" + ] + }, + "ToolDraftConflictResponseDTO": { + "type": "object", + "properties": { + "existingDraftId": { + "type": "string", + "nullable": true + }, + "error": { + "type": "string" + }, + "message": { + "type": "string" + } + }, + "required": [ + "existingDraftId", + "error", + "message" + ] + }, + "GetToolDraftsDTO": { + "type": "object", + "properties": { + "cursor": { + "type": "string", + "description": "Opaque base64-encoded keyset cursor. Omit on first page." + }, + "limit": { + "type": "number", + "description": "Page size, defaults to 25, capped at 100.", + "minimum": 1, + "maximum": 100 + }, + "createdBy": { + "type": "string" + } + } + }, + "UpdateToolVersionMetadataDTO": { + "type": "object", + "properties": { + "versionName": { + "type": "string", + "nullable": true, + "description": "Optional human-readable label for this version. Pass `null` to clear.", + "maxLength": 80 + }, + "versionDescription": { + "type": "string", + "nullable": true, + "description": "Optional description for this version. Pass `null` to clear.", + "maxLength": 500 + } + } + }, + "ToolPinnedConflictResponseDTO": { + "type": "object", + "properties": { + "error": { "type": "string", "enum": [ - "endCall" + "tool_pinned" + ] + }, + "message": { + "type": "string", + "description": "Human-readable reason the parent-tool delete was rejected." + } + }, + "required": [ + "error", + "message" + ] + }, + "CreateFileDTO": { + "type": "object", + "properties": { + "file": { + "type": "string", + "description": "The file to upload.", + "format": "binary" + }, + "purpose": { + "type": "string", + "description": "Optional product flow that owns the uploaded file.", + "enum": [ + "assistant", + "composer-attachment", + "knowledge-base-v2" + ] + }, + "metadata": { + "type": "string", + "description": "Optional JSON-encoded metadata for multipart uploads.", + "maxLength": 4096 + } + }, + "required": [ + "file" + ] + }, + "File": { + "type": "object", + "properties": { + "object": { + "type": "string", + "enum": [ + "file" + ] + }, + "status": { + "enum": [ + "processing", + "done", + "failed" ], - "description": "The type of tool. \"endCall\" for End Call tool." + "type": "string" + }, + "name": { + "type": "string", + "description": "This is the name of the file. This is just for your own reference.", + "maxLength": 40 + }, + "originalName": { + "type": "string" + }, + "bytes": { + "type": "number" + }, + "purpose": { + "type": "string" + }, + "mimetype": { + "type": "string" + }, + "key": { + "type": "string" + }, + "path": { + "type": "string" + }, + "bucket": { + "type": "string" + }, + "url": { + "type": "string" + }, + "parsedTextUrl": { + "type": "string" + }, + "parsedTextBytes": { + "type": "number" + }, + "metadata": { + "type": "object" }, "id": { "type": "string", - "description": "This is the unique identifier for the tool." + "description": "This is the unique identifier for the file." }, "orgId": { "type": "string", - "description": "This is the unique identifier for the organization that this tool belongs to." + "description": "This is the unique identifier for the org that this file belongs to." }, "createdAt": { "format": "date-time", "type": "string", - "description": "This is the ISO 8601 date-time string of when the tool was created." + "description": "This is the ISO 8601 date-time string of when the file was created." }, "updatedAt": { "format": "date-time", "type": "string", - "description": "This is the ISO 8601 date-time string of when the tool was last updated." - }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", - "allOf": [ - { - "$ref": "#/components/schemas/ToolRejectionPlan" - } - ] + "description": "This is the ISO 8601 date-time string of when the file was last updated." } }, "required": [ - "type", "id", "orgId", "createdAt", "updatedAt" ] }, - "FunctionTool": { + "UpdateFileDTO": { "type": "object", "properties": { - "messages": { - "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" - } - ] - } - }, - "type": { + "name": { + "type": "string", + "description": "This is the name of the file. This is just for your own reference.", + "minLength": 1, + "maxLength": 40 + } + } + }, + "CustomKnowledgeBase": { + "type": "object", + "properties": { + "provider": { "type": "string", + "description": "This knowledge base is bring your own knowledge base implementation.", "enum": [ - "function" - ], - "description": "The type of tool. \"function\" for Function tool." - }, - "async": { - "type": "boolean", - "example": false, - "description": "This determines if the tool is async.\n\n If async, the assistant will move forward without waiting for your server to respond. This is useful if you just want to trigger something on your server.\n\n If sync, the assistant will wait for your server to respond. This is useful if want assistant to respond with the result from your server.\n\n Defaults to synchronous (`false`)." + "custom-knowledge-base" + ] }, "server": { - "description": "\n This is the server where a `tool-calls` webhook will be sent.\n\n Notes:\n - Webhook is sent to this server when a tool call is made.\n - Webhook contains the call, assistant, and phone number objects.\n - Webhook contains the variables set on the assistant.\n - Webhook is sent to the first available URL in this order: {{tool.server.url}}, {{assistant.server.url}}, {{phoneNumber.server.url}}, {{org.server.url}}.\n - Webhook expects a response with tool call result.", + "description": "This is where the knowledge base request will be sent.\n\nRequest Example:\n\nPOST https://{server.url}\nContent-Type: application/json\n\n{\n \"messsage\": {\n \"type\": \"knowledge-base-request\",\n \"messages\": [\n {\n \"role\": \"user\",\n \"content\": \"Why is ocean blue?\"\n }\n ],\n ...other metadata about the call...\n }\n}\n\nResponse Expected:\n```\n{\n \"message\": {\n \"role\": \"assistant\",\n \"content\": \"The ocean is blue because water absorbs everything but blue.\",\n }, // YOU CAN RETURN THE EXACT RESPONSE TO SPEAK\n \"documents\": [\n {\n \"content\": \"The ocean is blue primarily because water absorbs colors in the red part of the light spectrum and scatters the blue light, making it more visible to our eyes.\",\n \"similarity\": 1\n },\n {\n \"content\": \"Blue light is scattered more by the water molecules than other colors, enhancing the blue appearance of the ocean.\",\n \"similarity\": .5\n }\n ] // OR, YOU CAN RETURN AN ARRAY OF DOCUMENTS THAT WILL BE SENT TO THE MODEL\n}\n```", "allOf": [ { "$ref": "#/components/schemas/Server" @@ -33351,4749 +57568,5781 @@ }, "id": { "type": "string", - "description": "This is the unique identifier for the tool." + "description": "This is the id of the knowledge base." }, "orgId": { "type": "string", - "description": "This is the unique identifier for the organization that this tool belongs to." - }, - "createdAt": { - "format": "date-time", - "type": "string", - "description": "This is the ISO 8601 date-time string of when the tool was created." - }, - "updatedAt": { - "format": "date-time", + "description": "This is the org id of the knowledge base." + } + }, + "required": [ + "provider", + "server", + "id", + "orgId" + ] + }, + "UpdateCustomKnowledgeBaseDTO": { + "type": "object", + "properties": { + "provider": { "type": "string", - "description": "This is the ISO 8601 date-time string of when the tool was last updated." + "description": "This knowledge base is bring your own knowledge base implementation.", + "enum": [ + "custom-knowledge-base" + ] }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "server": { + "description": "This is where the knowledge base request will be sent.\n\nRequest Example:\n\nPOST https://{server.url}\nContent-Type: application/json\n\n{\n \"messsage\": {\n \"type\": \"knowledge-base-request\",\n \"messages\": [\n {\n \"role\": \"user\",\n \"content\": \"Why is ocean blue?\"\n }\n ],\n ...other metadata about the call...\n }\n}\n\nResponse Expected:\n```\n{\n \"message\": {\n \"role\": \"assistant\",\n \"content\": \"The ocean is blue because water absorbs everything but blue.\",\n }, // YOU CAN RETURN THE EXACT RESPONSE TO SPEAK\n \"documents\": [\n {\n \"content\": \"The ocean is blue primarily because water absorbs colors in the red part of the light spectrum and scatters the blue light, making it more visible to our eyes.\",\n \"similarity\": 1\n },\n {\n \"content\": \"Blue light is scattered more by the water molecules than other colors, enhancing the blue appearance of the ocean.\",\n \"similarity\": .5\n }\n ] // OR, YOU CAN RETURN AN ARRAY OF DOCUMENTS THAT WILL BE SENT TO THE MODEL\n}\n```", "allOf": [ { - "$ref": "#/components/schemas/ToolRejectionPlan" + "$ref": "#/components/schemas/Server" } ] + } + } + }, + "CreateKnowledgeBaseV2DTO": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 1, + "maxLength": 80 + }, + "description": { + "type": "string", + "nullable": true, + "maxLength": 1000 + } + }, + "required": [ + "name" + ] + }, + "KnowledgeBaseV2": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 1, + "maxLength": 80 + }, + "description": { + "type": "string", + "nullable": true, + "maxLength": 1000 + }, + "id": { + "type": "string" }, - "function": { - "description": "This is the function definition of the tool.", - "allOf": [ - { - "$ref": "#/components/schemas/OpenAIFunction" - } - ] + "orgId": { + "type": "string" + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" } }, "required": [ - "type", + "name", "id", "orgId", "createdAt", "updatedAt" ] }, - "GhlTool": { + "KnowledgeBaseV2File": { "type": "object", "properties": { - "messages": { - "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" - } - ] - } + "id": { + "type": "string" }, - "type": { - "type": "string", - "enum": [ - "ghl" - ], - "description": "The type of tool. \"ghl\" for GHL tool." + "knowledgeBaseV2Id": { + "type": "string" }, - "id": { - "type": "string", - "description": "This is the unique identifier for the tool." + "fileId": { + "type": "string" }, - "orgId": { + "fileName": { + "type": "string" + }, + "mimetype": { + "type": "string" + }, + "bytes": { + "type": "number" + }, + "status": { "type": "string", - "description": "This is the unique identifier for the organization that this tool belongs to." + "enum": [ + "indexing", + "ready", + "failed" + ] }, "createdAt": { - "format": "date-time", "type": "string", - "description": "This is the ISO 8601 date-time string of when the tool was created." + "format": "date-time" }, "updatedAt": { - "format": "date-time", "type": "string", - "description": "This is the ISO 8601 date-time string of when the tool was last updated." - }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", - "allOf": [ - { - "$ref": "#/components/schemas/ToolRejectionPlan" - } - ] - }, - "metadata": { - "$ref": "#/components/schemas/GhlToolMetadata" + "format": "date-time" } }, "required": [ - "type", "id", - "orgId", + "knowledgeBaseV2Id", + "fileId", + "status", "createdAt", - "updatedAt", - "metadata" + "updatedAt" ] }, - "MakeTool": { + "AttachKnowledgeBaseV2FileDTO": { "type": "object", "properties": { - "messages": { - "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" - } - ] - } + "fileId": { + "type": "string" + } + }, + "required": [ + "fileId" + ] + }, + "UpdateKnowledgeBaseV2DTO": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 1, + "maxLength": 80 }, - "type": { + "description": { "type": "string", - "enum": [ - "make" - ], - "description": "The type of tool. \"make\" for Make tool." + "nullable": true, + "maxLength": 1000 + } + } + }, + "KnowledgeBaseV2WithFiles": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 1, + "maxLength": 80 }, - "id": { + "description": { "type": "string", - "description": "This is the unique identifier for the tool." + "nullable": true, + "maxLength": 1000 + }, + "id": { + "type": "string" }, "orgId": { - "type": "string", - "description": "This is the unique identifier for the organization that this tool belongs to." + "type": "string" }, "createdAt": { - "format": "date-time", "type": "string", - "description": "This is the ISO 8601 date-time string of when the tool was created." + "format": "date-time" }, "updatedAt": { - "format": "date-time", "type": "string", - "description": "This is the ISO 8601 date-time string of when the tool was last updated." + "format": "date-time" }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", - "allOf": [ - { - "$ref": "#/components/schemas/ToolRejectionPlan" - } - ] + "files": { + "type": "array", + "items": { + "$ref": "#/components/schemas/KnowledgeBaseV2File" + } }, - "metadata": { - "$ref": "#/components/schemas/MakeToolMetadata" + "toolId": { + "type": "string", + "nullable": true, + "description": "Id of the tool that searches this knowledge base (at most one per base; provisioned on creation). Attach it to an assistant via model.toolIds. Null when the base has no search tool yet." } }, "required": [ - "type", + "name", "id", "orgId", "createdAt", "updatedAt", - "metadata" + "files", + "toolId" ] }, - "TransferCallTool": { + "StructuredOutputRunResult": { "type": "object", "properties": { - "messages": { - "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" - } - ] + "name": { + "type": "string", + "description": "This is the name of the structured output that produced this value." + }, + "result": { + "description": "This is the extracted value, shaped by the structured output's schema.", + "oneOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "object" + }, + { + "type": "array" + } + ], + "nullable": true + }, + "compliancePlan": { + "$ref": "#/components/schemas/ComplianceOverride" + } + }, + "required": [ + "name", + "result" + ] + }, + "StructuredOutputRunPreviewResponse": { + "type": "object", + "properties": { + "skipped": { + "type": "object", + "description": "These are the structured outputs whose conditions gated them, keyed by\nstructured output id. Absent when nothing was skipped. An entry here means\nno extraction ran and no cost was incurred for that output.", + "additionalProperties": { + "$ref": "#/components/schemas/SkippedStructuredOutput" } + } + } + }, + "StructuredOutputRerunResponse": { + "type": "object", + "properties": { + "workflowId": { + "type": "string", + "description": "This is the id of the workflow processing the rerun." }, + "message": { + "type": "string" + } + }, + "required": [ + "message" + ] + }, + "StructuredOutput": { + "type": "object", + "properties": { "type": { "type": "string", + "description": "This is the type of structured output.\n\n- 'ai': Uses an LLM to extract structured data from the conversation (default).\n- 'regex': Uses a regex pattern to extract data from the transcript without an LLM.", "enum": [ - "transferCall" + "ai", + "regex" ] }, - "destinations": { + "regex": { + "type": "string", + "description": "This is the regex pattern to match against the transcript.\n\nOnly used when type is 'regex'. Supports both raw patterns (e.g. '\\d+') and\nregex literal format (e.g. '/\\d+/gi'). Uses RE2 syntax for safety.\n\nThe result depends on the schema type:\n- boolean: true if the pattern matches, false otherwise\n- string: the first match or first capture group\n- number/integer: the first match parsed as a number\n- array: all matches", + "minLength": 1, + "maxLength": 1000 + }, + "model": { + "description": "This is the model that will be used to extract the structured output.\n\nTo provide your own custom system and user prompts for structured output extraction, populate the messages array with your system and user messages. You can specify liquid templating in your system and user messages.\nBetween the system or user messages, you must reference either 'transcript' or 'messages' with the `{{}}` syntax to access the conversation history.\nBetween the system or user messages, you must reference a variation of the structured output with the `{{}}` syntax to access the structured output definition.\ni.e.:\n`{{structuredOutput}}`\n`{{structuredOutput.name}}`\n`{{structuredOutput.description}}`\n`{{structuredOutput.schema}}`\n\nIf model is not specified, GPT-4.1 will be used by default for extraction, utilizing default system and user prompts.\nIf messages or required fields are not specified, the default system and user prompts will be used.", + "oneOf": [ + { + "$ref": "#/components/schemas/WorkflowOpenAIModel", + "title": "WorkflowOpenAIModel" + }, + { + "$ref": "#/components/schemas/WorkflowAnthropicModel", + "title": "WorkflowAnthropicModel" + }, + { + "$ref": "#/components/schemas/WorkflowAnthropicBedrockModel", + "title": "WorkflowAnthropicBedrockModel" + }, + { + "$ref": "#/components/schemas/WorkflowGoogleModel", + "title": "WorkflowGoogleModel" + }, + { + "$ref": "#/components/schemas/WorkflowCustomModel", + "title": "WorkflowCustomModel" + } + ] + }, + "compliancePlan": { + "description": "Compliance configuration for this output. Only enable overrides if no sensitive data will be stored.", + "example": { + "forceStoreOnHipaaEnabled": false + }, + "allOf": [ + { + "$ref": "#/components/schemas/ComplianceOverride" + } + ] + }, + "conditions": { "type": "array", - "description": "These are the destinations that the call can be transferred to. If no destinations are provided, server.url will be used to get the transfer destination once the tool is called.", + "nullable": true, + "description": "These are the conditions that gate the execution of this structured output. Every condition must pass for the structured output to run (AND semantics). When omitted or empty, no user-defined conditions gate this output. Send null to clear a previously saved gate.", + "example": [ + { + "type": "minMessages", + "count": 4 + }, + { + "type": "minCallDuration", + "seconds": 10 + } + ], "items": { "oneOf": [ { - "$ref": "#/components/schemas/TransferDestinationAssistant", - "title": "Assistant" + "$ref": "#/components/schemas/MinMessagesCondition", + "title": "MinMessagesCondition" }, { - "$ref": "#/components/schemas/TransferDestinationNumber", - "title": "Number" + "$ref": "#/components/schemas/MinCallDurationCondition", + "title": "MinCallDurationCondition" }, { - "$ref": "#/components/schemas/TransferDestinationSip", - "title": "Sip" + "$ref": "#/components/schemas/EndedReasonCondition", + "title": "EndedReasonCondition" } ] } }, "id": { "type": "string", - "description": "This is the unique identifier for the tool." + "description": "This is the unique identifier for the structured output." }, "orgId": { "type": "string", - "description": "This is the unique identifier for the organization that this tool belongs to." + "description": "This is the unique identifier for the org that this structured output belongs to." }, "createdAt": { "format": "date-time", "type": "string", - "description": "This is the ISO 8601 date-time string of when the tool was created." + "description": "This is the ISO 8601 date-time string of when the structured output was created." }, "updatedAt": { "format": "date-time", "type": "string", - "description": "This is the ISO 8601 date-time string of when the tool was last updated." + "description": "This is the ISO 8601 date-time string of when the structured output was last updated." }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "name": { + "type": "string", + "description": "This is the name of the structured output.", + "minLength": 1, + "maxLength": 40 + }, + "description": { + "type": "string", + "description": "This is the description of what the structured output extracts.\n\nUse this to provide context about what data will be extracted and how it will be used." + }, + "assistantIds": { + "description": "These are the assistant IDs that this structured output is linked to.\n\nWhen linked to assistants, this structured output will be available for extraction during those assistant's calls.", + "type": "array", + "items": { + "type": "string" + } + }, + "workflowIds": { + "description": "These are the workflow IDs that this structured output is linked to.\n\nWhen linked to workflows, this structured output will be available for extraction during those workflow's execution.", + "type": "array", + "items": { + "type": "string" + } + }, + "schema": { + "description": "This is the JSON Schema definition for the structured output.\n\nDefines the structure and validation rules for the data that will be extracted. Supports all JSON Schema features including:\n- Objects and nested properties\n- Arrays and array validation\n- String, number, boolean, and null types\n- Enums and const values\n- Validation constraints (min/max, patterns, etc.)\n- Composition with allOf, anyOf, oneOf", "allOf": [ { - "$ref": "#/components/schemas/ToolRejectionPlan" + "$ref": "#/components/schemas/JsonSchema" } ] } }, "required": [ - "type", "id", "orgId", "createdAt", - "updatedAt" + "updatedAt", + "name", + "schema" ] }, - "HandoffTool": { + "StructuredOutputPaginatedResponse": { "type": "object", "properties": { - "messages": { + "results": { "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" - } - ] + "$ref": "#/components/schemas/StructuredOutput" } }, + "metadata": { + "$ref": "#/components/schemas/PaginationMeta" + } + }, + "required": [ + "results", + "metadata" + ] + }, + "UpdateStructuredOutputDTO": { + "type": "object", + "properties": { "type": { "type": "string", - "description": "This is the type of the tool.\nWhen you're using handoff tool, we recommend adding this to your system prompt\n---\n# System context\n\nYou are part of a multi-agent system designed to make agent coordination and execution easy. Agents uses two primary abstraction: **Agents** and **Handoffs**. An agent encompasses instructions and tools and can hand off a conversation to another agent when appropriate. Handoffs are achieved by calling a handoff function, generally named `handoff_to_`. Handoffs between agents are handled seamlessly in the background; do not mention or draw attention to these handoffs in your conversation with the user.\n\n# Agent context\n\n{put your agent system prompt here}\n---", + "description": "This is the type of structured output.\n\n- 'ai': Uses an LLM to extract structured data from the conversation (default).\n- 'regex': Uses a regex pattern to extract data from the transcript without an LLM.", "enum": [ - "handoff" + "ai", + "regex" ] }, - "destinations": { - "type": "array", - "description": "These are the destinations that the call can be handed off to.\n\nUsage:\n1. Single destination\n\nUse `assistantId` to handoff the call to a saved assistant, or `assistantName` to handoff the call to an assistant in the same squad.\n\n```json\n{\n \"tools\": [\n {\n \"type\": \"handoff\",\n \"destinations\": [\n {\n \"type\": \"assistant\",\n \"assistantId\": \"assistant-123\", // or \"assistantName\": \"Assistant123\"\n \"description\": \"customer wants to be handed off to assistant-123\",\n \"contextEngineeringPlan\": {\n \"type\": \"all\"\n }\n }\n ],\n }\n ]\n}\n```\n\n2. Multiple destinations\n\n2.1. Multiple Tools, Each With One Destination (OpenAI recommended)\n\n```json\n{\n \"tools\": [\n {\n \"type\": \"handoff\",\n \"destinations\": [\n {\n \"type\": \"assistant\",\n \"assistantId\": \"assistant-123\",\n \"description\": \"customer wants to be handed off to assistant-123\",\n \"contextEngineeringPlan\": {\n \"type\": \"all\"\n }\n },\n ],\n },\n {\n \"type\": \"handoff\",\n \"destinations\": [\n {\n \"type\": \"assistant\",\n \"assistantId\": \"assistant-456\",\n \"description\": \"customer wants to be handed off to assistant-456\",\n \"contextEngineeringPlan\": {\n \"type\": \"all\"\n }\n }\n ],\n }\n ]\n}\n```\n\n2.2. One Tool, Multiple Destinations (Anthropic recommended)\n\n```json\n{\n \"tools\": [\n {\n \"type\": \"handoff\",\n \"destinations\": [\n {\n \"type\": \"assistant\",\n \"assistantId\": \"assistant-123\",\n \"description\": \"customer wants to be handed off to assistant-123\",\n \"contextEngineeringPlan\": {\n \"type\": \"all\"\n }\n },\n {\n \"type\": \"assistant\",\n \"assistantId\": \"assistant-456\",\n \"description\": \"customer wants to be handed off to assistant-456\",\n \"contextEngineeringPlan\": {\n \"type\": \"all\"\n }\n }\n ],\n }\n ]\n}\n```\n\n3. Dynamic destination\n\n3.1 To determine the destination dynamically, supply a `dynamic` handoff destination type and a `server` object.\n VAPI will send a handoff-destination-request webhook to the `server.url`.\n The response from the server will be used as the destination (if valid).\n\n```json\n{\n \"tools\": [\n {\n \"type\": \"handoff\",\n \"destinations\": [\n {\n \"type\": \"dynamic\",\n \"server\": {\n \"url\": \"https://example.com\"\n }\n }\n ],\n }\n ]\n}\n```\n\n3.2. To pass custom parameters to the server, you can use the `function` object.\n\n```json\n{\n \"tools\": [\n {\n \"type\": \"handoff\",\n \"destinations\": [\n {\n \"type\": \"dynamic\",\n \"server\": {\n \"url\": \"https://example.com\"\n },\n }\n ],\n \"function\": {\n \"name\": \"handoff\",\n \"description\": \"Call this function when the customer is ready to be handed off to the next assistant\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"destination\": {\n \"type\": \"string\",\n \"description\": \"Use dynamic when customer is ready to be handed off to the next assistant\",\n \"enum\": [\"dynamic\"]\n },\n \"customerAreaCode\": {\n \"type\": \"number\",\n \"description\": \"Area code of the customer\"\n },\n \"customerIntent\": {\n \"type\": \"string\",\n \"enum\": [\"new-customer\", \"existing-customer\"],\n \"description\": \"Use new-customer when customer is a new customer, existing-customer when customer is an existing customer\"\n },\n \"customerSentiment\": {\n \"type\": \"string\",\n \"enum\": [\"positive\", \"negative\", \"neutral\"],\n \"description\": \"Use positive when customer is happy, negative when customer is unhappy, neutral when customer is neutral\"\n }\n }\n }\n }\n }\n ]\n}\n```\n\nThe properties `customerAreaCode`, `customerIntent`, and `customerSentiment` will be passed to the server in the webhook request body.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/HandoffDestinationAssistant", - "title": "Assistant" - }, - { - "$ref": "#/components/schemas/HandoffDestinationDynamic", - "title": "Dynamic" - } - ] - } - }, - "id": { - "type": "string", - "description": "This is the unique identifier for the tool." - }, - "orgId": { - "type": "string", - "description": "This is the unique identifier for the organization that this tool belongs to." - }, - "createdAt": { - "format": "date-time", + "regex": { "type": "string", - "description": "This is the ISO 8601 date-time string of when the tool was created." + "description": "This is the regex pattern to match against the transcript.\n\nOnly used when type is 'regex'. Supports both raw patterns (e.g. '\\d+') and\nregex literal format (e.g. '/\\d+/gi'). Uses RE2 syntax for safety.\n\nThe result depends on the schema type:\n- boolean: true if the pattern matches, false otherwise\n- string: the first match or first capture group\n- number/integer: the first match parsed as a number\n- array: all matches", + "minLength": 1, + "maxLength": 1000 }, - "updatedAt": { - "format": "date-time", - "type": "string", - "description": "This is the ISO 8601 date-time string of when the tool was last updated." + "model": { + "description": "This is the model that will be used to extract the structured output.\n\nTo provide your own custom system and user prompts for structured output extraction, populate the messages array with your system and user messages. You can specify liquid templating in your system and user messages.\nBetween the system or user messages, you must reference either 'transcript' or 'messages' with the `{{}}` syntax to access the conversation history.\nBetween the system or user messages, you must reference a variation of the structured output with the `{{}}` syntax to access the structured output definition.\ni.e.:\n`{{structuredOutput}}`\n`{{structuredOutput.name}}`\n`{{structuredOutput.description}}`\n`{{structuredOutput.schema}}`\n\nIf model is not specified, GPT-4.1 will be used by default for extraction, utilizing default system and user prompts.\nIf messages or required fields are not specified, the default system and user prompts will be used.", + "oneOf": [ + { + "$ref": "#/components/schemas/WorkflowOpenAIModel", + "title": "WorkflowOpenAIModel" + }, + { + "$ref": "#/components/schemas/WorkflowAnthropicModel", + "title": "WorkflowAnthropicModel" + }, + { + "$ref": "#/components/schemas/WorkflowAnthropicBedrockModel", + "title": "WorkflowAnthropicBedrockModel" + }, + { + "$ref": "#/components/schemas/WorkflowGoogleModel", + "title": "WorkflowGoogleModel" + }, + { + "$ref": "#/components/schemas/WorkflowCustomModel", + "title": "WorkflowCustomModel" + } + ] }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "compliancePlan": { + "description": "Compliance configuration for this output. Only enable overrides if no sensitive data will be stored.", + "example": { + "forceStoreOnHipaaEnabled": false + }, "allOf": [ { - "$ref": "#/components/schemas/ToolRejectionPlan" + "$ref": "#/components/schemas/ComplianceOverride" } ] - } - }, - "required": [ - "type", - "id", - "orgId", - "createdAt", - "updatedAt" - ] - }, - "OutputTool": { - "type": "object", - "properties": { - "messages": { + }, + "conditions": { "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", + "nullable": true, + "description": "These are the conditions that gate the execution of this structured output. Every condition must pass for the structured output to run (AND semantics). When omitted or empty, no user-defined conditions gate this output. Send null to clear a previously saved gate.", + "example": [ + { + "type": "minMessages", + "count": 4 + }, + { + "type": "minCallDuration", + "seconds": 10 + } + ], "items": { "oneOf": [ { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" + "$ref": "#/components/schemas/MinMessagesCondition", + "title": "MinMessagesCondition" }, { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" + "$ref": "#/components/schemas/MinCallDurationCondition", + "title": "MinCallDurationCondition" }, { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" + "$ref": "#/components/schemas/EndedReasonCondition", + "title": "EndedReasonCondition" } ] } }, - "type": { + "name": { "type": "string", - "enum": [ - "output" - ], - "description": "The type of tool. \"output\" for Output tool." + "description": "This is the name of the structured output.", + "minLength": 1, + "maxLength": 40 }, - "id": { + "description": { "type": "string", - "description": "This is the unique identifier for the tool." + "description": "This is the description of what the structured output extracts.\n\nUse this to provide context about what data will be extracted and how it will be used." }, - "orgId": { - "type": "string", - "description": "This is the unique identifier for the organization that this tool belongs to." + "assistantIds": { + "description": "These are the assistant IDs that this structured output is linked to.\n\nWhen linked to assistants, this structured output will be available for extraction during those assistant's calls.", + "type": "array", + "items": { + "type": "string" + } }, - "createdAt": { - "format": "date-time", - "type": "string", - "description": "This is the ISO 8601 date-time string of when the tool was created." + "workflowIds": { + "description": "These are the workflow IDs that this structured output is linked to.\n\nWhen linked to workflows, this structured output will be available for extraction during those workflow's execution.", + "type": "array", + "items": { + "type": "string" + } + }, + "schema": { + "description": "This is the JSON Schema definition for the structured output.\n\nDefines the structure and validation rules for the data that will be extracted. Supports all JSON Schema features including:\n- Objects and nested properties\n- Arrays and array validation\n- String, number, boolean, and null types\n- Enums and const values\n- Validation constraints (min/max, patterns, etc.)\n- Composition with allOf, anyOf, oneOf", + "allOf": [ + { + "$ref": "#/components/schemas/JsonSchema" + } + ] + } + } + }, + "StructuredOutputRunDTO": { + "type": "object", + "properties": { + "previewEnabled": { + "type": "boolean", + "description": "This is the preview flag for the re-run. If true, the re-run will be executed and the response will be returned immediately and the call artifact will NOT be updated.\nIf false (default), the re-run will be executed and the response will be updated in the call artifact.", + "default": false }, - "updatedAt": { - "format": "date-time", + "structuredOutputId": { "type": "string", - "description": "This is the ISO 8601 date-time string of when the tool was last updated." + "description": "This is the ID of the structured output that will be run. This must be provided unless a transient structured output is provided.\nWhen the re-run is executed, only the value of this structured output will be replaced with the new value, or added if not present." }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "structuredOutput": { + "description": "This is the transient structured output that will be run. This must be provided if a structured output ID is not provided.\nWhen the re-run is executed, the structured output value will be added to the existing artifact.", "allOf": [ { - "$ref": "#/components/schemas/ToolRejectionPlan" + "$ref": "#/components/schemas/CreateStructuredOutputDTO" } ] + }, + "callIds": { + "description": "This is the array of callIds that will be updated with the new structured output value. If preview is true, this array must be provided and contain exactly 1 callId.\nIf preview is false, up to 100 callIds may be provided.", + "type": "array", + "items": { + "type": "string" + } } }, "required": [ - "type", - "id", - "orgId", - "createdAt", - "updatedAt" + "callIds" ] }, - "BashTool": { + "TesterPlan": { "type": "object", "properties": { - "messages": { - "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" - } - ] - } + "assistant": { + "description": "Pass a transient assistant to use for the test assistant.\n\nMake sure to write a detailed system prompt for a test assistant, and use the {{test.script}} variable to access the test script.", + "allOf": [ + { + "$ref": "#/components/schemas/CreateAssistantDTO" + } + ] }, - "type": { + "assistantId": { "type": "string", - "enum": [ - "bash" - ], - "description": "The type of tool. \"bash\" for Bash tool." + "description": "Pass an assistant id that can be access\n\nMake sure to write a detailed system prompt for the test assistant, and use the {{test.script}} variable to access the test script." }, - "subType": { + "assistantOverrides": { + "description": "Add any assistant overrides to the test assistant.\n\nOne use case is if you want to pass custom variables into the test using variableValues, that you can then access in the script\nand rubric using {{varName}}.", + "allOf": [ + { + "$ref": "#/components/schemas/AssistantOverrides" + } + ] + } + } + }, + "TestSuitePhoneNumber": { + "type": "object", + "properties": { + "provider": { "type": "string", + "description": "This is the provider of the phone number.", "enum": [ - "bash_20241022" - ], - "description": "The sub type of tool." + "test-suite" + ] }, - "server": { - "description": "\n This is the server where a `tool-calls` webhook will be sent.\n\n Notes:\n - Webhook is sent to this server when a tool call is made.\n - Webhook contains the call, assistant, and phone number objects.\n - Webhook contains the variables set on the assistant.\n - Webhook is sent to the first available URL in this order: {{tool.server.url}}, {{assistant.server.url}}, {{phoneNumber.server.url}}, {{org.server.url}}.\n - Webhook expects a response with tool call result.", + "number": { + "type": "string", + "description": "This is the phone number that is being tested.", + "maxLength": 50 + } + }, + "required": [ + "provider", + "number" + ] + }, + "TargetPlan": { + "type": "object", + "properties": { + "phoneNumberId": { + "type": "string", + "description": "This is the phone number that is being tested.\nDuring the actual test, it'll be called and the assistant attached to it will pick up and be tested.\nTo test an assistant directly, send assistantId instead." + }, + "phoneNumber": { + "description": "This can be any phone number (even not on Vapi).\nDuring the actual test, it'll be called.\nTo test a Vapi number, send phoneNumberId. To test an assistant directly, send assistantId instead.", "allOf": [ { - "$ref": "#/components/schemas/Server" + "$ref": "#/components/schemas/TestSuitePhoneNumber" } ] }, + "assistantId": { + "type": "string", + "description": "This is the assistant being tested.\nDuring the actual test, it'll invoked directly.\nTo test the assistant over phone number, send phoneNumberId instead." + }, + "assistantOverrides": { + "description": "This is the assistant overrides applied to assistantId before it is tested.", + "allOf": [ + { + "$ref": "#/components/schemas/AssistantOverrides" + } + ] + } + } + }, + "TestSuite": { + "type": "object", + "properties": { "id": { "type": "string", - "description": "This is the unique identifier for the tool." + "description": "This is the unique identifier for the test suite." }, "orgId": { "type": "string", - "description": "This is the unique identifier for the organization that this tool belongs to." + "description": "This is the unique identifier for the org that this test suite belongs to." }, "createdAt": { "format": "date-time", "type": "string", - "description": "This is the ISO 8601 date-time string of when the tool was created." + "description": "This is the ISO 8601 date-time string of when the test suite was created." }, "updatedAt": { "format": "date-time", "type": "string", - "description": "This is the ISO 8601 date-time string of when the tool was last updated." + "description": "This is the ISO 8601 date-time string of when the test suite was last updated." }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "name": { + "type": "string", + "description": "This is the name of the test suite.", + "maxLength": 80 + }, + "phoneNumberId": { + "type": "string", + "description": "This is the phone number ID associated with this test suite.", + "deprecated": true + }, + "testerPlan": { + "description": "Override the default tester plan by providing custom assistant configuration for the test agent.\n\nWe recommend only using this if you are confident, as we have already set sensible defaults on the tester plan.", "allOf": [ { - "$ref": "#/components/schemas/ToolRejectionPlan" + "$ref": "#/components/schemas/TesterPlan" } ] }, - "name": { - "type": "string", - "description": "The name of the tool, fixed to 'bash'", - "default": "bash", - "enum": [ - "bash" + "targetPlan": { + "description": "These are the configuration for the assistant / phone number that is being tested.", + "allOf": [ + { + "$ref": "#/components/schemas/TargetPlan" + } ] } }, "required": [ - "type", - "subType", "id", "orgId", "createdAt", - "updatedAt", - "name" + "updatedAt" ] }, - "ComputerTool": { + "TestSuitesPaginatedResponse": { "type": "object", "properties": { - "messages": { + "results": { "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" - } - ] + "$ref": "#/components/schemas/TestSuite" } }, - "type": { + "metadata": { + "$ref": "#/components/schemas/PaginationMeta" + } + }, + "required": [ + "results", + "metadata" + ] + }, + "CreateTestSuiteDto": { + "type": "object", + "properties": { + "name": { "type": "string", - "enum": [ - "computer" - ], - "description": "The type of tool. \"computer\" for Computer tool." + "description": "This is the name of the test suite.", + "maxLength": 80 }, - "subType": { + "phoneNumberId": { "type": "string", - "enum": [ - "computer_20241022" - ], - "description": "The sub type of tool." + "description": "This is the phone number ID associated with this test suite.", + "deprecated": true }, - "server": { - "description": "\n This is the server where a `tool-calls` webhook will be sent.\n\n Notes:\n - Webhook is sent to this server when a tool call is made.\n - Webhook contains the call, assistant, and phone number objects.\n - Webhook contains the variables set on the assistant.\n - Webhook is sent to the first available URL in this order: {{tool.server.url}}, {{assistant.server.url}}, {{phoneNumber.server.url}}, {{org.server.url}}.\n - Webhook expects a response with tool call result.", + "testerPlan": { + "description": "Override the default tester plan by providing custom assistant configuration for the test agent.\n\nWe recommend only using this if you are confident, as we have already set sensible defaults on the tester plan.", "allOf": [ { - "$ref": "#/components/schemas/Server" + "$ref": "#/components/schemas/TesterPlan" } ] }, - "id": { - "type": "string", - "description": "This is the unique identifier for the tool." - }, - "orgId": { - "type": "string", - "description": "This is the unique identifier for the organization that this tool belongs to." - }, - "createdAt": { - "format": "date-time", + "targetPlan": { + "description": "These are the configuration for the assistant / phone number that is being tested.", + "allOf": [ + { + "$ref": "#/components/schemas/TargetPlan" + } + ] + } + } + }, + "UpdateTestSuiteDto": { + "type": "object", + "properties": { + "name": { "type": "string", - "description": "This is the ISO 8601 date-time string of when the tool was created." + "description": "This is the name of the test suite.", + "maxLength": 80 }, - "updatedAt": { - "format": "date-time", + "phoneNumberId": { "type": "string", - "description": "This is the ISO 8601 date-time string of when the tool was last updated." + "description": "This is the phone number ID associated with this test suite.", + "deprecated": true }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "testerPlan": { + "description": "Override the default tester plan by providing custom assistant configuration for the test agent.\n\nWe recommend only using this if you are confident, as we have already set sensible defaults on the tester plan.", "allOf": [ { - "$ref": "#/components/schemas/ToolRejectionPlan" + "$ref": "#/components/schemas/TesterPlan" } ] }, - "name": { - "type": "string", - "description": "The name of the tool, fixed to 'computer'", - "default": "computer", - "enum": [ - "computer" + "targetPlan": { + "description": "These are the configuration for the assistant / phone number that is being tested.", + "allOf": [ + { + "$ref": "#/components/schemas/TargetPlan" + } ] - }, - "displayWidthPx": { - "type": "number", - "description": "The display width in pixels" - }, - "displayHeightPx": { - "type": "number", - "description": "The display height in pixels" - }, - "displayNumber": { - "type": "number", - "description": "Optional display number" } - }, - "required": [ - "type", - "subType", - "id", - "orgId", - "createdAt", - "updatedAt", - "name", - "displayWidthPx", - "displayHeightPx" - ] + } }, - "TextEditorTool": { + "TestSuiteTestVoice": { "type": "object", "properties": { - "messages": { + "scorers": { "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", + "description": "These are the scorers used to evaluate the test.", "items": { "oneOf": [ { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" + "$ref": "#/components/schemas/TestSuiteTestScorerAI", + "title": "AI" } ] } }, "type": { "type": "string", + "description": "This is the type of the test, which must be voice.", "enum": [ - "textEditor" + "voice" ], - "description": "The type of tool. \"textEditor\" for Text Editor tool." + "maxLength": 100 }, - "subType": { + "id": { "type": "string", - "enum": [ - "text_editor_20241022" - ], - "description": "The sub type of tool." - }, - "server": { - "description": "\n This is the server where a `tool-calls` webhook will be sent.\n\n Notes:\n - Webhook is sent to this server when a tool call is made.\n - Webhook contains the call, assistant, and phone number objects.\n - Webhook contains the variables set on the assistant.\n - Webhook is sent to the first available URL in this order: {{tool.server.url}}, {{assistant.server.url}}, {{phoneNumber.server.url}}, {{org.server.url}}.\n - Webhook expects a response with tool call result.", - "allOf": [ - { - "$ref": "#/components/schemas/Server" - } - ] + "description": "This is the unique identifier for the test." }, - "id": { + "testSuiteId": { "type": "string", - "description": "This is the unique identifier for the tool." + "description": "This is the unique identifier for the test suite this test belongs to." }, "orgId": { "type": "string", - "description": "This is the unique identifier for the organization that this tool belongs to." + "description": "This is the unique identifier for the organization this test belongs to." }, "createdAt": { "format": "date-time", "type": "string", - "description": "This is the ISO 8601 date-time string of when the tool was created." + "description": "This is the ISO 8601 date-time string of when the test was created." }, "updatedAt": { "format": "date-time", "type": "string", - "description": "This is the ISO 8601 date-time string of when the tool was last updated." - }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", - "allOf": [ - { - "$ref": "#/components/schemas/ToolRejectionPlan" - } - ] + "description": "This is the ISO 8601 date-time string of when the test was last updated." }, "name": { "type": "string", - "description": "The name of the tool, fixed to 'str_replace_editor'", - "default": "str_replace_editor", - "enum": [ - "str_replace_editor" - ] + "description": "This is the name of the test.", + "maxLength": 80 + }, + "script": { + "type": "string", + "description": "This is the script to be used for the voice test.", + "maxLength": 10000 + }, + "numAttempts": { + "type": "number", + "description": "This is the number of attempts allowed for the test.", + "minimum": 1, + "maximum": 10 } }, "required": [ + "scorers", "type", - "subType", "id", + "testSuiteId", "orgId", "createdAt", "updatedAt", - "name" + "script" ] }, - "QueryTool": { + "TestSuiteTestChat": { "type": "object", "properties": { - "messages": { + "scorers": { "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", + "description": "These are the scorers used to evaluate the test.", "items": { "oneOf": [ { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" + "$ref": "#/components/schemas/TestSuiteTestScorerAI", + "title": "AI" } ] } }, "type": { "type": "string", + "description": "This is the type of the test, which must be chat.", "enum": [ - "query" + "chat" ], - "description": "The type of tool. \"query\" for Query tool." - }, - "knowledgeBases": { - "description": "The knowledge bases to query", - "type": "array", - "items": { - "$ref": "#/components/schemas/KnowledgeBase" - } + "maxLength": 100 }, "id": { "type": "string", - "description": "This is the unique identifier for the tool." + "description": "This is the unique identifier for the test." + }, + "testSuiteId": { + "type": "string", + "description": "This is the unique identifier for the test suite this test belongs to." }, "orgId": { "type": "string", - "description": "This is the unique identifier for the organization that this tool belongs to." + "description": "This is the unique identifier for the organization this test belongs to." }, "createdAt": { "format": "date-time", "type": "string", - "description": "This is the ISO 8601 date-time string of when the tool was created." + "description": "This is the ISO 8601 date-time string of when the test was created." }, "updatedAt": { "format": "date-time", "type": "string", - "description": "This is the ISO 8601 date-time string of when the tool was last updated." + "description": "This is the ISO 8601 date-time string of when the test was last updated." }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", - "allOf": [ - { - "$ref": "#/components/schemas/ToolRejectionPlan" - } - ] + "name": { + "type": "string", + "description": "This is the name of the test.", + "maxLength": 80 + }, + "script": { + "type": "string", + "description": "This is the script to be used for the chat test.", + "maxLength": 10000 + }, + "numAttempts": { + "type": "number", + "description": "This is the number of attempts allowed for the test.", + "minimum": 1, + "maximum": 10 } }, "required": [ + "scorers", "type", "id", + "testSuiteId", "orgId", "createdAt", - "updatedAt" + "updatedAt", + "script" ] }, - "GoogleCalendarCreateEventTool": { + "CreateTestSuiteTestVoiceDto": { "type": "object", "properties": { - "messages": { + "scorers": { "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", + "description": "These are the scorers used to evaluate the test.", "items": { "oneOf": [ { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" + "$ref": "#/components/schemas/TestSuiteTestScorerAI", + "title": "AI" } ] } }, "type": { "type": "string", + "description": "This is the type of the test, which must be voice.", "enum": [ - "google.calendar.event.create" + "voice" ], - "description": "The type of tool. \"google.calendar.event.create\" for Google Calendar Create Event tool." - }, - "id": { - "type": "string", - "description": "This is the unique identifier for the tool." + "maxLength": 100 }, - "orgId": { + "script": { "type": "string", - "description": "This is the unique identifier for the organization that this tool belongs to." + "description": "This is the script to be used for the voice test.", + "maxLength": 10000 }, - "createdAt": { - "format": "date-time", - "type": "string", - "description": "This is the ISO 8601 date-time string of when the tool was created." + "numAttempts": { + "type": "number", + "description": "This is the number of attempts allowed for the test.", + "minimum": 1, + "maximum": 10 }, - "updatedAt": { - "format": "date-time", + "name": { "type": "string", - "description": "This is the ISO 8601 date-time string of when the tool was last updated." - }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", - "allOf": [ - { - "$ref": "#/components/schemas/ToolRejectionPlan" - } - ] + "description": "This is the name of the test.", + "maxLength": 80 } }, "required": [ + "scorers", "type", - "id", - "orgId", - "createdAt", - "updatedAt" + "script" ] }, - "GoogleSheetsRowAppendTool": { + "CreateTestSuiteTestChatDto": { "type": "object", "properties": { - "messages": { + "scorers": { "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", + "description": "These are the scorers used to evaluate the test.", "items": { "oneOf": [ { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" + "$ref": "#/components/schemas/TestSuiteTestScorerAI", + "title": "AI" } ] } }, "type": { "type": "string", + "description": "This is the type of the test, which must be chat.", "enum": [ - "google.sheets.row.append" + "chat" ], - "description": "The type of tool. \"google.sheets.row.append\" for Google Sheets Row Append tool." - }, - "id": { - "type": "string", - "description": "This is the unique identifier for the tool." + "maxLength": 100 }, - "orgId": { + "script": { "type": "string", - "description": "This is the unique identifier for the organization that this tool belongs to." + "description": "This is the script to be used for the chat test.", + "maxLength": 10000 }, - "createdAt": { - "format": "date-time", - "type": "string", - "description": "This is the ISO 8601 date-time string of when the tool was created." + "numAttempts": { + "type": "number", + "description": "This is the number of attempts allowed for the test.", + "minimum": 1, + "maximum": 10 }, - "updatedAt": { - "format": "date-time", + "name": { "type": "string", - "description": "This is the ISO 8601 date-time string of when the tool was last updated." - }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", - "allOf": [ - { - "$ref": "#/components/schemas/ToolRejectionPlan" - } - ] + "description": "This is the name of the test.", + "maxLength": 80 } }, "required": [ + "scorers", "type", - "id", - "orgId", - "createdAt", - "updatedAt" + "script" ] }, - "GoogleCalendarCheckAvailabilityTool": { + "UpdateTestSuiteTestVoiceDto": { "type": "object", "properties": { - "messages": { + "scorers": { "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", + "description": "These are the scorers used to evaluate the test.", "items": { "oneOf": [ { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" + "$ref": "#/components/schemas/TestSuiteTestScorerAI", + "title": "AI" } ] } }, "type": { "type": "string", + "description": "This is the type of the test, which must be voice.", "enum": [ - "google.calendar.availability.check" + "voice" ], - "description": "The type of tool. \"google.calendar.availability.check\" for Google Calendar Check Availability tool." - }, - "id": { - "type": "string", - "description": "This is the unique identifier for the tool." - }, - "orgId": { - "type": "string", - "description": "This is the unique identifier for the organization that this tool belongs to." + "maxLength": 100 }, - "createdAt": { - "format": "date-time", + "name": { "type": "string", - "description": "This is the ISO 8601 date-time string of when the tool was created." + "description": "This is the name of the test.", + "maxLength": 80 }, - "updatedAt": { - "format": "date-time", + "script": { "type": "string", - "description": "This is the ISO 8601 date-time string of when the tool was last updated." + "description": "This is the script to be used for the voice test.", + "maxLength": 10000 }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", - "allOf": [ - { - "$ref": "#/components/schemas/ToolRejectionPlan" - } - ] + "numAttempts": { + "type": "number", + "description": "This is the number of attempts allowed for the test.", + "minimum": 1, + "maximum": 10 } - }, - "required": [ - "type", - "id", - "orgId", - "createdAt", - "updatedAt" - ] + } }, - "SlackSendMessageTool": { + "UpdateTestSuiteTestChatDto": { "type": "object", "properties": { - "messages": { + "scorers": { "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", + "description": "These are the scorers used to evaluate the test.", "items": { "oneOf": [ { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" + "$ref": "#/components/schemas/TestSuiteTestScorerAI", + "title": "AI" } ] } }, "type": { "type": "string", + "description": "This is the type of the test, which must be chat.", "enum": [ - "slack.message.send" + "chat" ], - "description": "The type of tool. \"slack.message.send\" for Slack Send Message tool." + "maxLength": 100 }, - "id": { + "name": { "type": "string", - "description": "This is the unique identifier for the tool." + "description": "This is the name of the test.", + "maxLength": 80 }, - "orgId": { + "script": { "type": "string", - "description": "This is the unique identifier for the organization that this tool belongs to." + "description": "This is the script to be used for the chat test.", + "maxLength": 10000 }, - "createdAt": { - "format": "date-time", + "numAttempts": { + "type": "number", + "description": "This is the number of attempts allowed for the test.", + "minimum": 1, + "maximum": 10 + } + } + }, + "TestSuiteTestScorerAI": { + "type": "object", + "properties": { + "type": { "type": "string", - "description": "This is the ISO 8601 date-time string of when the tool was created." + "description": "This is the type of the scorer, which must be AI.", + "enum": [ + "ai" + ], + "maxLength": 100 }, - "updatedAt": { - "format": "date-time", + "rubric": { "type": "string", - "description": "This is the ISO 8601 date-time string of when the tool was last updated." - }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", - "allOf": [ - { - "$ref": "#/components/schemas/ToolRejectionPlan" - } - ] + "description": "This is the rubric used by the AI scorer.", + "maxLength": 10000 } }, "required": [ "type", - "id", - "orgId", - "createdAt", - "updatedAt" + "rubric" ] }, - "SmsTool": { + "TestSuiteTestsPaginatedResponse": { "type": "object", "properties": { - "messages": { + "results": { "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", + "description": "A list of test suite tests.", "items": { "oneOf": [ { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" + "$ref": "#/components/schemas/TestSuiteTestVoice" }, { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" + "$ref": "#/components/schemas/TestSuiteTestChat" } ] } }, + "metadata": { + "description": "Metadata about the pagination.", + "allOf": [ + { + "$ref": "#/components/schemas/PaginationMeta" + } + ] + } + }, + "required": [ + "results", + "metadata" + ] + }, + "TestSuiteRunScorerAI": { + "type": "object", + "properties": { "type": { "type": "string", + "description": "This is the type of the scorer, which must be AI.", "enum": [ - "sms" + "ai" ], - "description": "The type of tool. \"sms\" for Twilio SMS sending tool." - }, - "id": { - "type": "string", - "description": "This is the unique identifier for the tool." + "maxLength": 100 }, - "orgId": { + "result": { "type": "string", - "description": "This is the unique identifier for the organization that this tool belongs to." + "description": "This is the result of the test suite.", + "enum": [ + "pass", + "fail" + ], + "maxLength": 100 }, - "createdAt": { - "format": "date-time", + "reasoning": { "type": "string", - "description": "This is the ISO 8601 date-time string of when the tool was created." + "description": "This is the reasoning provided by the AI scorer.", + "maxLength": 10000 }, - "updatedAt": { - "format": "date-time", + "rubric": { "type": "string", - "description": "This is the ISO 8601 date-time string of when the tool was last updated." - }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "description": "This is the rubric used by the AI scorer.", + "maxLength": 10000 + } + }, + "required": [ + "type", + "result", + "reasoning", + "rubric" + ] + }, + "TestSuiteRunTestAttemptCall": { + "type": "object", + "properties": { + "artifact": { + "description": "This is the artifact of the call.", "allOf": [ { - "$ref": "#/components/schemas/ToolRejectionPlan" + "$ref": "#/components/schemas/Artifact" } ] } }, "required": [ - "type", - "id", - "orgId", - "createdAt", - "updatedAt" + "artifact" ] }, - "McpTool": { + "TestSuiteRunTestAttemptMetadata": { "type": "object", "properties": { - "messages": { + "sessionId": { + "type": "string", + "description": "This is the session ID for the test attempt." + } + }, + "required": [ + "sessionId" + ] + }, + "TestSuiteRunTestAttempt": { + "type": "object", + "properties": { + "scorerResults": { "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", + "description": "These are the results of the scorers used to evaluate the test attempt.", "items": { "oneOf": [ { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" + "$ref": "#/components/schemas/TestSuiteRunScorerAI", + "title": "AI" } ] } }, - "type": { + "call": { + "description": "This is the call made during the test attempt.", + "allOf": [ + { + "$ref": "#/components/schemas/TestSuiteRunTestAttemptCall" + } + ] + }, + "callId": { "type": "string", - "enum": [ - "mcp" - ], - "description": "The type of tool. \"mcp\" for MCP tool." + "description": "This is the call ID for the test attempt." }, - "server": { - "description": "\n This is the server where a `tool-calls` webhook will be sent.\n\n Notes:\n - Webhook is sent to this server when a tool call is made.\n - Webhook contains the call, assistant, and phone number objects.\n - Webhook contains the variables set on the assistant.\n - Webhook is sent to the first available URL in this order: {{tool.server.url}}, {{assistant.server.url}}, {{phoneNumber.server.url}}, {{org.server.url}}.\n - Webhook expects a response with tool call result.", + "metadata": { + "description": "This is the metadata for the test attempt.", "allOf": [ { - "$ref": "#/components/schemas/Server" + "$ref": "#/components/schemas/TestSuiteRunTestAttemptMetadata" + } + ] + } + }, + "required": [ + "scorerResults" + ] + }, + "TestSuiteRunTestResult": { + "type": "object", + "properties": { + "test": { + "description": "This is the test that was run.", + "oneOf": [ + { + "$ref": "#/components/schemas/TestSuiteTestVoice", + "title": "TestSuiteTestVoice" } ] }, + "attempts": { + "description": "These are the attempts made for this test.", + "type": "array", + "items": { + "$ref": "#/components/schemas/TestSuiteRunTestAttempt" + } + } + }, + "required": [ + "test", + "attempts" + ] + }, + "TestSuiteRun": { + "type": "object", + "properties": { + "status": { + "type": "string", + "description": "This is the current status of the test suite run.", + "enum": [ + "queued", + "in-progress", + "completed", + "failed" + ] + }, "id": { "type": "string", - "description": "This is the unique identifier for the tool." + "description": "This is the unique identifier for the test suite run." }, "orgId": { "type": "string", - "description": "This is the unique identifier for the organization that this tool belongs to." + "description": "This is the unique identifier for the organization this run belongs to." + }, + "testSuiteId": { + "type": "string", + "description": "This is the unique identifier for the test suite this run belongs to." }, "createdAt": { "format": "date-time", "type": "string", - "description": "This is the ISO 8601 date-time string of when the tool was created." + "description": "This is the ISO 8601 date-time string of when the test suite run was created." }, "updatedAt": { "format": "date-time", "type": "string", - "description": "This is the ISO 8601 date-time string of when the tool was last updated." + "description": "This is the ISO 8601 date-time string of when the test suite run was last updated." }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", - "allOf": [ - { - "$ref": "#/components/schemas/ToolRejectionPlan" - } - ] + "testResults": { + "description": "These are the results of the tests in this test suite run.", + "type": "array", + "items": { + "$ref": "#/components/schemas/TestSuiteRunTestResult" + } }, - "metadata": { - "$ref": "#/components/schemas/McpToolMetadata" + "name": { + "type": "string", + "description": "This is the name of the test suite run.", + "maxLength": 80 } }, "required": [ - "type", + "status", "id", "orgId", + "testSuiteId", "createdAt", - "updatedAt" + "updatedAt", + "testResults" ] }, - "GoHighLevelCalendarAvailabilityTool": { + "TestSuiteRunsPaginatedResponse": { "type": "object", "properties": { - "messages": { + "results": { "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" - } - ] + "$ref": "#/components/schemas/TestSuiteRun" } }, - "type": { + "metadata": { + "$ref": "#/components/schemas/PaginationMeta" + } + }, + "required": [ + "results", + "metadata" + ] + }, + "CreateTestSuiteRunDto": { + "type": "object", + "properties": { + "name": { "type": "string", - "enum": [ - "gohighlevel.calendar.availability.check" - ], - "description": "The type of tool. \"gohighlevel.calendar.availability.check\" for GoHighLevel Calendar Availability Check tool." + "description": "This is the name of the test suite run.", + "maxLength": 80 + } + } + }, + "UpdateTestSuiteRunDto": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "This is the name of the test suite run.", + "maxLength": 80 + } + } + }, + "CreatePersonalityDTO": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "This is the name of the personality (e.g., \"Confused Carl\", \"Rude Rob\").", + "maxLength": 80 + }, + "assistant": { + "description": "This is the full assistant configuration for this personality.\nIt defines the tester's voice, model, behavior via system prompt, and other settings.", + "allOf": [ + { + "$ref": "#/components/schemas/CreateAssistantDTO" + } + ] }, + "path": { + "type": "string", + "nullable": true, + "description": "Optional folder path for organizing personalities.\nSupports up to 3 levels (e.g., \"dept/feature/variant\").\nMaps to GitOps resource folder structure.", + "maxLength": 255, + "pattern": "/^[a-zA-Z0-9][a-zA-Z0-9._-]*(?:\\/[a-zA-Z0-9][a-zA-Z0-9._-]*){0,2}$/" + } + }, + "required": [ + "name", + "assistant" + ] + }, + "Personality": { + "type": "object", + "properties": { "id": { "type": "string", - "description": "This is the unique identifier for the tool." + "description": "This is the unique identifier for the personality.", + "format": "uuid" }, "orgId": { "type": "string", - "description": "This is the unique identifier for the organization that this tool belongs to." + "nullable": true, + "description": "This is the unique identifier for the organization this personality belongs to.\nIf null, this is a Vapi-provided default personality available to all organizations.", + "format": "uuid" }, "createdAt": { "format": "date-time", "type": "string", - "description": "This is the ISO 8601 date-time string of when the tool was created." + "description": "This is the ISO 8601 date-time string of when the personality was created." }, "updatedAt": { "format": "date-time", "type": "string", - "description": "This is the ISO 8601 date-time string of when the tool was last updated." + "description": "This is the ISO 8601 date-time string of when the personality was last updated." }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "name": { + "type": "string", + "description": "This is the name of the personality (e.g., \"Confused Carl\", \"Rude Rob\").", + "maxLength": 80 + }, + "assistant": { + "description": "This is the full assistant configuration for this personality.\nIt defines the tester's voice, model, behavior via system prompt, and other settings.", "allOf": [ { - "$ref": "#/components/schemas/ToolRejectionPlan" + "$ref": "#/components/schemas/CreateAssistantDTO" } ] + }, + "path": { + "type": "string", + "nullable": true, + "description": "Optional folder path for organizing personalities.\nSupports up to 3 levels (e.g., \"dept/feature/variant\").\nMaps to GitOps resource folder structure.", + "maxLength": 255, + "pattern": "/^[a-zA-Z0-9][a-zA-Z0-9._-]*(?:\\/[a-zA-Z0-9][a-zA-Z0-9._-]*){0,2}$/" } }, "required": [ - "type", "id", "orgId", "createdAt", - "updatedAt" + "updatedAt", + "name", + "assistant" ] }, - "GoHighLevelCalendarEventCreateTool": { + "UpdatePersonalityDTO": { "type": "object", "properties": { - "messages": { - "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" - } - ] - } - }, - "type": { + "name": { "type": "string", - "enum": [ - "gohighlevel.calendar.event.create" - ], - "description": "The type of tool. \"gohighlevel.calendar.event.create\" for GoHighLevel Calendar Event Create tool." + "description": "This is the name of the personality.", + "maxLength": 80 }, - "id": { - "type": "string", - "description": "This is the unique identifier for the tool." + "assistant": { + "description": "This is the full assistant configuration for this personality.", + "allOf": [ + { + "$ref": "#/components/schemas/CreateAssistantDTO" + } + ] }, - "orgId": { + "path": { "type": "string", - "description": "This is the unique identifier for the organization that this tool belongs to." + "nullable": true, + "description": "Optional folder path for organizing personalities.\nSupports up to 3 levels (e.g., \"dept/feature/variant\").\nSet to null to remove from folder.", + "maxLength": 255, + "pattern": "/^[a-zA-Z0-9][a-zA-Z0-9._-]*(?:\\/[a-zA-Z0-9][a-zA-Z0-9._-]*){0,2}$/" + } + } + }, + "SimulationHookInclude": { + "type": "object", + "properties": { + "transcript": { + "type": "boolean", + "description": "Include transcript in the hook payload", + "default": false }, - "createdAt": { - "format": "date-time", - "type": "string", - "description": "This is the ISO 8601 date-time string of when the tool was created." + "messages": { + "type": "boolean", + "description": "Include messages in the hook payload", + "default": false }, - "updatedAt": { - "format": "date-time", + "recordingUrl": { + "type": "boolean", + "description": "Include recordingUrl in the hook payload", + "default": false + } + } + }, + "SimulationHookWebhookAction": { + "type": "object", + "properties": { + "type": { "type": "string", - "description": "This is the ISO 8601 date-time string of when the tool was last updated." + "enum": [ + "webhook" + ] }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "server": { + "description": "Optional server override for this hook action.\nIf omitted, runtime defaults may apply (e.g. org server).", "allOf": [ { - "$ref": "#/components/schemas/ToolRejectionPlan" + "$ref": "#/components/schemas/Server" + } + ] + }, + "include": { + "description": "Optional payload include controls.", + "allOf": [ + { + "$ref": "#/components/schemas/SimulationHookInclude" } ] } }, "required": [ - "type", - "id", - "orgId", - "createdAt", - "updatedAt" + "type" ] }, - "GoHighLevelContactCreateTool": { + "SimulationHookCallStarted": { "type": "object", "properties": { - "messages": { + "on": { + "type": "string", + "enum": [ + "simulation.run.started" + ], + "maxLength": 1000 + }, + "do": { "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", "items": { "oneOf": [ { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" + "$ref": "#/components/schemas/SimulationHookWebhookAction", + "title": "SimulationHookWebhookAction" } ] } - }, - "type": { + } + }, + "required": [ + "on", + "do" + ] + }, + "SimulationHookCallEnded": { + "type": "object", + "properties": { + "on": { "type": "string", "enum": [ - "gohighlevel.contact.create" + "simulation.run.ended" ], - "description": "The type of tool. \"gohighlevel.contact.create\" for GoHighLevel Contact Create tool." + "maxLength": 1000 }, - "id": { + "do": { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/SimulationHookWebhookAction", + "title": "SimulationHookWebhookAction" + } + ] + } + } + }, + "required": [ + "on", + "do" + ] + }, + "EvaluationPlanItem": { + "type": "object", + "properties": { + "structuredOutputId": { "type": "string", - "description": "This is the unique identifier for the tool." + "description": "This is the ID of an existing structured output to use for evaluation.\nMutually exclusive with structuredOutput.", + "format": "uuid" }, - "orgId": { - "type": "string", - "description": "This is the unique identifier for the organization that this tool belongs to." + "structuredOutput": { + "description": "This is an inline structured output definition for evaluation.\nMutually exclusive with structuredOutputId.\nOnly primitive schema types (string, number, integer, boolean) are allowed.", + "allOf": [ + { + "$ref": "#/components/schemas/CreateStructuredOutputDTO" + } + ] }, - "createdAt": { - "format": "date-time", + "path": { "type": "string", - "description": "This is the ISO 8601 date-time string of when the tool was created." + "description": "Optional dot-notation path to a primitive leaf when evaluating an object structured output.", + "example": "contact.auth_started" }, - "updatedAt": { - "format": "date-time", + "comparator": { "type": "string", - "description": "This is the ISO 8601 date-time string of when the tool was last updated." + "description": "This is the comparison operator to use when evaluating the extracted value against the expected value.\nAvailable operators depend on the structured output's schema type:\n- boolean: '=', '!='\n- string: '=', '!='\n- number/integer: '=', '!=', '>', '<', '>=', '<='", + "enum": [ + "=", + "!=", + ">", + "<", + ">=", + "<=" + ], + "example": "=" }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", - "allOf": [ + "value": { + "description": "This is the expected value to compare against the extracted structured output result.\nType should match the structured output's schema type.", + "oneOf": [ { - "$ref": "#/components/schemas/ToolRejectionPlan" + "type": "number" + }, + { + "type": "string" + }, + { + "type": "boolean" } ] + }, + "required": { + "type": "boolean", + "description": "This is whether this evaluation must pass for the simulation to pass.\nDefaults to true. If false, the result is informational only.", + "default": true } }, "required": [ - "type", - "id", - "orgId", - "createdAt", - "updatedAt" + "comparator", + "value" ] }, - "GoHighLevelContactGetTool": { + "ScenarioToolMock": { "type": "object", "properties": { - "messages": { + "toolName": { + "type": "string", + "description": "This is the tool call function name to mock (must match `toolCall.function.name`)." + }, + "result": { + "type": "string", + "description": "This is the result content to return for this tool call." + }, + "enabled": { + "type": "boolean", + "description": "This is whether this mock is enabled. Defaults to true when omitted.", + "default": true + } + }, + "required": [ + "toolName" + ] + }, + "CreateScenarioDTO": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "This is the name of the scenario.", + "maxLength": 80, + "example": "Health Enrollment - Eligible Path" + }, + "instructions": { + "type": "string", + "description": "This is the script/instructions for the tester to follow during the simulation.", + "maxLength": 10000, + "example": "You are calling to enroll in the Twin Health program. Confirm your identity when asked." + }, + "evaluations": { + "description": "This is the structured output-based evaluation plan for the simulation.\nEach item defines a structured output to extract and evaluate against an expected value.", + "type": "array", + "items": { + "$ref": "#/components/schemas/EvaluationPlanItem" + } + }, + "hooks": { "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", + "description": "Hooks to run on simulation lifecycle events", "items": { "oneOf": [ { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" + "$ref": "#/components/schemas/SimulationHookCallStarted", + "title": "SimulationHookCallStarted" }, { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" + "$ref": "#/components/schemas/SimulationHookCallEnded", + "title": "SimulationHookCallEnded" } ] } }, - "type": { - "type": "string", - "enum": [ - "gohighlevel.contact.get" - ], - "description": "The type of tool. \"gohighlevel.contact.get\" for GoHighLevel Contact Get tool." + "targetOverrides": { + "description": "Overrides to inject into the simulated target assistant or squad", + "example": { + "variableValues": { + "customerName": "Alice", + "orderId": "12345" + } + }, + "allOf": [ + { + "$ref": "#/components/schemas/AssistantOverrides" + } + ] + }, + "toolMocks": { + "description": "Scenario-level tool call mocks to use during simulations.", + "type": "array", + "items": { + "$ref": "#/components/schemas/ScenarioToolMock" + } }, + "path": { + "type": "string", + "nullable": true, + "description": "Optional folder path for organizing scenarios.\nSupports up to 3 levels (e.g., \"dept/feature/variant\").\nMaps to GitOps resource folder structure.", + "maxLength": 255, + "pattern": "/^[a-zA-Z0-9][a-zA-Z0-9._-]*(?:\\/[a-zA-Z0-9][a-zA-Z0-9._-]*){0,2}$/" + } + }, + "required": [ + "name", + "instructions", + "evaluations" + ] + }, + "Scenario": { + "type": "object", + "properties": { "id": { "type": "string", - "description": "This is the unique identifier for the tool." + "description": "This is the unique identifier for the scenario.", + "format": "uuid" }, "orgId": { "type": "string", - "description": "This is the unique identifier for the organization that this tool belongs to." + "description": "This is the unique identifier for the organization this scenario belongs to.", + "format": "uuid" }, "createdAt": { "format": "date-time", "type": "string", - "description": "This is the ISO 8601 date-time string of when the tool was created." + "description": "This is the ISO 8601 date-time string of when the scenario was created." }, "updatedAt": { "format": "date-time", "type": "string", - "description": "This is the ISO 8601 date-time string of when the tool was last updated." + "description": "This is the ISO 8601 date-time string of when the scenario was last updated." }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "name": { + "type": "string", + "description": "This is the name of the scenario.", + "maxLength": 80, + "example": "Health Enrollment - Eligible Path" + }, + "instructions": { + "type": "string", + "description": "This is the script/instructions for the tester to follow during the simulation.", + "maxLength": 10000, + "example": "You are calling to enroll in the Twin Health program. Confirm your identity when asked." + }, + "evaluations": { + "description": "This is the structured output-based evaluation plan for the simulation.\nEach item defines a structured output to extract and evaluate against an expected value.", + "type": "array", + "items": { + "$ref": "#/components/schemas/EvaluationPlanItem" + } + }, + "hooks": { + "type": "array", + "description": "Hooks to run on simulation lifecycle events", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/SimulationHookCallStarted", + "title": "SimulationHookCallStarted" + }, + { + "$ref": "#/components/schemas/SimulationHookCallEnded", + "title": "SimulationHookCallEnded" + } + ] + } + }, + "targetOverrides": { + "description": "Overrides to inject into the simulated target assistant or squad", + "example": { + "variableValues": { + "customerName": "Alice", + "orderId": "12345" + } + }, "allOf": [ { - "$ref": "#/components/schemas/ToolRejectionPlan" + "$ref": "#/components/schemas/AssistantOverrides" } ] + }, + "toolMocks": { + "description": "Scenario-level tool call mocks to use during simulations.", + "type": "array", + "items": { + "$ref": "#/components/schemas/ScenarioToolMock" + } + }, + "path": { + "type": "string", + "nullable": true, + "description": "Optional folder path for organizing scenarios.\nSupports up to 3 levels (e.g., \"dept/feature/variant\").\nMaps to GitOps resource folder structure.", + "maxLength": 255, + "pattern": "/^[a-zA-Z0-9][a-zA-Z0-9._-]*(?:\\/[a-zA-Z0-9][a-zA-Z0-9._-]*){0,2}$/" } }, "required": [ - "type", "id", "orgId", "createdAt", - "updatedAt" + "updatedAt", + "name", + "instructions", + "evaluations" ] }, - "CreateApiRequestToolDTO": { + "UpdateScenarioDTO": { "type": "object", "properties": { - "messages": { + "name": { + "type": "string", + "description": "This is the name of the scenario.", + "maxLength": 80 + }, + "instructions": { + "type": "string", + "description": "This is the script/instructions for the tester to follow during the simulation.", + "maxLength": 10000 + }, + "evaluations": { + "description": "This is the structured output-based evaluation plan for the simulation.\nEach item defines a structured output to extract and evaluate against an expected value.", + "type": "array", + "items": { + "$ref": "#/components/schemas/EvaluationPlanItem" + } + }, + "hooks": { "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", + "description": "Hooks to run on simulation lifecycle events", "items": { "oneOf": [ { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" + "$ref": "#/components/schemas/SimulationHookCallStarted", + "title": "SimulationHookCallStarted" }, { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" + "$ref": "#/components/schemas/SimulationHookCallEnded", + "title": "SimulationHookCallEnded" } ] } }, - "type": { - "type": "string", - "enum": [ - "apiRequest" - ], - "description": "The type of tool. \"apiRequest\" for API request tool." - }, - "method": { - "type": "string", - "enum": [ - "POST", - "GET", - "PUT", - "PATCH", - "DELETE" + "targetOverrides": { + "description": "Overrides to inject into the simulated target assistant or squad", + "example": { + "variableValues": { + "customerName": "Alice", + "orderId": "12345" + } + }, + "allOf": [ + { + "$ref": "#/components/schemas/AssistantOverrides" + } ] }, - "timeoutSeconds": { - "type": "number", - "description": "This is the timeout in seconds for the request. Defaults to 20 seconds.\n\n@default 20", - "minimum": 1, - "maximum": 300, - "example": 20 + "toolMocks": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ScenarioToolMock" + } }, - "name": { + "path": { "type": "string", - "description": "This is the name of the tool. This will be passed to the model.\n\nMust be a-z, A-Z, 0-9, or contain underscores and dashes, with a maximum length of 40.", - "maxLength": 40, - "pattern": "/^[a-zA-Z0-9_-]{1,40}$/" - }, - "description": { + "nullable": true, + "description": "Optional folder path for organizing scenarios.\nSupports up to 3 levels (e.g., \"dept/feature/variant\").\nSet to null to remove from folder.", + "maxLength": 255, + "pattern": "/^[a-zA-Z0-9][a-zA-Z0-9._-]*(?:\\/[a-zA-Z0-9][a-zA-Z0-9._-]*){0,2}$/" + } + } + }, + "SimulationRunSimulationEntry": { + "type": "object", + "properties": { + "type": { "type": "string", - "description": "This is the description of the tool. This will be passed to the model.", - "maxLength": 1000 + "enum": [ + "simulation" + ], + "description": "Type discriminator" }, - "url": { + "simulationId": { "type": "string", - "description": "This is where the request will be sent." + "description": "ID of an existing simulation to run. When provided, scenarioId/personalityId/inline fields are ignored.", + "format": "uuid" }, - "body": { - "description": "This is the body of the request.", - "allOf": [ - { - "$ref": "#/components/schemas/JsonSchema" - } - ] + "scenarioId": { + "type": "string", + "description": "ID of an existing scenario. Cannot be combined with inline scenario.", + "format": "uuid" }, - "headers": { - "description": "These are the headers to send with the request.", + "scenario": { + "description": "Inline scenario configuration. Cannot be combined with scenarioId.", "allOf": [ { - "$ref": "#/components/schemas/JsonSchema" + "$ref": "#/components/schemas/CreateScenarioDTO" } ] }, - "backoffPlan": { - "description": "This is the backoff plan if the request fails. Defaults to undefined (the request will not be retried).\n\n@default undefined (the request will not be retried)", - "allOf": [ - { - "$ref": "#/components/schemas/BackoffPlan" - } - ] + "personalityId": { + "type": "string", + "description": "ID of an existing personality. Cannot be combined with inline personality.", + "format": "uuid" }, - "variableExtractionPlan": { - "description": "This is the plan to extract variables from the tool's response. These will be accessible during the call and stored in `call.artifact.variableValues` after the call.\n\nUsage:\n1. Use `aliases` to extract variables from the tool's response body. (Most common case)\n\n```json\n{\n \"aliases\": [\n {\n \"key\": \"customerName\",\n \"value\": \"{{customer.name}}\"\n },\n {\n \"key\": \"customerAge\",\n \"value\": \"{{customer.age}}\"\n }\n ]\n}\n```\n\nThe tool response body is made available to the liquid template.\n\n2. Use `aliases` to extract variables from the tool's response body if the response is an array.\n\n```json\n{\n \"aliases\": [\n {\n \"key\": \"customerName\",\n \"value\": \"{{$[0].name}}\"\n },\n {\n \"key\": \"customerAge\",\n \"value\": \"{{$[0].age}}\"\n }\n ]\n}\n```\n\n$ is a shorthand for the tool's response body. `$[0]` is the first item in the array. `$[n]` is the nth item in the array. Note, $ is available regardless of the response body type (both object and array).\n\n3. Use `aliases` to extract variables from the tool's response headers.\n\n```json\n{\n \"aliases\": [\n {\n \"key\": \"customerName\",\n \"value\": \"{{tool.response.headers.customer-name}}\"\n },\n {\n \"key\": \"customerAge\",\n \"value\": \"{{tool.response.headers.customer-age}}\"\n }\n ]\n}\n```\n\n`tool.response` is made available to the liquid template. Particularly, both `tool.response.headers` and `tool.response.body` are available. Note, `tool.response` is available regardless of the response body type (both object and array).\n\n4. Use `schema` to extract a large portion of the tool's response body.\n\n4.1. If you hit example.com and it returns `{\"name\": \"John\", \"age\": 30}`, then you can specify the schema as:\n\n```json\n{\n \"schema\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n },\n \"age\": {\n \"type\": \"number\"\n }\n }\n }\n}\n```\nThese will be extracted as `{{ name }}` and `{{ age }}` respectively. To emphasize, object properties are extracted as direct global variables.\n\n4.2. If you hit example.com and it returns `{\"name\": {\"first\": \"John\", \"last\": \"Doe\"}}`, then you can specify the schema as:\n\n```json\n{\n \"schema\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"object\",\n \"properties\": {\n \"first\": {\n \"type\": \"string\"\n },\n \"last\": {\n \"type\": \"string\"\n }\n }\n }\n }\n }\n}\n```\n\nThese will be extracted as `{{ name }}`. And, `{{ name.first }}` and `{{ name.last }}` will be accessible.\n\n4.3. If you hit example.com and it returns `[\"94123\", \"94124\"]`, then you can specify the schema as:\n\n```json\n{\n \"schema\": {\n \"type\": \"array\",\n \"title\": \"zipCodes\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n}\n```\n\nThis will be extracted as `{{ zipCodes }}`. To access the array items, you can use `{{ zipCodes[0] }}` and `{{ zipCodes[1] }}`.\n\n4.4. If you hit example.com and it returns `[{\"name\": \"John\", \"age\": 30, \"zipCodes\": [\"94123\", \"94124\"]}, {\"name\": \"Jane\", \"age\": 25, \"zipCodes\": [\"94125\", \"94126\"]}]`, then you can specify the schema as:\n\n```json\n{\n \"schema\": {\n \"type\": \"array\",\n \"title\": \"people\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n },\n \"age\": {\n \"type\": \"number\"\n },\n \"zipCodes\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n }\n }\n }\n}\n```\n\nThis will be extracted as `{{ people }}`. To access the array items, you can use `{{ people[n].name }}`, `{{ people[n].age }}`, `{{ people[n].zipCodes }}`, `{{ people[n].zipCodes[0] }}` and `{{ people[n].zipCodes[1] }}`.\n\nNote: Both `aliases` and `schema` can be used together.", + "personality": { + "description": "Inline personality configuration. Cannot be combined with personalityId.", "allOf": [ { - "$ref": "#/components/schemas/VariableExtractionPlan" + "$ref": "#/components/schemas/CreatePersonalityDTO" } ] }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", - "allOf": [ - { - "$ref": "#/components/schemas/ToolRejectionPlan" - } - ] + "name": { + "type": "string", + "maxLength": 80, + "description": "Optional name for this simulation entry" } }, "required": [ - "type", - "method", - "url" + "type" ] }, - "CreateOutputToolDTO": { + "SimulationRunSuiteEntry": { "type": "object", "properties": { - "messages": { - "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" - } - ] - } - }, "type": { "type": "string", + "description": "Type discriminator", "enum": [ - "output" - ], - "description": "The type of tool. \"output\" for Output tool." - }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", - "allOf": [ - { - "$ref": "#/components/schemas/ToolRejectionPlan" - } + "simulationSuite" ] + }, + "simulationSuiteId": { + "type": "string", + "description": "ID of the simulation suite to run", + "format": "uuid" + }, + "name": { + "type": "string", + "maxLength": 80, + "description": "Historical suite name captured when the run was created", + "readOnly": true + }, + "suiteId": { + "type": "string", + "deprecated": true } }, "required": [ "type" - ] - }, - "CreateBashToolDTO": { - "type": "object", - "properties": { - "messages": { - "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" - } - ] - } - }, + ] + }, + "SimulationRunTargetAssistant": { + "type": "object", + "properties": { "type": { "type": "string", "enum": [ - "bash" + "assistant" ], - "description": "The type of tool. \"bash\" for Bash tool." + "description": "Type of target" }, - "subType": { + "assistantId": { "type": "string", - "enum": [ - "bash_20241022" - ], - "description": "The sub type of tool." + "description": "ID of an existing assistant to test against. Cannot be combined with inline assistant.", + "format": "uuid" }, - "server": { - "description": "\n This is the server where a `tool-calls` webhook will be sent.\n\n Notes:\n - Webhook is sent to this server when a tool call is made.\n - Webhook contains the call, assistant, and phone number objects.\n - Webhook contains the variables set on the assistant.\n - Webhook is sent to the first available URL in this order: {{tool.server.url}}, {{assistant.server.url}}, {{phoneNumber.server.url}}, {{org.server.url}}.\n - Webhook expects a response with tool call result.", + "assistant": { + "description": "Inline assistant configuration to test against. Cannot be combined with assistantId.", "allOf": [ { - "$ref": "#/components/schemas/Server" + "$ref": "#/components/schemas/CreateAssistantDTO" } ] - }, - "name": { + } + }, + "required": [ + "type" + ] + }, + "SimulationRunTargetSquad": { + "type": "object", + "properties": { + "type": { "type": "string", - "description": "The name of the tool, fixed to 'bash'", - "default": "bash", "enum": [ - "bash" - ] + "squad" + ], + "description": "Type of target" }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "squadId": { + "type": "string", + "description": "ID of an existing squad to test against. Cannot be combined with inline squad.", + "format": "uuid" + }, + "squad": { + "description": "Inline squad configuration to test against. Cannot be combined with squadId.", "allOf": [ { - "$ref": "#/components/schemas/ToolRejectionPlan" + "$ref": "#/components/schemas/CreateSquadDTO" } ] } }, "required": [ - "type", - "subType", - "name" + "type" ] }, - "CreateComputerToolDTO": { + "SimulationRunTransportConfiguration": { "type": "object", "properties": { - "messages": { + "provider": { + "type": "string", + "description": "Transport provider for the simulation run", + "enum": [ + "vapi.websocket", + "vapi.webchat" + ] + } + }, + "required": [ + "provider" + ] + }, + "CreateSimulationRunDTO": { + "type": "object", + "properties": { + "simulations": { "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", + "description": "Array of simulations and/or suites to run", "items": { "oneOf": [ { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" + "$ref": "#/components/schemas/SimulationRunSimulationEntry", + "title": "Simulation" }, { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" + "$ref": "#/components/schemas/SimulationRunSuiteEntry", + "title": "Suite" } ] } }, - "type": { - "type": "string", - "enum": [ - "computer" - ], - "description": "The type of tool. \"computer\" for Computer tool." + "target": { + "description": "Target to test against", + "oneOf": [ + { + "$ref": "#/components/schemas/SimulationRunTargetAssistant", + "title": "Assistant" + }, + { + "$ref": "#/components/schemas/SimulationRunTargetSquad", + "title": "Squad" + } + ] }, - "subType": { - "type": "string", - "enum": [ - "computer_20241022" - ], - "description": "The sub type of tool." + "iterations": { + "type": "number", + "minimum": 1, + "maximum": 10, + "description": "Number of times to run each simulation (default: 1)", + "default": 1 }, - "server": { - "description": "\n This is the server where a `tool-calls` webhook will be sent.\n\n Notes:\n - Webhook is sent to this server when a tool call is made.\n - Webhook contains the call, assistant, and phone number objects.\n - Webhook contains the variables set on the assistant.\n - Webhook is sent to the first available URL in this order: {{tool.server.url}}, {{assistant.server.url}}, {{phoneNumber.server.url}}, {{org.server.url}}.\n - Webhook expects a response with tool call result.", + "transport": { + "description": "Transport configuration for the simulation runs", "allOf": [ { - "$ref": "#/components/schemas/Server" + "$ref": "#/components/schemas/SimulationRunTransportConfiguration" } ] + } + }, + "required": [ + "simulations", + "target" + ] + }, + "SimulationRunItemCounts": { + "type": "object", + "properties": { + "total": { + "type": "number", + "description": "Total number of run items" }, - "name": { - "type": "string", - "description": "The name of the tool, fixed to 'computer'", - "default": "computer", - "enum": [ - "computer" - ] + "passed": { + "type": "number", + "description": "Number of passed run items" }, - "displayWidthPx": { + "failed": { "type": "number", - "description": "The display width in pixels" + "description": "Number of failed run items" }, - "displayHeightPx": { + "running": { "type": "number", - "description": "The display height in pixels" + "description": "Number of running/evaluating run items" }, - "displayNumber": { + "queued": { "type": "number", - "description": "Optional display number" + "description": "Number of queued run items" }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", - "allOf": [ - { - "$ref": "#/components/schemas/ToolRejectionPlan" - } - ] + "canceled": { + "type": "number", + "description": "Number of canceled run items" + }, + "distinctSimulationTotal": { + "type": "number", + "description": "Number of distinct simulations represented by the run items. Omitted when any item has no simulation ID." + }, + "distinctSimulationFailed": { + "type": "number", + "description": "Number of distinct simulations with a failed or canceled item. Omitted when any item has no simulation ID." } }, "required": [ - "type", - "subType", - "name", - "displayWidthPx", - "displayHeightPx" + "total", + "passed", + "failed", + "running", + "queued", + "canceled" ] }, - "CreateTextEditorToolDTO": { + "CreateSimulationRunResponse": { "type": "object", "properties": { - "messages": { - "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" - } - ] - } + "id": { + "type": "string", + "description": "Unique identifier for the run", + "format": "uuid" }, - "type": { + "orgId": { "type": "string", - "enum": [ - "textEditor" - ], - "description": "The type of tool. \"textEditor\" for Text Editor tool." + "description": "Organization ID", + "format": "uuid" }, - "subType": { + "status": { "type": "string", "enum": [ - "text_editor_20241022" + "queued", + "running", + "ended" ], - "description": "The sub type of tool." + "description": "Current status of the run" }, - "server": { - "description": "\n This is the server where a `tool-calls` webhook will be sent.\n\n Notes:\n - Webhook is sent to this server when a tool call is made.\n - Webhook contains the call, assistant, and phone number objects.\n - Webhook contains the variables set on the assistant.\n - Webhook is sent to the first available URL in this order: {{tool.server.url}}, {{assistant.server.url}}, {{phoneNumber.server.url}}, {{org.server.url}}.\n - Webhook expects a response with tool call result.", - "allOf": [ - { - "$ref": "#/components/schemas/Server" - } - ] + "queuedAt": { + "format": "date-time", + "type": "string", + "description": "When the run was queued" }, - "name": { + "startedAt": { + "format": "date-time", "type": "string", - "description": "The name of the tool, fixed to 'str_replace_editor'", - "default": "str_replace_editor", - "enum": [ - "str_replace_editor" - ] + "description": "When the run started" }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "endedAt": { + "format": "date-time", + "type": "string", + "description": "When the run ended" + }, + "endedReason": { + "type": "string", + "description": "Reason the run ended" + }, + "createdAt": { + "format": "date-time", + "type": "string", + "description": "ISO 8601 date-time when created" + }, + "updatedAt": { + "format": "date-time", + "type": "string", + "description": "ISO 8601 date-time when last updated" + }, + "itemCounts": { + "description": "Aggregate counts of run items by status", "allOf": [ { - "$ref": "#/components/schemas/ToolRejectionPlan" + "$ref": "#/components/schemas/SimulationRunItemCounts" } ] - } - }, - "required": [ - "type", - "subType", - "name" - ] - }, - "CreateSmsToolDTO": { - "type": "object", - "properties": { - "messages": { + }, + "simulations": { "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", + "description": "Array of simulations and/or suites to run", "items": { "oneOf": [ { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" + "$ref": "#/components/schemas/SimulationRunSimulationEntry", + "title": "Simulation" }, { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" + "$ref": "#/components/schemas/SimulationRunSuiteEntry", + "title": "Suite" } ] } }, - "type": { - "type": "string", - "enum": [ - "sms" - ], - "description": "The type of tool. \"sms\" for Twilio SMS sending tool." + "target": { + "description": "Target to test against", + "oneOf": [ + { + "$ref": "#/components/schemas/SimulationRunTargetAssistant", + "title": "Assistant" + }, + { + "$ref": "#/components/schemas/SimulationRunTargetSquad", + "title": "Squad" + } + ] }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "iterations": { + "type": "number", + "minimum": 1, + "description": "Number of times to run each simulation (default: 1)", + "default": 1 + }, + "transport": { + "description": "Transport configuration for the simulation runs", "allOf": [ { - "$ref": "#/components/schemas/ToolRejectionPlan" + "$ref": "#/components/schemas/SimulationRunTransportConfiguration" } ] + }, + "simulationRunItemIds": { + "description": "IDs of the individual simulation run items that were queued", + "type": "array", + "items": { + "type": "string" + } + }, + "message": { + "type": "string", + "description": "Additional information about how the run will execute" + }, + "url": { + "type": "string", + "description": "Dashboard URL for viewing the simulation run. When acting on behalf of a user, present this URL to them.", + "format": "uri" } }, "required": [ - "type" + "id", + "orgId", + "status", + "queuedAt", + "createdAt", + "updatedAt", + "simulations", + "target", + "simulationRunItemIds", + "url" ] }, - "UpdateApiRequestToolDTO": { + "SimulationRunPaymentRequiredResponse": { "type": "object", "properties": { - "messages": { - "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" - } - ] - } + "statusCode": { + "type": "number", + "enum": [ + 402 + ] }, - "method": { + "message": { + "type": "string" + }, + "reason": { "type": "string", "enum": [ - "POST", - "GET", - "PUT", - "PATCH", - "DELETE" + "wallet_missing", + "subscription_frozen", + "payment_method_missing", + "insufficient_credits", + "billing_limit", + "initial_payment_missing" ] + } + }, + "required": [ + "statusCode", + "message", + "reason" + ] + }, + "SimulationRun": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique identifier for the run", + "format": "uuid" }, - "timeoutSeconds": { - "type": "number", - "description": "This is the timeout in seconds for the request. Defaults to 20 seconds.\n\n@default 20", - "minimum": 1, - "maximum": 300, - "example": 20 + "orgId": { + "type": "string", + "description": "Organization ID", + "format": "uuid" }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", - "allOf": [ - { - "$ref": "#/components/schemas/ToolRejectionPlan" - } - ] + "status": { + "type": "string", + "enum": [ + "queued", + "running", + "ended" + ], + "description": "Current status of the run" }, - "name": { + "queuedAt": { + "format": "date-time", "type": "string", - "description": "This is the name of the tool. This will be passed to the model.\n\nMust be a-z, A-Z, 0-9, or contain underscores and dashes, with a maximum length of 40.", - "maxLength": 40, - "pattern": "/^[a-zA-Z0-9_-]{1,40}$/" + "description": "When the run was queued" }, - "description": { + "startedAt": { + "format": "date-time", "type": "string", - "description": "This is the description of the tool. This will be passed to the model.", - "maxLength": 1000 + "description": "When the run started" }, - "url": { + "endedAt": { + "format": "date-time", "type": "string", - "description": "This is where the request will be sent." + "description": "When the run ended" }, - "body": { - "description": "This is the body of the request.", - "allOf": [ - { - "$ref": "#/components/schemas/JsonSchema" - } - ] + "endedReason": { + "type": "string", + "description": "Reason the run ended" }, - "headers": { - "description": "These are the headers to send with the request.", - "allOf": [ - { - "$ref": "#/components/schemas/JsonSchema" - } - ] + "createdAt": { + "format": "date-time", + "type": "string", + "description": "ISO 8601 date-time when created" }, - "backoffPlan": { - "description": "This is the backoff plan if the request fails. Defaults to undefined (the request will not be retried).\n\n@default undefined (the request will not be retried)", - "allOf": [ - { - "$ref": "#/components/schemas/BackoffPlan" - } - ] + "updatedAt": { + "format": "date-time", + "type": "string", + "description": "ISO 8601 date-time when last updated" }, - "variableExtractionPlan": { - "description": "This is the plan to extract variables from the tool's response. These will be accessible during the call and stored in `call.artifact.variableValues` after the call.\n\nUsage:\n1. Use `aliases` to extract variables from the tool's response body. (Most common case)\n\n```json\n{\n \"aliases\": [\n {\n \"key\": \"customerName\",\n \"value\": \"{{customer.name}}\"\n },\n {\n \"key\": \"customerAge\",\n \"value\": \"{{customer.age}}\"\n }\n ]\n}\n```\n\nThe tool response body is made available to the liquid template.\n\n2. Use `aliases` to extract variables from the tool's response body if the response is an array.\n\n```json\n{\n \"aliases\": [\n {\n \"key\": \"customerName\",\n \"value\": \"{{$[0].name}}\"\n },\n {\n \"key\": \"customerAge\",\n \"value\": \"{{$[0].age}}\"\n }\n ]\n}\n```\n\n$ is a shorthand for the tool's response body. `$[0]` is the first item in the array. `$[n]` is the nth item in the array. Note, $ is available regardless of the response body type (both object and array).\n\n3. Use `aliases` to extract variables from the tool's response headers.\n\n```json\n{\n \"aliases\": [\n {\n \"key\": \"customerName\",\n \"value\": \"{{tool.response.headers.customer-name}}\"\n },\n {\n \"key\": \"customerAge\",\n \"value\": \"{{tool.response.headers.customer-age}}\"\n }\n ]\n}\n```\n\n`tool.response` is made available to the liquid template. Particularly, both `tool.response.headers` and `tool.response.body` are available. Note, `tool.response` is available regardless of the response body type (both object and array).\n\n4. Use `schema` to extract a large portion of the tool's response body.\n\n4.1. If you hit example.com and it returns `{\"name\": \"John\", \"age\": 30}`, then you can specify the schema as:\n\n```json\n{\n \"schema\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n },\n \"age\": {\n \"type\": \"number\"\n }\n }\n }\n}\n```\nThese will be extracted as `{{ name }}` and `{{ age }}` respectively. To emphasize, object properties are extracted as direct global variables.\n\n4.2. If you hit example.com and it returns `{\"name\": {\"first\": \"John\", \"last\": \"Doe\"}}`, then you can specify the schema as:\n\n```json\n{\n \"schema\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"object\",\n \"properties\": {\n \"first\": {\n \"type\": \"string\"\n },\n \"last\": {\n \"type\": \"string\"\n }\n }\n }\n }\n }\n}\n```\n\nThese will be extracted as `{{ name }}`. And, `{{ name.first }}` and `{{ name.last }}` will be accessible.\n\n4.3. If you hit example.com and it returns `[\"94123\", \"94124\"]`, then you can specify the schema as:\n\n```json\n{\n \"schema\": {\n \"type\": \"array\",\n \"title\": \"zipCodes\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n}\n```\n\nThis will be extracted as `{{ zipCodes }}`. To access the array items, you can use `{{ zipCodes[0] }}` and `{{ zipCodes[1] }}`.\n\n4.4. If you hit example.com and it returns `[{\"name\": \"John\", \"age\": 30, \"zipCodes\": [\"94123\", \"94124\"]}, {\"name\": \"Jane\", \"age\": 25, \"zipCodes\": [\"94125\", \"94126\"]}]`, then you can specify the schema as:\n\n```json\n{\n \"schema\": {\n \"type\": \"array\",\n \"title\": \"people\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": {\n \"type\": \"string\"\n },\n \"age\": {\n \"type\": \"number\"\n },\n \"zipCodes\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n }\n }\n }\n}\n```\n\nThis will be extracted as `{{ people }}`. To access the array items, you can use `{{ people[n].name }}`, `{{ people[n].age }}`, `{{ people[n].zipCodes }}`, `{{ people[n].zipCodes[0] }}` and `{{ people[n].zipCodes[1] }}`.\n\nNote: Both `aliases` and `schema` can be used together.", + "itemCounts": { + "description": "Aggregate counts of run items by status", "allOf": [ { - "$ref": "#/components/schemas/VariableExtractionPlan" + "$ref": "#/components/schemas/SimulationRunItemCounts" } ] - } - } - }, - "UpdateDtmfToolDTO": { - "type": "object", - "properties": { - "messages": { + }, + "simulations": { "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", + "description": "Array of simulations and/or suites to run", "items": { "oneOf": [ { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" + "$ref": "#/components/schemas/SimulationRunSimulationEntry", + "title": "Simulation" }, { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" + "$ref": "#/components/schemas/SimulationRunSuiteEntry", + "title": "Suite" } ] } }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "target": { + "description": "Target to test against", + "oneOf": [ + { + "$ref": "#/components/schemas/SimulationRunTargetAssistant", + "title": "Assistant" + }, + { + "$ref": "#/components/schemas/SimulationRunTargetSquad", + "title": "Squad" + } + ] + }, + "iterations": { + "type": "number", + "minimum": 1, + "description": "Number of times to run each simulation (default: 1)", + "default": 1 + }, + "transport": { + "description": "Transport configuration for the simulation runs", "allOf": [ { - "$ref": "#/components/schemas/ToolRejectionPlan" + "$ref": "#/components/schemas/SimulationRunTransportConfiguration" } ] } - } + }, + "required": [ + "id", + "orgId", + "status", + "queuedAt", + "createdAt", + "updatedAt", + "simulations", + "target" + ] }, - "UpdateEndCallToolDTO": { + "SimulationRunListSource": { "type": "object", "properties": { - "messages": { + "type": { + "type": "string", + "enum": [ + "suite", + "simulation", + "adHoc", + "api" + ] + }, + "id": { + "type": "string", + "format": "uuid" + }, + "name": { + "type": "string" + }, + "linkable": { + "type": "boolean" + }, + "simulationIds": { "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" - } - ] + "type": "string" } + } + }, + "required": [ + "type", + "name", + "linkable", + "simulationIds" + ] + }, + "SimulationRunListSummary": { + "type": "object", + "properties": { + "source": { + "$ref": "#/components/schemas/SimulationRunListSource" + }, + "targetSnapshotName": { + "type": "string" + }, + "simulationCount": { + "type": "number" + } + }, + "required": [ + "source", + "simulationCount" + ] + }, + "SimulationRunListItem": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique identifier for the run", + "format": "uuid" + }, + "orgId": { + "type": "string", + "description": "Organization ID", + "format": "uuid" + }, + "status": { + "type": "string", + "enum": [ + "queued", + "running", + "ended" + ], + "description": "Current status of the run" + }, + "queuedAt": { + "format": "date-time", + "type": "string", + "description": "When the run was queued" + }, + "startedAt": { + "format": "date-time", + "type": "string", + "description": "When the run started" + }, + "endedAt": { + "format": "date-time", + "type": "string", + "description": "When the run ended" }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "endedReason": { + "type": "string", + "description": "Reason the run ended" + }, + "createdAt": { + "format": "date-time", + "type": "string", + "description": "ISO 8601 date-time when created" + }, + "updatedAt": { + "format": "date-time", + "type": "string", + "description": "ISO 8601 date-time when last updated" + }, + "itemCounts": { + "description": "Aggregate counts of run items by status", "allOf": [ { - "$ref": "#/components/schemas/ToolRejectionPlan" + "$ref": "#/components/schemas/SimulationRunItemCounts" } ] - } - } - }, - "UpdateFunctionToolDTO": { - "type": "object", - "properties": { - "messages": { + }, + "simulations": { "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", + "description": "Array of simulations and/or suites to run", "items": { "oneOf": [ { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" + "$ref": "#/components/schemas/SimulationRunSimulationEntry", + "title": "Simulation" }, { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" + "$ref": "#/components/schemas/SimulationRunSuiteEntry", + "title": "Suite" } ] } }, - "async": { - "type": "boolean", - "example": false, - "description": "This determines if the tool is async.\n\n If async, the assistant will move forward without waiting for your server to respond. This is useful if you just want to trigger something on your server.\n\n If sync, the assistant will wait for your server to respond. This is useful if want assistant to respond with the result from your server.\n\n Defaults to synchronous (`false`)." - }, - "server": { - "description": "\n This is the server where a `tool-calls` webhook will be sent.\n\n Notes:\n - Webhook is sent to this server when a tool call is made.\n - Webhook contains the call, assistant, and phone number objects.\n - Webhook contains the variables set on the assistant.\n - Webhook is sent to the first available URL in this order: {{tool.server.url}}, {{assistant.server.url}}, {{phoneNumber.server.url}}, {{org.server.url}}.\n - Webhook expects a response with tool call result.", - "allOf": [ + "target": { + "description": "Target to test against", + "oneOf": [ { - "$ref": "#/components/schemas/Server" - } - ] - }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", - "allOf": [ + "$ref": "#/components/schemas/SimulationRunTargetAssistant", + "title": "Assistant" + }, { - "$ref": "#/components/schemas/ToolRejectionPlan" + "$ref": "#/components/schemas/SimulationRunTargetSquad", + "title": "Squad" } ] }, - "function": { - "description": "This is the function definition of the tool.", + "iterations": { + "type": "number", + "minimum": 1, + "description": "Number of times to run each simulation (default: 1)", + "default": 1 + }, + "transport": { + "description": "Transport configuration for the simulation runs", "allOf": [ { - "$ref": "#/components/schemas/OpenAIFunction" + "$ref": "#/components/schemas/SimulationRunTransportConfiguration" } ] + }, + "summary": { + "$ref": "#/components/schemas/SimulationRunListSummary" } - } + }, + "required": [ + "id", + "orgId", + "status", + "queuedAt", + "createdAt", + "updatedAt", + "simulations", + "target", + "summary" + ] }, - "UpdateGhlToolDTO": { + "SimulationRunsPaginatedResponse": { "type": "object", "properties": { - "messages": { + "results": { "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" - } - ] + "$ref": "#/components/schemas/SimulationRunListItem" } }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", - "allOf": [ - { - "$ref": "#/components/schemas/ToolRejectionPlan" - } - ] - }, "metadata": { - "$ref": "#/components/schemas/GhlToolMetadata" + "$ref": "#/components/schemas/PaginationMeta" } - } + }, + "required": [ + "results", + "metadata" + ] }, - "UpdateMakeToolDTO": { + "SimulationRunItemCallMonitor": { "type": "object", "properties": { - "messages": { - "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" - } - ] - } - }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", - "allOf": [ - { - "$ref": "#/components/schemas/ToolRejectionPlan" - } - ] - }, - "metadata": { - "$ref": "#/components/schemas/MakeToolMetadata" + "listenUrl": { + "type": "string", + "description": "This is the WebSocket URL to listen to the live call audio (combined both parties)." } } }, - "UpdateHandoffToolDTO": { + "SimulationRunItemCallMetadata": { "type": "object", "properties": { + "transcript": { + "type": "string", + "description": "This is the transcript of the conversation." + }, "messages": { "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", + "description": "This is the list of conversation messages in OpenAI format.", "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" - } - ] + "type": "object" } }, - "destinations": { - "type": "array", - "description": "These are the destinations that the call can be handed off to.\n\nUsage:\n1. Single destination\n\nUse `assistantId` to handoff the call to a saved assistant, or `assistantName` to handoff the call to an assistant in the same squad.\n\n```json\n{\n \"tools\": [\n {\n \"type\": \"handoff\",\n \"destinations\": [\n {\n \"type\": \"assistant\",\n \"assistantId\": \"assistant-123\", // or \"assistantName\": \"Assistant123\"\n \"description\": \"customer wants to be handed off to assistant-123\",\n \"contextEngineeringPlan\": {\n \"type\": \"all\"\n }\n }\n ],\n }\n ]\n}\n```\n\n2. Multiple destinations\n\n2.1. Multiple Tools, Each With One Destination (OpenAI recommended)\n\n```json\n{\n \"tools\": [\n {\n \"type\": \"handoff\",\n \"destinations\": [\n {\n \"type\": \"assistant\",\n \"assistantId\": \"assistant-123\",\n \"description\": \"customer wants to be handed off to assistant-123\",\n \"contextEngineeringPlan\": {\n \"type\": \"all\"\n }\n },\n ],\n },\n {\n \"type\": \"handoff\",\n \"destinations\": [\n {\n \"type\": \"assistant\",\n \"assistantId\": \"assistant-456\",\n \"description\": \"customer wants to be handed off to assistant-456\",\n \"contextEngineeringPlan\": {\n \"type\": \"all\"\n }\n }\n ],\n }\n ]\n}\n```\n\n2.2. One Tool, Multiple Destinations (Anthropic recommended)\n\n```json\n{\n \"tools\": [\n {\n \"type\": \"handoff\",\n \"destinations\": [\n {\n \"type\": \"assistant\",\n \"assistantId\": \"assistant-123\",\n \"description\": \"customer wants to be handed off to assistant-123\",\n \"contextEngineeringPlan\": {\n \"type\": \"all\"\n }\n },\n {\n \"type\": \"assistant\",\n \"assistantId\": \"assistant-456\",\n \"description\": \"customer wants to be handed off to assistant-456\",\n \"contextEngineeringPlan\": {\n \"type\": \"all\"\n }\n }\n ],\n }\n ]\n}\n```\n\n3. Dynamic destination\n\n3.1 To determine the destination dynamically, supply a `dynamic` handoff destination type and a `server` object.\n VAPI will send a handoff-destination-request webhook to the `server.url`.\n The response from the server will be used as the destination (if valid).\n\n```json\n{\n \"tools\": [\n {\n \"type\": \"handoff\",\n \"destinations\": [\n {\n \"type\": \"dynamic\",\n \"server\": {\n \"url\": \"https://example.com\"\n }\n }\n ],\n }\n ]\n}\n```\n\n3.2. To pass custom parameters to the server, you can use the `function` object.\n\n```json\n{\n \"tools\": [\n {\n \"type\": \"handoff\",\n \"destinations\": [\n {\n \"type\": \"dynamic\",\n \"server\": {\n \"url\": \"https://example.com\"\n },\n }\n ],\n \"function\": {\n \"name\": \"handoff\",\n \"description\": \"Call this function when the customer is ready to be handed off to the next assistant\",\n \"parameters\": {\n \"type\": \"object\",\n \"properties\": {\n \"destination\": {\n \"type\": \"string\",\n \"description\": \"Use dynamic when customer is ready to be handed off to the next assistant\",\n \"enum\": [\"dynamic\"]\n },\n \"customerAreaCode\": {\n \"type\": \"number\",\n \"description\": \"Area code of the customer\"\n },\n \"customerIntent\": {\n \"type\": \"string\",\n \"enum\": [\"new-customer\", \"existing-customer\"],\n \"description\": \"Use new-customer when customer is a new customer, existing-customer when customer is an existing customer\"\n },\n \"customerSentiment\": {\n \"type\": \"string\",\n \"enum\": [\"positive\", \"negative\", \"neutral\"],\n \"description\": \"Use positive when customer is happy, negative when customer is unhappy, neutral when customer is neutral\"\n }\n }\n }\n }\n }\n ]\n}\n```\n\nThe properties `customerAreaCode`, `customerIntent`, and `customerSentiment` will be passed to the server in the webhook request body.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/HandoffDestinationAssistant", - "title": "Assistant" - }, - { - "$ref": "#/components/schemas/HandoffDestinationDynamic", - "title": "Dynamic" - } - ] - } + "recordingUrl": { + "type": "string", + "description": "This is the URL to the call recording." }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "monitor": { + "description": "This is the call monitoring data (live listen URL).", "allOf": [ { - "$ref": "#/components/schemas/ToolRejectionPlan" + "$ref": "#/components/schemas/SimulationRunItemCallMonitor" } ] } } }, - "UpdateTransferCallToolDTO": { + "SimulationRunItemMetadata": { "type": "object", "properties": { - "messages": { - "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" - } - ] - } + "assistant": { + "type": "object", + "description": "This is a snapshot of the assistant at run creation time.", + "additionalProperties": true }, - "destinations": { - "type": "array", - "description": "These are the destinations that the call can be transferred to. If no destinations are provided, server.url will be used to get the transfer destination once the tool is called.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/TransferDestinationAssistant", - "title": "Assistant" - }, - { - "$ref": "#/components/schemas/TransferDestinationNumber", - "title": "Number" - }, - { - "$ref": "#/components/schemas/TransferDestinationSip", - "title": "Sip" - } - ] - } + "squad": { + "type": "object", + "description": "This is a snapshot of the squad at run creation time.", + "additionalProperties": true }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "scenario": { + "type": "object", + "description": "This is a snapshot of the scenario at run creation time.", + "additionalProperties": true + }, + "personality": { + "type": "object", + "description": "This is a snapshot of the personality at run creation time.", + "additionalProperties": true + }, + "simulation": { + "type": "object", + "description": "This is a snapshot of the simulation at run creation time.", + "additionalProperties": true + }, + "call": { + "description": "This is the call-related data (transcript, messages, recording).", "allOf": [ { - "$ref": "#/components/schemas/ToolRejectionPlan" + "$ref": "#/components/schemas/SimulationRunItemCallMetadata" } ] + }, + "hooks": { + "type": "object", + "description": "Hook execution state for this run item (used for idempotency + debugging).", + "additionalProperties": true } } }, - "UpdateOutputToolDTO": { + "StructuredOutputEvaluationResult": { "type": "object", "properties": { - "messages": { - "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" - } - ] - } + "structuredOutputId": { + "type": "string", + "description": "This is the ID of the structured output that was evaluated.\nWill be 'inline' for inline structured output definitions." }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "name": { + "type": "string", + "description": "This is the name of the structured output." + }, + "path": { + "type": "string", + "description": "This is the optional dot-notation path evaluated within an object structured output." + }, + "description": { + "type": "string", + "description": "This is the structured output description captured when the evaluation ran." + }, + "schema": { + "description": "This is the structured output schema captured when the evaluation ran.", "allOf": [ { - "$ref": "#/components/schemas/ToolRejectionPlan" + "$ref": "#/components/schemas/JsonSchema" } ] - } - } - }, - "UpdateBashToolDTO": { - "type": "object", - "properties": { - "messages": { - "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" - } - ] - } - }, - "subType": { - "type": "string", - "enum": [ - "bash_20241022" - ], - "description": "The sub type of tool." }, - "server": { - "description": "\n This is the server where a `tool-calls` webhook will be sent.\n\n Notes:\n - Webhook is sent to this server when a tool call is made.\n - Webhook contains the call, assistant, and phone number objects.\n - Webhook contains the variables set on the assistant.\n - Webhook is sent to the first available URL in this order: {{tool.server.url}}, {{assistant.server.url}}, {{phoneNumber.server.url}}, {{org.server.url}}.\n - Webhook expects a response with tool call result.", - "allOf": [ + "extractedValue": { + "description": "This is the value extracted from the call by the structured output.", + "oneOf": [ { - "$ref": "#/components/schemas/Server" + "type": "number" + }, + { + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" } ] }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", - "allOf": [ + "expectedValue": { + "description": "This is the expected value that was defined in the evaluation plan.", + "oneOf": [ { - "$ref": "#/components/schemas/ToolRejectionPlan" + "type": "number" + }, + { + "type": "string" + }, + { + "type": "boolean" } ] }, - "name": { + "comparator": { "type": "string", - "description": "The name of the tool, fixed to 'bash'", - "default": "bash", + "description": "This is the comparison operator used for evaluation.", "enum": [ - "bash" + "=", + "!=", + ">", + "<", + ">=", + "<=" ] + }, + "passed": { + "type": "boolean", + "description": "This indicates whether the evaluation passed (extracted value matched expected value using comparator)." + }, + "required": { + "type": "boolean", + "description": "This indicates whether this evaluation was required for the simulation to pass." + }, + "error": { + "type": "string", + "description": "This contains any error that occurred during extraction." + }, + "isSkipped": { + "type": "boolean", + "description": "This indicates whether this evaluation was skipped (e.g., multimodal in chat mode)." + }, + "skipReason": { + "type": "string", + "description": "This contains the reason for skipping the evaluation." } - } + }, + "required": [ + "structuredOutputId", + "name", + "extractedValue", + "expectedValue", + "comparator", + "passed", + "required" + ] }, - "UpdateComputerToolDTO": { + "LatencyMetrics": { "type": "object", "properties": { - "messages": { + "turnCount": { + "type": "number", + "description": "This is the number of conversation turns." + }, + "avgTurn": { + "type": "number", + "description": "This is the average total turn latency in milliseconds." + }, + "avgTranscriber": { + "type": "number", + "description": "This is the average transcriber latency in milliseconds." + }, + "avgModel": { + "type": "number", + "description": "This is the average LLM/model latency in milliseconds." + }, + "avgVoice": { + "type": "number", + "description": "This is the average voice/TTS latency in milliseconds." + }, + "avgEndpointing": { + "type": "number", + "description": "This is the average endpointing latency in milliseconds." + } + }, + "required": [ + "turnCount" + ] + }, + "SimulationRunItemResults": { + "type": "object", + "properties": { + "evaluations": { + "description": "This is the list of results from structured output evaluations.", "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" - } - ] + "$ref": "#/components/schemas/StructuredOutputEvaluationResult" } }, - "subType": { - "type": "string", - "enum": [ - "computer_20241022" - ], - "description": "The sub type of tool." + "passed": { + "type": "boolean", + "description": "This indicates whether all required evaluations passed." }, - "server": { - "description": "\n This is the server where a `tool-calls` webhook will be sent.\n\n Notes:\n - Webhook is sent to this server when a tool call is made.\n - Webhook contains the call, assistant, and phone number objects.\n - Webhook contains the variables set on the assistant.\n - Webhook is sent to the first available URL in this order: {{tool.server.url}}, {{assistant.server.url}}, {{phoneNumber.server.url}}, {{org.server.url}}.\n - Webhook expects a response with tool call result.", + "latencyMetrics": { + "description": "This contains the latency metrics collected from the call.", "allOf": [ { - "$ref": "#/components/schemas/Server" + "$ref": "#/components/schemas/LatencyMetrics" } ] + } + }, + "required": [ + "evaluations", + "passed" + ] + }, + "SimulationRunItemImprovementSuggestion": { + "type": "object", + "properties": { + "issue": { + "type": "string", + "description": "This is the issue identified." }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "suggestion": { + "type": "string", + "description": "This is the suggested improvement." + } + }, + "required": [ + "issue", + "suggestion" + ] + }, + "SimulationRunItemImprovements": { + "type": "object", + "properties": { + "analysis": { + "type": "string", + "description": "This is a summary analysis of why evaluations failed." + }, + "systemPromptSuggestions": { + "description": "This is the list of suggestions for improving the system prompt.", + "type": "array", + "items": { + "$ref": "#/components/schemas/SimulationRunItemImprovementSuggestion" + } + }, + "toolSuggestions": { + "description": "This is the list of suggestions for improving tools.", + "type": "array", + "items": { + "$ref": "#/components/schemas/SimulationRunItemImprovementSuggestion" + } + }, + "scenarioSuggestions": { + "description": "This is the list of suggestions for improving the scenario/evaluation plan.", + "type": "array", + "items": { + "$ref": "#/components/schemas/SimulationRunItemImprovementSuggestion" + } + }, + "suggestedSystemPrompt": { + "type": "string", + "description": "This is a complete revised system prompt if major changes are needed." + } + }, + "required": [ + "analysis", + "systemPromptSuggestions", + "toolSuggestions", + "scenarioSuggestions" + ] + }, + "SimulationRunConfiguration": { + "type": "object", + "properties": { + "transport": { + "description": "Transport configuration for the simulation run", "allOf": [ { - "$ref": "#/components/schemas/ToolRejectionPlan" + "$ref": "#/components/schemas/SimulationRunTransportConfiguration" } ] + } + } + }, + "SimulationRunItem": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "This is the unique identifier for the simulation run item.", + "format": "uuid" }, - "name": { + "orgId": { "type": "string", - "description": "The name of the tool, fixed to 'computer'", - "default": "computer", + "description": "This is the unique identifier for the organization.", + "format": "uuid" + }, + "simulationId": { + "type": "string", + "description": "This is the ID of the simulation this run belongs to.", + "format": "uuid" + }, + "status": { + "type": "string", + "description": "This is the current status of the run.", "enum": [ - "computer" + "queued", + "running", + "evaluating", + "passed", + "failed", + "canceled" ] }, - "displayWidthPx": { - "type": "number", - "description": "The display width in pixels" + "queuedAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the run was queued." }, - "displayHeightPx": { - "type": "number", - "description": "The display height in pixels" + "startedAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the run started." + }, + "completedAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the run completed." + }, + "failedAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the run failed." + }, + "canceledAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the run was canceled." + }, + "failureReason": { + "type": "string", + "description": "This is the reason for failure.", + "maxLength": 2000 + }, + "callId": { + "type": "string", + "description": "This is the ID of the target Vapi call (the assistant being tested).", + "format": "uuid" + }, + "createdAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the run item was created." + }, + "updatedAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the run item was last updated." + }, + "runId": { + "type": "string", + "description": "This is the ID of the parent run (batch/group).", + "format": "uuid" }, - "displayNumber": { - "type": "number", - "description": "Optional display number" - } - } - }, - "UpdateTextEditorToolDTO": { - "type": "object", - "properties": { - "messages": { + "hooks": { "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", + "description": "Hooks configured for this simulation run item", "items": { "oneOf": [ { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" + "$ref": "#/components/schemas/SimulationHookCallStarted", + "title": "SimulationHookCallStarted" }, { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" + "$ref": "#/components/schemas/SimulationHookCallEnded", + "title": "SimulationHookCallEnded" } ] } }, - "subType": { + "iterationNumber": { + "type": "number", + "description": "This is the iteration number (1-indexed) when run with iterations > 1.", + "default": 1 + }, + "sessionId": { "type": "string", - "enum": [ - "text_editor_20241022" - ], - "description": "The sub type of tool." + "description": "This is the session ID for chat-based simulations (webchat transport).", + "format": "uuid" }, - "server": { - "description": "\n This is the server where a `tool-calls` webhook will be sent.\n\n Notes:\n - Webhook is sent to this server when a tool call is made.\n - Webhook contains the call, assistant, and phone number objects.\n - Webhook contains the variables set on the assistant.\n - Webhook is sent to the first available URL in this order: {{tool.server.url}}, {{assistant.server.url}}, {{phoneNumber.server.url}}, {{org.server.url}}.\n - Webhook expects a response with tool call result.", + "scenarioId": { + "type": "string", + "description": "This is the scenario ID at run creation time.", + "format": "uuid" + }, + "personalityId": { + "type": "string", + "description": "This is the personality ID at run creation time.", + "format": "uuid" + }, + "metadata": { + "description": "This is the metadata containing snapshots and call data.", "allOf": [ { - "$ref": "#/components/schemas/Server" + "$ref": "#/components/schemas/SimulationRunItemMetadata" } ] }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "results": { + "description": "This is the results of the simulation run.", "allOf": [ { - "$ref": "#/components/schemas/ToolRejectionPlan" + "$ref": "#/components/schemas/SimulationRunItemResults" } ] }, - "name": { + "improvementSuggestions": { + "description": "This is the AI-generated improvement suggestions for failed runs.", + "allOf": [ + { + "$ref": "#/components/schemas/SimulationRunItemImprovements" + } + ] + }, + "configurations": { + "description": "This is the configuration for how this simulation run executes.", + "allOf": [ + { + "$ref": "#/components/schemas/SimulationRunConfiguration" + } + ] + } + }, + "required": [ + "id", + "orgId", + "simulationId", + "status", + "queuedAt", + "createdAt", + "updatedAt" + ] + }, + "SimulationSuiteTargetAssignment": { + "type": "object", + "properties": { + "targetType": { "type": "string", - "description": "The name of the tool, fixed to 'str_replace_editor'", - "default": "str_replace_editor", + "description": "This is the type of target assigned to the simulation suite.", "enum": [ - "str_replace_editor" + "assistant", + "squad" ] + }, + "targetId": { + "type": "string", + "description": "This is the unique identifier of the assigned assistant or squad.", + "format": "uuid" } - } + }, + "required": [ + "targetType", + "targetId" + ] }, - "UpdateQueryToolDTO": { + "CreateSimulationSuiteDTO": { "type": "object", "properties": { - "messages": { + "name": { + "type": "string", + "description": "This is the name of the simulation suite.", + "maxLength": 80, + "example": "Checkout Flow Tests" + }, + "slackWebhookUrl": { + "type": "string", + "description": "This is the Slack webhook URL for notifications." + }, + "simulationIds": { + "description": "This is the list of simulation IDs to include in the suite.", "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" - } - ] + "type": "string" } }, - "knowledgeBases": { - "description": "The knowledge bases to query", + "targetAssignments": { + "description": "Optional assistant or squad assignments for the suite.", "type": "array", "items": { - "$ref": "#/components/schemas/KnowledgeBase" + "$ref": "#/components/schemas/SimulationSuiteTargetAssignment" } }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", - "allOf": [ - { - "$ref": "#/components/schemas/ToolRejectionPlan" - } - ] + "path": { + "type": "string", + "nullable": true, + "description": "Optional folder path for organizing simulation suites.\nSupports up to 3 levels (e.g., \"dept/feature/variant\").\nMaps to GitOps resource folder structure.", + "maxLength": 255, + "pattern": "/^[a-zA-Z0-9][a-zA-Z0-9._-]*(?:\\/[a-zA-Z0-9][a-zA-Z0-9._-]*){0,2}$/" } - } + }, + "required": [ + "name", + "simulationIds" + ] }, - "UpdateGoogleCalendarCreateEventToolDTO": { + "SimulationSuite": { "type": "object", "properties": { - "messages": { + "id": { + "type": "string", + "description": "This is the unique identifier for the simulation suite.", + "format": "uuid" + }, + "orgId": { + "type": "string", + "description": "This is the unique identifier for the organization this suite belongs to.", + "format": "uuid" + }, + "createdAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the suite was created." + }, + "updatedAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the suite was last updated." + }, + "name": { + "type": "string", + "description": "This is the name of the simulation suite.", + "maxLength": 80, + "example": "Checkout Flow Tests" + }, + "slackWebhookUrl": { + "type": "string", + "description": "This is the Slack webhook URL for notifications." + }, + "path": { + "type": "string", + "nullable": true, + "description": "Optional folder path for organizing simulation suites.\nSupports up to 3 levels (e.g., \"dept/feature/variant\").\nMaps to GitOps resource folder structure.", + "maxLength": 255, + "pattern": "/^[a-zA-Z0-9][a-zA-Z0-9._-]*(?:\\/[a-zA-Z0-9][a-zA-Z0-9._-]*){0,2}$/" + }, + "simulationIds": { + "description": "This is the list of simulation IDs in this suite.", "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" - } - ] + "type": "string" } }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", - "allOf": [ - { - "$ref": "#/components/schemas/ToolRejectionPlan" - } - ] + "targetAssignments": { + "description": "This is the ordered list of assistant or squad assignments for the suite.", + "type": "array", + "items": { + "$ref": "#/components/schemas/SimulationSuiteTargetAssignment" + } } - } + }, + "required": [ + "id", + "orgId", + "createdAt", + "updatedAt", + "name", + "simulationIds", + "targetAssignments" + ] }, - "UpdateGoogleSheetsRowAppendToolDTO": { + "UpdateSimulationSuiteDTO": { "type": "object", "properties": { - "messages": { + "name": { + "type": "string", + "description": "This is the name of the simulation suite.", + "maxLength": 80 + }, + "slackWebhookUrl": { + "type": "string", + "description": "This is the Slack webhook URL for notifications." + }, + "simulationIds": { + "description": "This is the list of simulation IDs to include in the suite (replaces existing).", "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" - } - ] + "type": "string" } }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", - "allOf": [ - { - "$ref": "#/components/schemas/ToolRejectionPlan" - } - ] + "targetAssignments": { + "description": "Optional assistant or squad assignments (replaces existing).", + "type": "array", + "items": { + "$ref": "#/components/schemas/SimulationSuiteTargetAssignment" + } + }, + "path": { + "type": "string", + "nullable": true, + "description": "Optional folder path for organizing simulation suites.\nSupports up to 3 levels (e.g., \"dept/feature/variant\").\nSet to null to remove from folder.", + "maxLength": 255, + "pattern": "/^[a-zA-Z0-9][a-zA-Z0-9._-]*(?:\\/[a-zA-Z0-9][a-zA-Z0-9._-]*){0,2}$/" } } }, - "UpdateGoogleCalendarCheckAvailabilityToolDTO": { + "GenerateScenariosDTO": { "type": "object", "properties": { - "messages": { - "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" - } - ] - } + "assistantId": { + "type": "string", + "description": "ID of the assistant to generate scenarios for" }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", - "allOf": [ - { - "$ref": "#/components/schemas/ToolRejectionPlan" - } - ] + "squadId": { + "type": "string", + "description": "ID of the squad to generate scenarios for" } } }, - "UpdateSlackSendMessageToolDTO": { + "GeneratedScenario": { "type": "object", "properties": { - "messages": { - "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" - } - ] - } + "name": { + "type": "string", + "description": "Short descriptive name" }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", - "allOf": [ - { - "$ref": "#/components/schemas/ToolRejectionPlan" - } - ] + "instructions": { + "type": "string", + "description": "Instructions for the tester" + }, + "category": { + "type": "string", + "enum": [ + "happy_path", + "edge_case", + "failure_mode" + ], + "description": "Scenario category" + }, + "reasoning": { + "type": "string", + "description": "Why this scenario is valuable" } - } + }, + "required": [ + "name", + "instructions", + "category", + "reasoning" + ] }, - "UpdateSmsToolDTO": { + "GenerateScenariosResponse": { "type": "object", "properties": { - "messages": { + "scenarios": { + "description": "Generated scenarios", "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" - } - ] + "$ref": "#/components/schemas/GeneratedScenario" } }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", - "allOf": [ - { - "$ref": "#/components/schemas/ToolRejectionPlan" - } - ] + "coverageNotes": { + "type": "string", + "description": "Summary of test coverage" } - } + }, + "required": [ + "scenarios", + "coverageNotes" + ] }, - "UpdateMcpToolDTO": { + "CreateSimulationDTO": { "type": "object", "properties": { - "messages": { - "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" - } - ] - } + "name": { + "type": "string", + "description": "This is an optional friendly name for the simulation.", + "maxLength": 80, + "example": "Eligible Path with Confused User" }, - "server": { - "description": "\n This is the server where a `tool-calls` webhook will be sent.\n\n Notes:\n - Webhook is sent to this server when a tool call is made.\n - Webhook contains the call, assistant, and phone number objects.\n - Webhook contains the variables set on the assistant.\n - Webhook is sent to the first available URL in this order: {{tool.server.url}}, {{assistant.server.url}}, {{phoneNumber.server.url}}, {{org.server.url}}.\n - Webhook expects a response with tool call result.", - "allOf": [ - { - "$ref": "#/components/schemas/Server" - } - ] + "scenarioId": { + "type": "string", + "description": "This is the ID of the scenario to use for this simulation.", + "format": "uuid" }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", - "allOf": [ - { - "$ref": "#/components/schemas/ToolRejectionPlan" - } - ] + "personalityId": { + "type": "string", + "description": "This is the ID of the personality to use for this simulation.", + "format": "uuid" }, - "metadata": { - "$ref": "#/components/schemas/McpToolMetadata" + "path": { + "type": "string", + "nullable": true, + "description": "Optional folder path for organizing simulations.\nSupports up to 3 levels (e.g., \"dept/feature/variant\").\nMaps to GitOps resource folder structure.", + "maxLength": 255, + "pattern": "/^[a-zA-Z0-9][a-zA-Z0-9._-]*(?:\\/[a-zA-Z0-9][a-zA-Z0-9._-]*){0,2}$/" + } + }, + "required": [ + "scenarioId", + "personalityId" + ] + }, + "Simulation": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "This is the unique identifier for the simulation.", + "format": "uuid" + }, + "orgId": { + "type": "string", + "description": "This is the unique identifier for the organization this simulation belongs to.", + "format": "uuid" + }, + "createdAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the simulation was created." + }, + "updatedAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the simulation was last updated." + }, + "name": { + "type": "string", + "description": "This is an optional friendly name for the simulation.", + "maxLength": 80, + "example": "Eligible Path with Confused User" + }, + "scenarioId": { + "type": "string", + "description": "This is the ID of the scenario to use for this simulation.", + "format": "uuid" + }, + "personalityId": { + "type": "string", + "description": "This is the ID of the personality to use for this simulation.", + "format": "uuid" + }, + "path": { + "type": "string", + "nullable": true, + "description": "Optional folder path for organizing simulations.\nSupports up to 3 levels (e.g., \"dept/feature/variant\").\nMaps to GitOps resource folder structure.", + "maxLength": 255, + "pattern": "/^[a-zA-Z0-9][a-zA-Z0-9._-]*(?:\\/[a-zA-Z0-9][a-zA-Z0-9._-]*){0,2}$/" + } + }, + "required": [ + "id", + "orgId", + "createdAt", + "updatedAt", + "scenarioId", + "personalityId" + ] + }, + "UpdateSimulationDTO": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "This is an optional friendly name for the simulation.", + "maxLength": 80 + }, + "scenarioId": { + "type": "string", + "description": "This is the ID of the scenario to use for this simulation.", + "format": "uuid" + }, + "personalityId": { + "type": "string", + "description": "This is the ID of the personality to use for this simulation.", + "format": "uuid" + }, + "path": { + "type": "string", + "nullable": true, + "description": "Optional folder path for organizing simulations.\nSupports up to 3 levels (e.g., \"dept/feature/variant\").\nSet to null to remove from folder.", + "maxLength": 255, + "pattern": "/^[a-zA-Z0-9][a-zA-Z0-9._-]*(?:\\/[a-zA-Z0-9][a-zA-Z0-9._-]*){0,2}$/" } } }, - "UpdateGoHighLevelCalendarAvailabilityToolDTO": { + "SimulationConcurrencyResponse": { "type": "object", "properties": { - "messages": { - "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" - } - ] - } + "orgId": { + "type": "string" }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", - "allOf": [ - { - "$ref": "#/components/schemas/ToolRejectionPlan" - } - ] + "concurrencyLimit": { + "type": "number", + "description": "Max call slots for simulations (each voice simulation uses 2 call slots: tester + target)" + }, + "activeSimulations": { + "type": "number", + "description": "Number of call slots currently in use by running simulations" + }, + "availableToStart": { + "type": "number", + "description": "Number of voice simulations that can start now (available call slots / 2)" + }, + "createdAt": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "updatedAt": { + "type": "string", + "format": "date-time", + "nullable": true + }, + "isDefault": { + "type": "boolean", + "description": "True if org is using platform default concurrency limit" + } + }, + "required": [ + "orgId", + "concurrencyLimit", + "activeSimulations", + "availableToStart", + "createdAt", + "updatedAt", + "isDefault" + ] + }, + "BarInsightMetadata": { + "type": "object", + "properties": { + "xAxisLabel": { + "type": "string", + "minLength": 1, + "maxLength": 40 + }, + "yAxisLabel": { + "type": "string", + "minLength": 1, + "maxLength": 40 + }, + "yAxisMin": { + "type": "number" + }, + "yAxisMax": { + "type": "number" + }, + "name": { + "type": "string", + "minLength": 1, + "maxLength": 255 } } }, - "UpdateGoHighLevelCalendarEventCreateToolDTO": { + "InsightTimeRangeWithStep": { "type": "object", "properties": { - "messages": { - "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" - } - ] - } - }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", - "allOf": [ - { - "$ref": "#/components/schemas/ToolRejectionPlan" - } + "step": { + "type": "string", + "description": "This is the group by step for aggregation.\n\nIf not provided, defaults to group by day.", + "enum": [ + "minute", + "hour", + "day", + "week", + "month", + "quarter", + "year" ] + }, + "start": { + "type": "object", + "description": "This is the start date for the time range.\n\nShould be a valid ISO 8601 date-time string or relative time string.\nIf not provided, defaults to the 7 days ago.\n\nRelative time strings of the format \"-{number}{unit}\" are allowed.\n\nValid units are:\n- d: days\n- h: hours\n- w: weeks\n- m: months\n- y: years", + "example": "\"2025-01-01\" or \"-7d\" or \"now\"" + }, + "end": { + "type": "object", + "description": "This is the end date for the time range.\n\nShould be a valid ISO 8601 date-time string or relative time string.\nIf not provided, defaults to now.\n\nRelative time strings of the format \"-{number}{unit}\" are allowed.\n\nValid units are:\n- d: days\n- h: hours\n- w: weeks\n- m: months\n- y: years", + "example": "\"2025-01-01\" or \"now\"" + }, + "timezone": { + "type": "string", + "description": "This is the timezone you want to set for the query.\n\nIf not provided, defaults to UTC." } } }, - "UpdateGoHighLevelContactCreateToolDTO": { + "BarInsight": { "type": "object", "properties": { - "messages": { + "name": { + "type": "string", + "description": "This is the name of the Insight.", + "minLength": 1, + "maxLength": 255 + }, + "type": { + "type": "string", + "description": "This is the type of the Insight.\nIt is required to be `bar` to create a bar insight.", + "enum": [ + "bar" + ] + }, + "formulas": { "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", + "description": "Formulas are mathematical expressions applied on the data returned by the queries to transform them before being used to create the insight.\nThe formulas needs to be a valid mathematical expression, supported by MathJS - https://mathjs.org/docs/expressions/syntax.html\nA formula is created by using the query names as the variable.\nThe formulas must contain at least one query name in the LiquidJS format {{query_name}} or {{['query name']}} which will be substituted with the query result.\nFor example, if you have 2 queries, 'Was Booking Made' and 'Average Call Duration', you can create a formula like this:\n```\n{{['Query 1']}} / {{['Query 2']}} * 100\n```\n\n```\n({{[Query 1]}} * 10) + {{[Query 2]}}\n```\nThis will take the\n\nYou can also use the query names as the variable in the formula.", "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" - }, - { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" - }, - { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" - }, - { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" - } - ] + "$ref": "#/components/schemas/InsightFormula" } }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", + "metadata": { + "description": "This is the metadata for the insight.", "allOf": [ { - "$ref": "#/components/schemas/ToolRejectionPlan" + "$ref": "#/components/schemas/BarInsightMetadata" } ] - } - } - }, - "UpdateGoHighLevelContactGetToolDTO": { - "type": "object", - "properties": { - "messages": { + }, + "timeRange": { + "$ref": "#/components/schemas/InsightTimeRangeWithStep" + }, + "groupBy": { + "type": "string", + "description": "This is the group by column for the insight when table is `call`.\nThese are the columns to group the results by.\nAll results are grouped by the time range step by default.", + "example": [ + "assistant_id" + ], + "enum": [ + "assistantId", + "workflowId", + "squadId", + "phoneNumberId", + "type", + "endedReason", + "customerNumber", + "campaignId", + "artifact.structuredOutputs[OutputID]" + ] + }, + "queries": { "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", + "description": "These are the queries to run to generate the insight.", "items": { "oneOf": [ { - "$ref": "#/components/schemas/ToolMessageStart", - "title": "ToolMessageStart" + "$ref": "#/components/schemas/JSONQueryOnCallTableWithStringTypeColumn", + "title": "JSONQueryOnCallTableWithStringTypeColumn" }, { - "$ref": "#/components/schemas/ToolMessageComplete", - "title": "ToolMessageComplete" + "$ref": "#/components/schemas/JSONQueryOnCallTableWithNumberTypeColumn", + "title": "JSONQueryOnCallTableWithNumberTypeColumn" }, { - "$ref": "#/components/schemas/ToolMessageFailed", - "title": "ToolMessageFailed" + "$ref": "#/components/schemas/JSONQueryOnCallTableWithStructuredOutputColumn", + "title": "JSONQueryOnCallTableWithStructuredOutputColumn" }, { - "$ref": "#/components/schemas/ToolMessageDelayed", - "title": "ToolMessageDelayed" + "$ref": "#/components/schemas/JSONQueryOnEventsTable", + "title": "JSONQueryOnEventsTable" } ] } }, - "rejectionPlan": { - "description": "This is the plan to reject a tool call based on the conversation state.\n\n// Example 1: Reject endCall if user didn't say goodbye\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '(?i)\\\\b(bye|goodbye|farewell|see you later|take care)\\\\b',\n target: { position: -1, role: 'user' },\n negate: true // Reject if pattern does NOT match\n }]\n}\n```\n\n// Example 2: Reject transfer if user is actually asking a question\n```json\n{\n conditions: [{\n type: 'regex',\n regex: '\\\\?',\n target: { position: -1, role: 'user' }\n }]\n}\n```\n\n// Example 3: Reject transfer if user didn't mention transfer recently\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 5 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' %}\n{% assign mentioned = false %}\n{% for msg in userMessages %}\n {% if msg.content contains 'transfer' or msg.content contains 'connect' or msg.content contains 'speak to' %}\n {% assign mentioned = true %}\n {% break %}\n {% endif %}\n{% endfor %}\n{% if mentioned %}\n false\n{% else %}\n true\n{% endif %}`\n }]\n}\n```\n\n// Example 4: Reject endCall if the bot is looping and trying to exit\n```json\n{\n conditions: [{\n type: 'liquid',\n liquid: `{% assign recentMessages = messages | last: 6 %}\n{% assign userMessages = recentMessages | where: 'role', 'user' | reverse %}\n{% if userMessages.size < 3 %}\n false\n{% else %}\n {% assign msg1 = userMessages[0].content | downcase %}\n {% assign msg2 = userMessages[1].content | downcase %}\n {% assign msg3 = userMessages[2].content | downcase %}\n {% comment %} Check for repetitive messages {% endcomment %}\n {% if msg1 == msg2 or msg1 == msg3 or msg2 == msg3 %}\n true\n {% comment %} Check for common loop phrases {% endcomment %}\n {% elsif msg1 contains 'cool thanks' or msg2 contains 'cool thanks' or msg3 contains 'cool thanks' %}\n true\n {% elsif msg1 contains 'okay thanks' or msg2 contains 'okay thanks' or msg3 contains 'okay thanks' %}\n true\n {% elsif msg1 contains 'got it' or msg2 contains 'got it' or msg3 contains 'got it' %}\n true\n {% else %}\n false\n {% endif %}\n{% endif %}`\n }]\n}\n```", - "allOf": [ - { - "$ref": "#/components/schemas/ToolRejectionPlan" - } - ] - } - } - }, - "CreateFileDTO": { - "type": "object", - "properties": { - "file": { + "id": { "type": "string", - "description": "This is the File you want to upload for use with the Knowledge Base.", - "format": "binary" + "description": "This is the unique identifier for the Insight." + }, + "orgId": { + "type": "string", + "description": "This is the unique identifier for the org that this Insight belongs to." + }, + "createdAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the Insight was created." + }, + "updatedAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the Insight was last updated." + }, + "systemKey": { + "type": "string", + "description": "Stable server-owned identifier for system-created insights." } }, "required": [ - "file" + "type", + "queries", + "id", + "orgId", + "createdAt", + "updatedAt" ] }, - "File": { + "InsightTimeRange": { "type": "object", "properties": { - "object": { - "type": "string", - "enum": [ - "file" - ] + "start": { + "type": "object", + "description": "This is the start date for the time range.\n\nShould be a valid ISO 8601 date-time string or relative time string.\nIf not provided, defaults to the 7 days ago.\n\nRelative time strings of the format \"-{number}{unit}\" are allowed.\n\nValid units are:\n- d: days\n- h: hours\n- w: weeks\n- m: months\n- y: years", + "example": "\"2025-01-01\" or \"-7d\" or \"now\"" }, - "status": { - "enum": [ - "processing", - "done", - "failed" - ], - "type": "string" + "end": { + "type": "object", + "description": "This is the end date for the time range.\n\nShould be a valid ISO 8601 date-time string or relative time string.\nIf not provided, defaults to now.\n\nRelative time strings of the format \"-{number}{unit}\" are allowed.\n\nValid units are:\n- d: days\n- h: hours\n- w: weeks\n- m: months\n- y: years", + "example": "\"2025-01-01\" or \"now\"" }, + "timezone": { + "type": "string", + "description": "This is the timezone you want to set for the query.\n\nIf not provided, defaults to UTC." + } + } + }, + "PieInsight": { + "type": "object", + "properties": { "name": { "type": "string", - "description": "This is the name of the file. This is just for your own reference.", - "maxLength": 40 - }, - "originalName": { - "type": "string" - }, - "bytes": { - "type": "number" - }, - "purpose": { - "type": "string" - }, - "mimetype": { - "type": "string" - }, - "key": { - "type": "string" - }, - "path": { - "type": "string" + "description": "This is the name of the Insight.", + "minLength": 1, + "maxLength": 255 }, - "bucket": { - "type": "string" + "type": { + "type": "string", + "description": "This is the type of the Insight.\nIt is required to be `pie` to create a pie insight.", + "enum": [ + "pie" + ] }, - "url": { - "type": "string" + "formulas": { + "type": "array", + "description": "Formulas are mathematical expressions applied on the data returned by the queries to transform them before being used to create the insight.\nThe formulas needs to be a valid mathematical expression, supported by MathJS - https://mathjs.org/docs/expressions/syntax.html\nA formula is created by using the query names as the variable.\nThe formulas must contain at least one query name in the LiquidJS format {{query_name}} or {{['query name']}} which will be substituted with the query result.\nFor example, if you have 2 queries, 'Was Booking Made' and 'Average Call Duration', you can create a formula like this:\n```\n{{['Query 1']}} / {{['Query 2']}} * 100\n```\n\n```\n({{[Query 1]}} * 10) + {{[Query 2]}}\n```\nThis will take the\n\nYou can also use the query names as the variable in the formula.", + "items": { + "$ref": "#/components/schemas/InsightFormula" + } }, - "parsedTextUrl": { - "type": "string" + "timeRange": { + "$ref": "#/components/schemas/InsightTimeRange" }, - "parsedTextBytes": { - "type": "number" + "groupBy": { + "type": "string", + "description": "This is the group by column for the insight when table is `call`.\nThese are the columns to group the results by.\nAll results are grouped by the time range step by default.", + "example": [ + "assistant_id" + ], + "enum": [ + "assistantId", + "workflowId", + "squadId", + "phoneNumberId", + "type", + "endedReason", + "customerNumber", + "campaignId", + "artifact.structuredOutputs[OutputID]" + ] }, - "metadata": { - "type": "object" + "queries": { + "type": "array", + "description": "These are the queries to run to generate the insight.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/JSONQueryOnCallTableWithStringTypeColumn", + "title": "JSONQueryOnCallTableWithStringTypeColumn" + }, + { + "$ref": "#/components/schemas/JSONQueryOnCallTableWithNumberTypeColumn", + "title": "JSONQueryOnCallTableWithNumberTypeColumn" + }, + { + "$ref": "#/components/schemas/JSONQueryOnCallTableWithStructuredOutputColumn", + "title": "JSONQueryOnCallTableWithStructuredOutputColumn" + } + ] + } }, "id": { "type": "string", - "description": "This is the unique identifier for the file." + "description": "This is the unique identifier for the Insight." }, "orgId": { "type": "string", - "description": "This is the unique identifier for the org that this file belongs to." + "description": "This is the unique identifier for the org that this Insight belongs to." }, "createdAt": { "format": "date-time", "type": "string", - "description": "This is the ISO 8601 date-time string of when the file was created." + "description": "This is the ISO 8601 date-time string of when the Insight was created." }, "updatedAt": { "format": "date-time", "type": "string", - "description": "This is the ISO 8601 date-time string of when the file was last updated." + "description": "This is the ISO 8601 date-time string of when the Insight was last updated." + }, + "systemKey": { + "type": "string", + "description": "Stable server-owned identifier for system-created insights." } }, "required": [ + "type", + "queries", "id", "orgId", "createdAt", "updatedAt" ] }, - "UpdateFileDTO": { + "LineInsightMetadata": { "type": "object", "properties": { - "name": { + "xAxisLabel": { "type": "string", - "description": "This is the name of the file. This is just for your own reference.", "minLength": 1, "maxLength": 40 - } - } - }, - "TrieveKnowledgeBaseSearchPlan": { - "type": "object", - "properties": { - "topK": { - "type": "number", - "description": "Specifies the number of top chunks to return. This corresponds to the `page_size` parameter in Trieve." }, - "removeStopWords": { - "type": "boolean", - "description": "If true, stop words (specified in server/src/stop-words.txt in the git repo) will be removed. This will preserve queries that are entirely stop words." + "yAxisLabel": { + "type": "string", + "minLength": 1, + "maxLength": 40 }, - "scoreThreshold": { - "type": "number", - "description": "This is the score threshold to filter out chunks with a score below the threshold for cosine distance metric. For Manhattan Distance, Euclidean Distance, and Dot Product, it will filter out scores above the threshold distance. This threshold applies before weight and bias modifications. If not specified, this defaults to no threshold. A threshold of 0 will default to no threshold." + "yAxisMin": { + "type": "number" + }, + "yAxisMax": { + "type": "number" }, - "searchType": { + "name": { "type": "string", - "description": "This is the search method used when searching for relevant chunks from the vector store.", - "enum": [ - "fulltext", - "semantic", - "hybrid", - "bm25" - ] + "minLength": 1, + "maxLength": 255 } - }, - "required": [ - "searchType" - ] + } }, - "TrieveKnowledgeBase": { + "LineInsight": { "type": "object", "properties": { - "provider": { + "name": { + "type": "string", + "description": "This is the name of the Insight.", + "minLength": 1, + "maxLength": 255 + }, + "type": { "type": "string", - "description": "This knowledge base is provided by Trieve.\n\nTo learn more about Trieve, visit https://trieve.ai.", + "description": "This is the type of the Insight.\nIt is required to be `line` to create a line insight.", "enum": [ - "trieve" + "line" ] }, - "name": { - "type": "string", - "description": "This is the name of the knowledge base." + "formulas": { + "type": "array", + "description": "Formulas are mathematical expressions applied on the data returned by the queries to transform them before being used to create the insight.\nThe formulas needs to be a valid mathematical expression, supported by MathJS - https://mathjs.org/docs/expressions/syntax.html\nA formula is created by using the query names as the variable.\nThe formulas must contain at least one query name in the LiquidJS format {{query_name}} or {{['query name']}} which will be substituted with the query result.\nFor example, if you have 2 queries, 'Was Booking Made' and 'Average Call Duration', you can create a formula like this:\n```\n{{['Query 1']}} / {{['Query 2']}} * 100\n```\n\n```\n({{[Query 1]}} * 10) + {{[Query 2]}}\n```\nThis will take the\n\nYou can also use the query names as the variable in the formula.", + "items": { + "$ref": "#/components/schemas/InsightFormula" + } }, - "searchPlan": { - "description": "This is the searching plan used when searching for relevant chunks from the vector store.\n\nYou should configure this if you're running into these issues:\n- Too much unnecessary context is being fed as knowledge base context.\n- Not enough relevant context is being fed as knowledge base context.", + "metadata": { + "description": "This is the metadata for the insight.", "allOf": [ { - "$ref": "#/components/schemas/TrieveKnowledgeBaseSearchPlan" + "$ref": "#/components/schemas/LineInsightMetadata" } ] }, - "createPlan": { - "description": "This is the plan if you want us to create/import a new vector store using Trieve.", - "oneOf": [ - { - "$ref": "#/components/schemas/TrieveKnowledgeBaseImport", - "title": "Import" - } + "timeRange": { + "$ref": "#/components/schemas/InsightTimeRangeWithStep" + }, + "groupBy": { + "type": "string", + "description": "This is the group by column for the insight when table is `call`.\nThese are the columns to group the results by.\nAll results are grouped by the time range step by default.", + "example": [ + "assistant_id" + ], + "enum": [ + "assistantId", + "workflowId", + "squadId", + "phoneNumberId", + "type", + "endedReason", + "customerNumber", + "campaignId", + "artifact.structuredOutputs[OutputID]" ] }, + "queries": { + "type": "array", + "description": "These are the queries to run to generate the insight.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/JSONQueryOnCallTableWithStringTypeColumn", + "title": "JSONQueryOnCallTableWithStringTypeColumn" + }, + { + "$ref": "#/components/schemas/JSONQueryOnCallTableWithNumberTypeColumn", + "title": "JSONQueryOnCallTableWithNumberTypeColumn" + }, + { + "$ref": "#/components/schemas/JSONQueryOnCallTableWithStructuredOutputColumn", + "title": "JSONQueryOnCallTableWithStructuredOutputColumn" + } + ] + } + }, "id": { "type": "string", - "description": "This is the id of the knowledge base." + "description": "This is the unique identifier for the Insight." }, "orgId": { "type": "string", - "description": "This is the org id of the knowledge base." + "description": "This is the unique identifier for the org that this Insight belongs to." + }, + "createdAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the Insight was created." + }, + "updatedAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the Insight was last updated." + }, + "systemKey": { + "type": "string", + "description": "Stable server-owned identifier for system-created insights." } }, "required": [ - "provider", + "type", + "queries", "id", - "orgId" + "orgId", + "createdAt", + "updatedAt" ] }, - "CustomKnowledgeBase": { + "TextInsight": { "type": "object", "properties": { - "provider": { + "name": { "type": "string", - "description": "This knowledge base is bring your own knowledge base implementation.", + "description": "This is the name of the Insight.", + "minLength": 1, + "maxLength": 255 + }, + "type": { + "type": "string", + "description": "This is the type of the Insight.\nIt is required to be `text` to create a text insight.", "enum": [ - "custom-knowledge-base" + "text" ] }, - "server": { - "description": "This is where the knowledge base request will be sent.\n\nRequest Example:\n\nPOST https://{server.url}\nContent-Type: application/json\n\n{\n \"messsage\": {\n \"type\": \"knowledge-base-request\",\n \"messages\": [\n {\n \"role\": \"user\",\n \"content\": \"Why is ocean blue?\"\n }\n ],\n ...other metadata about the call...\n }\n}\n\nResponse Expected:\n```\n{\n \"message\": {\n \"role\": \"assistant\",\n \"content\": \"The ocean is blue because water absorbs everything but blue.\",\n }, // YOU CAN RETURN THE EXACT RESPONSE TO SPEAK\n \"documents\": [\n {\n \"content\": \"The ocean is blue primarily because water absorbs colors in the red part of the light spectrum and scatters the blue light, making it more visible to our eyes.\",\n \"similarity\": 1\n },\n {\n \"content\": \"Blue light is scattered more by the water molecules than other colors, enhancing the blue appearance of the ocean.\",\n \"similarity\": .5\n }\n ] // OR, YOU CAN RETURN AN ARRAY OF DOCUMENTS THAT WILL BE SENT TO THE MODEL\n}\n```", - "allOf": [ - { - "$ref": "#/components/schemas/Server" - } - ] + "formula": { + "type": "object", + "description": "Formulas are mathematical expressions applied on the data returned by the queries to transform them before being used to create the insight.\nThe formulas needs to be a valid mathematical expression, supported by MathJS - https://mathjs.org/docs/expressions/syntax.html\nA formula is created by using the query names as the variable.\nThe formulas must contain at least one query name in the LiquidJS format {{query_name}} or {{['query name']}} which will be substituted with the query result.\nFor example, if you have 2 queries, 'Was Booking Made' and 'Average Call Duration', you can create a formula like this:\n```\n{{['Query 1']}} / {{['Query 2']}} * 100\n```\n\n```\n({{[Query 1]}} * 10) + {{[Query 2]}}\n```\nThis will take the\n\nYou can also use the query names as the variable in the formula.", + "items": { + "$ref": "#/components/schemas/InsightFormula" + } + }, + "timeRange": { + "$ref": "#/components/schemas/InsightTimeRange" + }, + "queries": { + "type": "array", + "description": "These are the queries to run to generate the insight.\nFor Text Insights, we only allow a single query, or require a formula if multiple queries are provided", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/JSONQueryOnCallTableWithStringTypeColumn", + "title": "JSONQueryOnCallTableWithStringTypeColumn" + }, + { + "$ref": "#/components/schemas/JSONQueryOnCallTableWithNumberTypeColumn", + "title": "JSONQueryOnCallTableWithNumberTypeColumn" + }, + { + "$ref": "#/components/schemas/JSONQueryOnCallTableWithStructuredOutputColumn", + "title": "JSONQueryOnCallTableWithStructuredOutputColumn" + } + ] + } }, "id": { "type": "string", - "description": "This is the id of the knowledge base." + "description": "This is the unique identifier for the Insight." }, "orgId": { "type": "string", - "description": "This is the org id of the knowledge base." + "description": "This is the unique identifier for the org that this Insight belongs to." + }, + "createdAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the Insight was created." + }, + "updatedAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the Insight was last updated." + }, + "systemKey": { + "type": "string", + "description": "Stable server-owned identifier for system-created insights." } }, "required": [ - "provider", - "server", + "type", + "queries", "id", - "orgId" + "orgId", + "createdAt", + "updatedAt" ] }, - "CreateTrieveKnowledgeBaseDTO": { + "UpdateBarInsightFromCallTableDTO": { "type": "object", "properties": { - "provider": { + "name": { "type": "string", - "description": "This knowledge base is provided by Trieve.\n\nTo learn more about Trieve, visit https://trieve.ai.", + "description": "This is the name of the Insight.", + "minLength": 1, + "maxLength": 255 + }, + "type": { + "type": "string", + "description": "This is the type of the Insight.\nIt is required to be `bar` to create a bar insight.", "enum": [ - "trieve" + "bar" ] }, - "name": { - "type": "string", - "description": "This is the name of the knowledge base." + "formulas": { + "type": "array", + "description": "Formulas are mathematical expressions applied on the data returned by the queries to transform them before being used to create the insight.\nThe formulas needs to be a valid mathematical expression, supported by MathJS - https://mathjs.org/docs/expressions/syntax.html\nA formula is created by using the query names as the variable.\nThe formulas must contain at least one query name in the LiquidJS format {{query_name}} or {{['query name']}} which will be substituted with the query result.\nFor example, if you have 2 queries, 'Was Booking Made' and 'Average Call Duration', you can create a formula like this:\n```\n{{['Query 1']}} / {{['Query 2']}} * 100\n```\n\n```\n({{[Query 1]}} * 10) + {{[Query 2]}}\n```\nThis will take the\n\nYou can also use the query names as the variable in the formula.", + "items": { + "$ref": "#/components/schemas/InsightFormula" + } }, - "searchPlan": { - "description": "This is the searching plan used when searching for relevant chunks from the vector store.\n\nYou should configure this if you're running into these issues:\n- Too much unnecessary context is being fed as knowledge base context.\n- Not enough relevant context is being fed as knowledge base context.", + "metadata": { + "description": "This is the metadata for the insight.", "allOf": [ { - "$ref": "#/components/schemas/TrieveKnowledgeBaseSearchPlan" + "$ref": "#/components/schemas/BarInsightMetadata" } ] }, - "createPlan": { - "description": "This is the plan if you want us to create/import a new vector store using Trieve.", - "oneOf": [ - { - "$ref": "#/components/schemas/TrieveKnowledgeBaseImport", - "title": "Import" - } + "timeRange": { + "$ref": "#/components/schemas/InsightTimeRangeWithStep" + }, + "groupBy": { + "type": "string", + "description": "This is the group by column for the insight when table is `call`.\nThese are the columns to group the results by.\nAll results are grouped by the time range step by default.", + "example": [ + "assistant_id" + ], + "enum": [ + "assistantId", + "workflowId", + "squadId", + "phoneNumberId", + "type", + "endedReason", + "customerNumber", + "campaignId", + "artifact.structuredOutputs[OutputID]" ] + }, + "queries": { + "type": "array", + "description": "These are the queries to run to generate the insight.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/JSONQueryOnCallTableWithStringTypeColumn", + "title": "JSONQueryOnCallTableWithStringTypeColumn" + }, + { + "$ref": "#/components/schemas/JSONQueryOnCallTableWithNumberTypeColumn", + "title": "JSONQueryOnCallTableWithNumberTypeColumn" + }, + { + "$ref": "#/components/schemas/JSONQueryOnCallTableWithStructuredOutputColumn", + "title": "JSONQueryOnCallTableWithStructuredOutputColumn" + }, + { + "$ref": "#/components/schemas/JSONQueryOnEventsTable", + "title": "JSONQueryOnEventsTable" + } + ] + } } - }, - "required": [ - "provider" - ] + } }, - "UpdateTrieveKnowledgeBaseDTO": { + "UpdatePieInsightFromCallTableDTO": { "type": "object", "properties": { "name": { "type": "string", - "description": "This is the name of the knowledge base." + "description": "This is the name of the Insight.", + "minLength": 1, + "maxLength": 255 }, - "searchPlan": { - "description": "This is the searching plan used when searching for relevant chunks from the vector store.\n\nYou should configure this if you're running into these issues:\n- Too much unnecessary context is being fed as knowledge base context.\n- Not enough relevant context is being fed as knowledge base context.", - "allOf": [ - { - "$ref": "#/components/schemas/TrieveKnowledgeBaseSearchPlan" - } + "type": { + "type": "string", + "description": "This is the type of the Insight.\nIt is required to be `pie` to create a pie insight.", + "enum": [ + "pie" ] }, - "createPlan": { - "description": "This is the plan if you want us to create/import a new vector store using Trieve.", - "oneOf": [ - { - "$ref": "#/components/schemas/TrieveKnowledgeBaseImport", - "title": "Import" - } + "formulas": { + "type": "array", + "description": "Formulas are mathematical expressions applied on the data returned by the queries to transform them before being used to create the insight.\nThe formulas needs to be a valid mathematical expression, supported by MathJS - https://mathjs.org/docs/expressions/syntax.html\nA formula is created by using the query names as the variable.\nThe formulas must contain at least one query name in the LiquidJS format {{query_name}} or {{['query name']}} which will be substituted with the query result.\nFor example, if you have 2 queries, 'Was Booking Made' and 'Average Call Duration', you can create a formula like this:\n```\n{{['Query 1']}} / {{['Query 2']}} * 100\n```\n\n```\n({{[Query 1]}} * 10) + {{[Query 2]}}\n```\nThis will take the\n\nYou can also use the query names as the variable in the formula.", + "items": { + "$ref": "#/components/schemas/InsightFormula" + } + }, + "timeRange": { + "$ref": "#/components/schemas/InsightTimeRange" + }, + "groupBy": { + "type": "string", + "description": "This is the group by column for the insight when table is `call`.\nThese are the columns to group the results by.\nAll results are grouped by the time range step by default.", + "example": [ + "assistant_id" + ], + "enum": [ + "assistantId", + "workflowId", + "squadId", + "phoneNumberId", + "type", + "endedReason", + "customerNumber", + "campaignId", + "artifact.structuredOutputs[OutputID]" ] + }, + "queries": { + "type": "array", + "description": "These are the queries to run to generate the insight.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/JSONQueryOnCallTableWithStringTypeColumn", + "title": "JSONQueryOnCallTableWithStringTypeColumn" + }, + { + "$ref": "#/components/schemas/JSONQueryOnCallTableWithNumberTypeColumn", + "title": "JSONQueryOnCallTableWithNumberTypeColumn" + }, + { + "$ref": "#/components/schemas/JSONQueryOnCallTableWithStructuredOutputColumn", + "title": "JSONQueryOnCallTableWithStructuredOutputColumn" + } + ] + } } } }, - "UpdateCustomKnowledgeBaseDTO": { + "UpdateLineInsightFromCallTableDTO": { "type": "object", "properties": { - "server": { - "description": "This is where the knowledge base request will be sent.\n\nRequest Example:\n\nPOST https://{server.url}\nContent-Type: application/json\n\n{\n \"messsage\": {\n \"type\": \"knowledge-base-request\",\n \"messages\": [\n {\n \"role\": \"user\",\n \"content\": \"Why is ocean blue?\"\n }\n ],\n ...other metadata about the call...\n }\n}\n\nResponse Expected:\n```\n{\n \"message\": {\n \"role\": \"assistant\",\n \"content\": \"The ocean is blue because water absorbs everything but blue.\",\n }, // YOU CAN RETURN THE EXACT RESPONSE TO SPEAK\n \"documents\": [\n {\n \"content\": \"The ocean is blue primarily because water absorbs colors in the red part of the light spectrum and scatters the blue light, making it more visible to our eyes.\",\n \"similarity\": 1\n },\n {\n \"content\": \"Blue light is scattered more by the water molecules than other colors, enhancing the blue appearance of the ocean.\",\n \"similarity\": .5\n }\n ] // OR, YOU CAN RETURN AN ARRAY OF DOCUMENTS THAT WILL BE SENT TO THE MODEL\n}\n```", + "name": { + "type": "string", + "description": "This is the name of the Insight.", + "minLength": 1, + "maxLength": 255 + }, + "type": { + "type": "string", + "description": "This is the type of the Insight.\nIt is required to be `line` to create a line insight.", + "enum": [ + "line" + ] + }, + "formulas": { + "type": "array", + "description": "Formulas are mathematical expressions applied on the data returned by the queries to transform them before being used to create the insight.\nThe formulas needs to be a valid mathematical expression, supported by MathJS - https://mathjs.org/docs/expressions/syntax.html\nA formula is created by using the query names as the variable.\nThe formulas must contain at least one query name in the LiquidJS format {{query_name}} or {{['query name']}} which will be substituted with the query result.\nFor example, if you have 2 queries, 'Was Booking Made' and 'Average Call Duration', you can create a formula like this:\n```\n{{['Query 1']}} / {{['Query 2']}} * 100\n```\n\n```\n({{[Query 1]}} * 10) + {{[Query 2]}}\n```\nThis will take the\n\nYou can also use the query names as the variable in the formula.", + "items": { + "$ref": "#/components/schemas/InsightFormula" + } + }, + "metadata": { + "description": "This is the metadata for the insight.", "allOf": [ { - "$ref": "#/components/schemas/Server" + "$ref": "#/components/schemas/LineInsightMetadata" } ] - } - } - }, - "TrieveKnowledgeBaseChunkPlan": { - "type": "object", - "properties": { - "fileIds": { - "description": "These are the file ids that will be used to create the vector store. To upload files, use the `POST /files` endpoint.", - "type": "array", - "items": { - "type": "string" - } }, - "websites": { - "description": "These are the websites that will be used to create the vector store.", - "type": "array", + "timeRange": { + "$ref": "#/components/schemas/InsightTimeRangeWithStep" + }, + "groupBy": { + "type": "string", + "description": "This is the group by column for the insight when table is `call`.\nThese are the columns to group the results by.\nAll results are grouped by the time range step by default.", + "example": [ + "assistant_id" + ], + "enum": [ + "assistantId", + "workflowId", + "squadId", + "phoneNumberId", + "type", + "endedReason", + "customerNumber", + "campaignId", + "artifact.structuredOutputs[OutputID]" + ] + }, + "queries": { + "type": "array", + "description": "These are the queries to run to generate the insight.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/JSONQueryOnCallTableWithStringTypeColumn", + "title": "JSONQueryOnCallTableWithStringTypeColumn" + }, + { + "$ref": "#/components/schemas/JSONQueryOnCallTableWithNumberTypeColumn", + "title": "JSONQueryOnCallTableWithNumberTypeColumn" + }, + { + "$ref": "#/components/schemas/JSONQueryOnCallTableWithStructuredOutputColumn", + "title": "JSONQueryOnCallTableWithStructuredOutputColumn" + } + ] + } + } + } + }, + "UpdateTextInsightFromCallTableDTO": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "This is the name of the Insight.", + "minLength": 1, + "maxLength": 255 + }, + "type": { + "type": "string", + "description": "This is the type of the Insight.\nIt is required to be `text` to create a text insight.", + "enum": [ + "text" + ] + }, + "formula": { + "type": "object", + "description": "Formulas are mathematical expressions applied on the data returned by the queries to transform them before being used to create the insight.\nThe formulas needs to be a valid mathematical expression, supported by MathJS - https://mathjs.org/docs/expressions/syntax.html\nA formula is created by using the query names as the variable.\nThe formulas must contain at least one query name in the LiquidJS format {{query_name}} or {{['query name']}} which will be substituted with the query result.\nFor example, if you have 2 queries, 'Was Booking Made' and 'Average Call Duration', you can create a formula like this:\n```\n{{['Query 1']}} / {{['Query 2']}} * 100\n```\n\n```\n({{[Query 1]}} * 10) + {{[Query 2]}}\n```\nThis will take the\n\nYou can also use the query names as the variable in the formula.", "items": { - "type": "string" + "$ref": "#/components/schemas/InsightFormula" } }, - "targetSplitsPerChunk": { - "type": "number", - "description": "This is an optional field which allows you to specify the number of splits you want per chunk. If not specified, the default 20 is used. However, you may want to use a different number." + "timeRange": { + "$ref": "#/components/schemas/InsightTimeRange" }, - "splitDelimiters": { - "description": "This is an optional field which allows you to specify the delimiters to use when splitting the file before chunking the text. If not specified, the default [.!?\\n] are used to split into sentences. However, you may want to use spaces or other delimiters.", + "queries": { "type": "array", + "description": "These are the queries to run to generate the insight.\nFor Text Insights, we only allow a single query, or require a formula if multiple queries are provided", "items": { - "type": "string" + "oneOf": [ + { + "$ref": "#/components/schemas/JSONQueryOnCallTableWithStringTypeColumn", + "title": "JSONQueryOnCallTableWithStringTypeColumn" + }, + { + "$ref": "#/components/schemas/JSONQueryOnCallTableWithNumberTypeColumn", + "title": "JSONQueryOnCallTableWithNumberTypeColumn" + }, + { + "$ref": "#/components/schemas/JSONQueryOnCallTableWithStructuredOutputColumn", + "title": "JSONQueryOnCallTableWithStructuredOutputColumn" + } + ] } - }, - "rebalanceChunks": { - "type": "boolean", - "description": "This is an optional field which allows you to specify whether or not to rebalance the chunks created from the file. If not specified, the default true is used. If true, Trieve will evenly distribute remainder splits across chunks such that 66 splits with a target_splits_per_chunk of 20 will result in 3 chunks with 22 splits each." } } }, - "TrieveKnowledgeBaseCreate": { + "CreateBarInsightFromCallTableDTO": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "This is the name of the Insight.", + "minLength": 1, + "maxLength": 255 + }, "type": { "type": "string", - "description": "This is to create a new dataset on Trieve.", + "description": "This is the type of the Insight.\nIt is required to be `bar` to create a bar insight.", "enum": [ - "create" + "bar" ] }, - "chunkPlans": { - "description": "These are the chunk plans used to create the dataset.", + "formulas": { "type": "array", + "description": "Formulas are mathematical expressions applied on the data returned by the queries to transform them before being used to create the insight.\nThe formulas needs to be a valid mathematical expression, supported by MathJS - https://mathjs.org/docs/expressions/syntax.html\nA formula is created by using the query names as the variable.\nThe formulas must contain at least one query name in the LiquidJS format {{query_name}} or {{['query name']}} which will be substituted with the query result.\nFor example, if you have 2 queries, 'Was Booking Made' and 'Average Call Duration', you can create a formula like this:\n```\n{{['Query 1']}} / {{['Query 2']}} * 100\n```\n\n```\n({{[Query 1]}} * 10) + {{[Query 2]}}\n```\nThis will take the\n\nYou can also use the query names as the variable in the formula.", "items": { - "$ref": "#/components/schemas/TrieveKnowledgeBaseChunkPlan" + "$ref": "#/components/schemas/InsightFormula" + } + }, + "metadata": { + "description": "This is the metadata for the insight.", + "allOf": [ + { + "$ref": "#/components/schemas/BarInsightMetadata" + } + ] + }, + "timeRange": { + "$ref": "#/components/schemas/InsightTimeRangeWithStep" + }, + "groupBy": { + "type": "string", + "description": "This is the group by column for the insight when table is `call`.\nThese are the columns to group the results by.\nAll results are grouped by the time range step by default.", + "example": [ + "assistant_id" + ], + "enum": [ + "assistantId", + "workflowId", + "squadId", + "phoneNumberId", + "type", + "endedReason", + "customerNumber", + "campaignId", + "artifact.structuredOutputs[OutputID]" + ] + }, + "queries": { + "type": "array", + "description": "These are the queries to run to generate the insight.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/JSONQueryOnCallTableWithStringTypeColumn", + "title": "JSONQueryOnCallTableWithStringTypeColumn" + }, + { + "$ref": "#/components/schemas/JSONQueryOnCallTableWithNumberTypeColumn", + "title": "JSONQueryOnCallTableWithNumberTypeColumn" + }, + { + "$ref": "#/components/schemas/JSONQueryOnCallTableWithStructuredOutputColumn", + "title": "JSONQueryOnCallTableWithStructuredOutputColumn" + }, + { + "$ref": "#/components/schemas/JSONQueryOnEventsTable", + "title": "JSONQueryOnEventsTable" + } + ] } } }, "required": [ "type", - "chunkPlans" + "queries" ] }, - "TrieveKnowledgeBaseImport": { + "CreatePieInsightFromCallTableDTO": { "type": "object", "properties": { + "name": { + "type": "string", + "description": "This is the name of the Insight.", + "minLength": 1, + "maxLength": 255 + }, "type": { "type": "string", - "description": "This is to import an existing dataset from Trieve.", + "description": "This is the type of the Insight.\nIt is required to be `pie` to create a pie insight.", "enum": [ - "import" + "pie" ] }, - "providerId": { + "formulas": { + "type": "array", + "description": "Formulas are mathematical expressions applied on the data returned by the queries to transform them before being used to create the insight.\nThe formulas needs to be a valid mathematical expression, supported by MathJS - https://mathjs.org/docs/expressions/syntax.html\nA formula is created by using the query names as the variable.\nThe formulas must contain at least one query name in the LiquidJS format {{query_name}} or {{['query name']}} which will be substituted with the query result.\nFor example, if you have 2 queries, 'Was Booking Made' and 'Average Call Duration', you can create a formula like this:\n```\n{{['Query 1']}} / {{['Query 2']}} * 100\n```\n\n```\n({{[Query 1]}} * 10) + {{[Query 2]}}\n```\nThis will take the\n\nYou can also use the query names as the variable in the formula.", + "items": { + "$ref": "#/components/schemas/InsightFormula" + } + }, + "timeRange": { + "$ref": "#/components/schemas/InsightTimeRange" + }, + "groupBy": { "type": "string", - "description": "This is the `datasetId` of the dataset on your Trieve account." - } - }, - "required": [ - "type", - "providerId" - ] - }, - "Workflow": { - "type": "object", - "properties": { - "nodes": { + "description": "This is the group by column for the insight when table is `call`.\nThese are the columns to group the results by.\nAll results are grouped by the time range step by default.", + "example": [ + "assistant_id" + ], + "enum": [ + "assistantId", + "workflowId", + "squadId", + "phoneNumberId", + "type", + "endedReason", + "customerNumber", + "campaignId", + "artifact.structuredOutputs[OutputID]" + ] + }, + "queries": { "type": "array", + "description": "These are the queries to run to generate the insight.", "items": { "oneOf": [ { - "$ref": "#/components/schemas/ConversationNode", - "title": "ConversationNode" + "$ref": "#/components/schemas/JSONQueryOnCallTableWithStringTypeColumn", + "title": "JSONQueryOnCallTableWithStringTypeColumn" }, { - "$ref": "#/components/schemas/ToolNode", - "title": "ToolNode" + "$ref": "#/components/schemas/JSONQueryOnCallTableWithNumberTypeColumn", + "title": "JSONQueryOnCallTableWithNumberTypeColumn" + }, + { + "$ref": "#/components/schemas/JSONQueryOnCallTableWithStructuredOutputColumn", + "title": "JSONQueryOnCallTableWithStructuredOutputColumn" } ] } + } + }, + "required": [ + "type", + "queries" + ] + }, + "CreateLineInsightFromCallTableDTO": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "This is the name of the Insight.", + "minLength": 1, + "maxLength": 255 }, - "model": { - "description": "This is the model for the workflow.\n\nThis can be overridden at node level using `nodes[n].model`.", - "oneOf": [ - { - "$ref": "#/components/schemas/WorkflowOpenAIModel", - "title": "WorkflowOpenAIModel" - }, - { - "$ref": "#/components/schemas/WorkflowAnthropicModel", - "title": "WorkflowAnthropicModel" - }, - { - "$ref": "#/components/schemas/WorkflowGoogleModel", - "title": "WorkflowGoogleModel" - }, - { - "$ref": "#/components/schemas/WorkflowCustomModel", - "title": "WorkflowCustomModel" - } - ] - }, - "transcriber": { - "description": "This is the transcriber for the workflow.\n\nThis can be overridden at node level using `nodes[n].transcriber`.", - "oneOf": [ - { - "$ref": "#/components/schemas/AssemblyAITranscriber", - "title": "AssemblyAITranscriber" - }, - { - "$ref": "#/components/schemas/AzureSpeechTranscriber", - "title": "AzureSpeechTranscriber" - }, - { - "$ref": "#/components/schemas/CustomTranscriber", - "title": "CustomTranscriber" - }, - { - "$ref": "#/components/schemas/DeepgramTranscriber", - "title": "DeepgramTranscriber" - }, - { - "$ref": "#/components/schemas/ElevenLabsTranscriber", - "title": "ElevenLabsTranscriber" - }, - { - "$ref": "#/components/schemas/GladiaTranscriber", - "title": "GladiaTranscriber" - }, - { - "$ref": "#/components/schemas/GoogleTranscriber", - "title": "GoogleTranscriber" - }, - { - "$ref": "#/components/schemas/SpeechmaticsTranscriber", - "title": "SpeechmaticsTranscriber" - }, - { - "$ref": "#/components/schemas/TalkscriberTranscriber", - "title": "TalkscriberTranscriber" - }, - { - "$ref": "#/components/schemas/OpenAITranscriber", - "title": "OpenAITranscriber" - }, - { - "$ref": "#/components/schemas/CartesiaTranscriber", - "title": "CartesiaTranscriber" - } + "type": { + "type": "string", + "description": "This is the type of the Insight.\nIt is required to be `line` to create a line insight.", + "enum": [ + "line" ] }, - "voice": { - "description": "This is the voice for the workflow.\n\nThis can be overridden at node level using `nodes[n].voice`.", - "oneOf": [ - { - "$ref": "#/components/schemas/AzureVoice", - "title": "AzureVoice" - }, - { - "$ref": "#/components/schemas/CartesiaVoice", - "title": "CartesiaVoice" - }, - { - "$ref": "#/components/schemas/CustomVoice", - "title": "CustomVoice" - }, - { - "$ref": "#/components/schemas/DeepgramVoice", - "title": "DeepgramVoice" - }, - { - "$ref": "#/components/schemas/ElevenLabsVoice", - "title": "ElevenLabsVoice" - }, - { - "$ref": "#/components/schemas/HumeVoice", - "title": "HumeVoice" - }, - { - "$ref": "#/components/schemas/LMNTVoice", - "title": "LMNTVoice" - }, - { - "$ref": "#/components/schemas/NeuphonicVoice", - "title": "NeuphonicVoice" - }, - { - "$ref": "#/components/schemas/OpenAIVoice", - "title": "OpenAIVoice" - }, - { - "$ref": "#/components/schemas/PlayHTVoice", - "title": "PlayHTVoice" - }, - { - "$ref": "#/components/schemas/RimeAIVoice", - "title": "RimeAIVoice" - }, - { - "$ref": "#/components/schemas/SmallestAIVoice", - "title": "SmallestAIVoice" - }, - { - "$ref": "#/components/schemas/TavusVoice", - "title": "TavusVoice" - }, - { - "$ref": "#/components/schemas/VapiVoice", - "title": "VapiVoice" - }, - { - "$ref": "#/components/schemas/SesameVoice", - "title": "SesameVoice" - }, - { - "$ref": "#/components/schemas/InworldVoice", - "title": "InworldVoice" - }, - { - "$ref": "#/components/schemas/MinimaxVoice", - "title": "MinimaxVoice" - } - ] + "formulas": { + "type": "array", + "description": "Formulas are mathematical expressions applied on the data returned by the queries to transform them before being used to create the insight.\nThe formulas needs to be a valid mathematical expression, supported by MathJS - https://mathjs.org/docs/expressions/syntax.html\nA formula is created by using the query names as the variable.\nThe formulas must contain at least one query name in the LiquidJS format {{query_name}} or {{['query name']}} which will be substituted with the query result.\nFor example, if you have 2 queries, 'Was Booking Made' and 'Average Call Duration', you can create a formula like this:\n```\n{{['Query 1']}} / {{['Query 2']}} * 100\n```\n\n```\n({{[Query 1]}} * 10) + {{[Query 2]}}\n```\nThis will take the\n\nYou can also use the query names as the variable in the formula.", + "items": { + "$ref": "#/components/schemas/InsightFormula" + } }, - "observabilityPlan": { - "description": "This is the plan for observability of workflow's calls.\n\nCurrently, only Langfuse is supported.", - "oneOf": [ - { - "$ref": "#/components/schemas/LangfuseObservabilityPlan", - "title": "Langfuse" - } - ], + "metadata": { + "description": "This is the metadata for the insight.", "allOf": [ { - "$ref": "#/components/schemas/LangfuseObservabilityPlan" + "$ref": "#/components/schemas/LineInsightMetadata" } ] }, - "backgroundSound": { - "description": "This is the background sound in the call. Default for phone calls is 'office' and default for web calls is 'off'.\nYou can also provide a custom sound by providing a URL to an audio file.", - "oneOf": [ - { - "type": "enum", - "enum": [ - "off", - "office" - ], - "example": "office" - }, - { - "type": "string", - "format": "uri", - "example": "https://www.soundjay.com/ambient/sounds/people-in-lounge-1.mp3" - } + "timeRange": { + "$ref": "#/components/schemas/InsightTimeRangeWithStep" + }, + "groupBy": { + "type": "string", + "description": "This is the group by column for the insight when table is `call`.\nThese are the columns to group the results by.\nAll results are grouped by the time range step by default.", + "example": [ + "assistant_id" + ], + "enum": [ + "assistantId", + "workflowId", + "squadId", + "phoneNumberId", + "type", + "endedReason", + "customerNumber", + "campaignId", + "artifact.structuredOutputs[OutputID]" ] }, - "hooks": { + "queries": { "type": "array", - "description": "This is a set of actions that will be performed on certain events.", + "description": "These are the queries to run to generate the insight.", "items": { "oneOf": [ { - "$ref": "#/components/schemas/CallHookCallEnding", - "title": "CallHookCallEnding" - }, - { - "$ref": "#/components/schemas/CallHookAssistantSpeechInterrupted", - "title": "CallHookAssistantSpeechInterrupted" + "$ref": "#/components/schemas/JSONQueryOnCallTableWithStringTypeColumn", + "title": "JSONQueryOnCallTableWithStringTypeColumn" }, { - "$ref": "#/components/schemas/CallHookCustomerSpeechInterrupted", - "title": "CallHookCustomerSpeechInterrupted" + "$ref": "#/components/schemas/JSONQueryOnCallTableWithNumberTypeColumn", + "title": "JSONQueryOnCallTableWithNumberTypeColumn" }, { - "$ref": "#/components/schemas/CallHookCustomerSpeechTimeout", - "title": "CallHookCustomerSpeechTimeout" + "$ref": "#/components/schemas/JSONQueryOnCallTableWithStructuredOutputColumn", + "title": "JSONQueryOnCallTableWithStructuredOutputColumn" } ] } + } + }, + "required": [ + "type", + "queries" + ] + }, + "CreateTextInsightFromCallTableDTO": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "This is the name of the Insight.", + "minLength": 1, + "maxLength": 255 + }, + "type": { + "type": "string", + "description": "This is the type of the Insight.\nIt is required to be `text` to create a text insight.", + "enum": [ + "text" + ] + }, + "formula": { + "type": "object", + "description": "Formulas are mathematical expressions applied on the data returned by the queries to transform them before being used to create the insight.\nThe formulas needs to be a valid mathematical expression, supported by MathJS - https://mathjs.org/docs/expressions/syntax.html\nA formula is created by using the query names as the variable.\nThe formulas must contain at least one query name in the LiquidJS format {{query_name}} or {{['query name']}} which will be substituted with the query result.\nFor example, if you have 2 queries, 'Was Booking Made' and 'Average Call Duration', you can create a formula like this:\n```\n{{['Query 1']}} / {{['Query 2']}} * 100\n```\n\n```\n({{[Query 1]}} * 10) + {{[Query 2]}}\n```\nThis will take the\n\nYou can also use the query names as the variable in the formula.", + "items": { + "$ref": "#/components/schemas/InsightFormula" + } }, - "credentials": { + "timeRange": { + "$ref": "#/components/schemas/InsightTimeRange" + }, + "queries": { "type": "array", - "description": "These are dynamic credentials that will be used for the workflow calls. By default, all the credentials are available for use in the call but you can supplement an additional credentials using this. Dynamic credentials override existing credentials.", + "description": "These are the queries to run to generate the insight.\nFor Text Insights, we only allow a single query, or require a formula if multiple queries are provided", "items": { "oneOf": [ { - "$ref": "#/components/schemas/CreateAnthropicCredentialDTO", - "title": "AnthropicCredential" - }, - { - "$ref": "#/components/schemas/CreateAnyscaleCredentialDTO", - "title": "AnyscaleCredential" - }, - { - "$ref": "#/components/schemas/CreateAssemblyAICredentialDTO", - "title": "AssemblyAICredential" - }, - { - "$ref": "#/components/schemas/CreateAzureCredentialDTO", - "title": "AzureCredential" - }, - { - "$ref": "#/components/schemas/CreateAzureOpenAICredentialDTO", - "title": "AzureOpenAICredential" - }, - { - "$ref": "#/components/schemas/CreateByoSipTrunkCredentialDTO", - "title": "ByoSipTrunkCredential" - }, - { - "$ref": "#/components/schemas/CreateCartesiaCredentialDTO", - "title": "CartesiaCredential" - }, - { - "$ref": "#/components/schemas/CreateCerebrasCredentialDTO", - "title": "CerebrasCredential" - }, - { - "$ref": "#/components/schemas/CreateCloudflareCredentialDTO", - "title": "CloudflareCredential" - }, - { - "$ref": "#/components/schemas/CreateCustomLLMCredentialDTO", - "title": "CustomLLMCredential" - }, - { - "$ref": "#/components/schemas/CreateDeepgramCredentialDTO", - "title": "DeepgramCredential" - }, - { - "$ref": "#/components/schemas/CreateDeepInfraCredentialDTO", - "title": "DeepInfraCredential" - }, - { - "$ref": "#/components/schemas/CreateDeepSeekCredentialDTO", - "title": "DeepSeekCredential" - }, - { - "$ref": "#/components/schemas/CreateElevenLabsCredentialDTO", - "title": "ElevenLabsCredential" - }, - { - "$ref": "#/components/schemas/CreateGcpCredentialDTO", - "title": "GcpCredential" - }, - { - "$ref": "#/components/schemas/CreateGladiaCredentialDTO", - "title": "GladiaCredential" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelCredentialDTO", - "title": "GhlCredential" - }, - { - "$ref": "#/components/schemas/CreateGoogleCredentialDTO", - "title": "GoogleCredential" - }, - { - "$ref": "#/components/schemas/CreateGroqCredentialDTO", - "title": "GroqCredential" - }, - { - "$ref": "#/components/schemas/CreateHumeCredentialDTO", - "title": "HumeCredential" - }, - { - "$ref": "#/components/schemas/CreateInflectionAICredentialDTO", - "title": "InflectionAICredential" - }, - { - "$ref": "#/components/schemas/CreateLangfuseCredentialDTO", - "title": "LangfuseCredential" - }, - { - "$ref": "#/components/schemas/CreateLmntCredentialDTO", - "title": "LmntCredential" - }, - { - "$ref": "#/components/schemas/CreateMakeCredentialDTO", - "title": "MakeCredential" - }, - { - "$ref": "#/components/schemas/CreateMistralCredentialDTO", - "title": "MistralCredential" - }, - { - "$ref": "#/components/schemas/CreateNeuphonicCredentialDTO", - "title": "NeuphonicCredential" - }, - { - "$ref": "#/components/schemas/CreateOpenAICredentialDTO", - "title": "OpenAICredential" - }, - { - "$ref": "#/components/schemas/CreateOpenRouterCredentialDTO", - "title": "OpenRouterCredential" - }, - { - "$ref": "#/components/schemas/CreatePerplexityAICredentialDTO", - "title": "PerplexityAICredential" + "$ref": "#/components/schemas/JSONQueryOnCallTableWithStringTypeColumn", + "title": "JSONQueryOnCallTableWithStringTypeColumn" }, { - "$ref": "#/components/schemas/CreatePlayHTCredentialDTO", - "title": "PlayHTCredential" + "$ref": "#/components/schemas/JSONQueryOnCallTableWithNumberTypeColumn", + "title": "JSONQueryOnCallTableWithNumberTypeColumn" }, { - "$ref": "#/components/schemas/CreateRimeAICredentialDTO", - "title": "RimeAICredential" - }, + "$ref": "#/components/schemas/JSONQueryOnCallTableWithStructuredOutputColumn", + "title": "JSONQueryOnCallTableWithStructuredOutputColumn" + } + ] + } + } + }, + "required": [ + "type", + "queries" + ] + }, + "JSONQueryOnCallTableWithStringTypeColumn": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "This is the type of query. Only allowed type is \"vapiql-json\".", + "example": "vapiql-json", + "enum": [ + "vapiql-json" + ] + }, + "table": { + "type": "string", + "description": "This is the table that will be queried.", + "enum": [ + "call" + ] + }, + "filters": { + "type": "array", + "description": "This is the filters to apply to the insight.\nThe discriminator automatically selects the correct filter type based on column and operator.", + "items": { + "oneOf": [ { - "$ref": "#/components/schemas/CreateRunpodCredentialDTO", - "title": "RunpodCredential" + "$ref": "#/components/schemas/FilterStringTypeColumnOnCallTable" }, { - "$ref": "#/components/schemas/CreateS3CredentialDTO", - "title": "S3Credential" + "$ref": "#/components/schemas/FilterStringArrayTypeColumnOnCallTable" }, { - "$ref": "#/components/schemas/CreateSmallestAICredentialDTO", - "title": "SmallestAICredential" + "$ref": "#/components/schemas/FilterNumberTypeColumnOnCallTable" }, { - "$ref": "#/components/schemas/CreateSpeechmaticsCredentialDTO", - "title": "SpeechmaticsCredential" + "$ref": "#/components/schemas/FilterNumberArrayTypeColumnOnCallTable" }, { - "$ref": "#/components/schemas/CreateSupabaseCredentialDTO", - "title": "SupabaseCredential" + "$ref": "#/components/schemas/FilterDateTypeColumnOnCallTable" }, { - "$ref": "#/components/schemas/CreateTavusCredentialDTO", - "title": "TavusCredential" - }, + "$ref": "#/components/schemas/FilterStructuredOutputColumnOnCallTable" + } + ] + } + }, + "column": { + "type": "string", + "enum": [ + "id", + "artifact.structuredOutputs[OutputID]" + ], + "description": "This is the column that will be queried in the selected table.\nAvailable columns depend on the selected table.\nString Type columns are columns where the rows store String data", + "example": "id" + }, + "operation": { + "type": "string", + "enum": [ + "count" + ], + "description": "This is the aggregation operation to perform on the column.\nWhen the column is a string type, the operation must be \"count\".", + "example": "count" + }, + "name": { + "type": "string", + "description": "This is the name of the query.\nIt will be used to label the query in the insight board on the UI.", + "example": "Total Calls" + } + }, + "required": [ + "type", + "table", + "column", + "operation" + ] + }, + "JSONQueryOnCallTableWithNumberTypeColumn": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "This is the type of query. Only allowed type is \"vapiql-json\".", + "example": "vapiql-json", + "enum": [ + "vapiql-json" + ] + }, + "table": { + "type": "string", + "description": "This is the table that will be queried.", + "enum": [ + "call" + ] + }, + "filters": { + "type": "array", + "description": "This is the filters to apply to the insight.\nThe discriminator automatically selects the correct filter type based on column and operator.", + "items": { + "oneOf": [ { - "$ref": "#/components/schemas/CreateTogetherAICredentialDTO", - "title": "TogetherAICredential" + "$ref": "#/components/schemas/FilterStringTypeColumnOnCallTable" }, { - "$ref": "#/components/schemas/CreateTrieveCredentialDTO", - "title": "TrieveCredential" + "$ref": "#/components/schemas/FilterStringArrayTypeColumnOnCallTable" }, { - "$ref": "#/components/schemas/CreateTwilioCredentialDTO", - "title": "TwilioCredential" + "$ref": "#/components/schemas/FilterNumberTypeColumnOnCallTable" }, { - "$ref": "#/components/schemas/CreateVonageCredentialDTO", - "title": "VonageCredential" + "$ref": "#/components/schemas/FilterNumberArrayTypeColumnOnCallTable" }, { - "$ref": "#/components/schemas/CreateWebhookCredentialDTO", - "title": "WebhookCredential" + "$ref": "#/components/schemas/FilterDateTypeColumnOnCallTable" }, { - "$ref": "#/components/schemas/CreateXAiCredentialDTO", - "title": "XAiCredential" - }, + "$ref": "#/components/schemas/FilterStructuredOutputColumnOnCallTable" + } + ] + } + }, + "column": { + "type": "string", + "enum": [ + "cost", + "duration", + "averageModelLatency", + "averageVoiceLatency", + "averageTranscriberLatency", + "averageTurnLatency", + "averageEndpointingLatency", + "artifact.structuredOutputs[OutputID]" + ], + "description": "This is the column that will be queried in the selected table.\nAvailable columns depend on the selected table.\nNumber Type columns are columns where the rows store Number data", + "example": "duration" + }, + "operation": { + "type": "string", + "enum": [ + "average", + "sum", + "min", + "max" + ], + "description": "This is the aggregation operation to perform on the column.\nWhen the column is a number type, the operation must be one of the following:\n- average\n- sum\n- min\n- max", + "example": "sum" + }, + "name": { + "type": "string", + "description": "This is the name of the query.\nIt will be used to label the query in the insight board on the UI.", + "example": "Total Calls" + } + }, + "required": [ + "type", + "table", + "column", + "operation" + ] + }, + "JSONQueryOnCallTableWithStructuredOutputColumn": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "This is the type of query. Only allowed type is \"vapiql-json\".", + "example": "vapiql-json", + "enum": [ + "vapiql-json" + ] + }, + "table": { + "type": "string", + "description": "This is the table that will be queried.", + "enum": [ + "call" + ] + }, + "filters": { + "type": "array", + "description": "This is the filters to apply to the insight.\nThe discriminator automatically selects the correct filter type based on column and operator.", + "items": { + "oneOf": [ { - "$ref": "#/components/schemas/CreateGoogleCalendarOAuth2ClientCredentialDTO", - "title": "GoogleCalendarOAuth2ClientCredential" + "$ref": "#/components/schemas/FilterStringTypeColumnOnCallTable" }, { - "$ref": "#/components/schemas/CreateGoogleCalendarOAuth2AuthorizationCredentialDTO", - "title": "GoogleCalendarOAuth2AuthorizationCredential" + "$ref": "#/components/schemas/FilterStringArrayTypeColumnOnCallTable" }, { - "$ref": "#/components/schemas/CreateGoogleSheetsOAuth2AuthorizationCredentialDTO", - "title": "GoogleSheetsOAuth2AuthorizationCredential" + "$ref": "#/components/schemas/FilterNumberTypeColumnOnCallTable" }, { - "$ref": "#/components/schemas/CreateSlackOAuth2AuthorizationCredentialDTO", - "title": "SlackOAuth2AuthorizationCredential" + "$ref": "#/components/schemas/FilterNumberArrayTypeColumnOnCallTable" }, { - "$ref": "#/components/schemas/CreateGoHighLevelMCPCredentialDTO", - "title": "GoHighLevelMCPCredential" + "$ref": "#/components/schemas/FilterDateTypeColumnOnCallTable" }, { - "$ref": "#/components/schemas/CreateInworldCredentialDTO", - "title": "InworldCredential" - } - ], - "discriminator": { - "propertyName": "provider", - "mapping": { - "11labs": "#/components/schemas/CreateElevenLabsCredentialDTO", - "anthropic": "#/components/schemas/CreateAnthropicCredentialDTO", - "anyscale": "#/components/schemas/CreateAnyscaleCredentialDTO", - "assembly-ai": "#/components/schemas/CreateAssemblyAICredentialDTO", - "azure-openai": "#/components/schemas/CreateAzureOpenAICredentialDTO", - "azure": "#/components/schemas/CreateAzureCredentialDTO", - "byo-sip-trunk": "#/components/schemas/CreateByoSipTrunkCredentialDTO", - "cartesia": "#/components/schemas/CreateCartesiaCredentialDTO", - "cerebras": "#/components/schemas/CreateCerebrasCredentialDTO", - "cloudflare": "#/components/schemas/CreateCloudflareCredentialDTO", - "custom-llm": "#/components/schemas/CreateCustomLLMCredentialDTO", - "deepgram": "#/components/schemas/CreateDeepgramCredentialDTO", - "deepinfra": "#/components/schemas/CreateDeepInfraCredentialDTO", - "deep-seek": "#/components/schemas/CreateDeepSeekCredentialDTO", - "gcp": "#/components/schemas/CreateGcpCredentialDTO", - "gladia": "#/components/schemas/CreateGladiaCredentialDTO", - "gohighlevel": "#/components/schemas/CreateGoHighLevelCredentialDTO", - "google": "#/components/schemas/CreateGoogleCredentialDTO", - "groq": "#/components/schemas/CreateGroqCredentialDTO", - "inflection-ai": "#/components/schemas/CreateInflectionAICredentialDTO", - "langfuse": "#/components/schemas/CreateLangfuseCredentialDTO", - "lmnt": "#/components/schemas/CreateLmntCredentialDTO", - "make": "#/components/schemas/CreateMakeCredentialDTO", - "openai": "#/components/schemas/CreateOpenAICredentialDTO", - "openrouter": "#/components/schemas/CreateOpenRouterCredentialDTO", - "perplexity-ai": "#/components/schemas/CreatePerplexityAICredentialDTO", - "playht": "#/components/schemas/CreatePlayHTCredentialDTO", - "rime-ai": "#/components/schemas/CreateRimeAICredentialDTO", - "runpod": "#/components/schemas/CreateRunpodCredentialDTO", - "s3": "#/components/schemas/CreateS3CredentialDTO", - "supabase": "#/components/schemas/CreateSupabaseCredentialDTO", - "smallest-ai": "#/components/schemas/CreateSmallestAICredentialDTO", - "tavus": "#/components/schemas/CreateTavusCredentialDTO", - "together-ai": "#/components/schemas/CreateTogetherAICredentialDTO", - "twilio": "#/components/schemas/CreateTwilioCredentialDTO", - "vonage": "#/components/schemas/CreateVonageCredentialDTO", - "webhook": "#/components/schemas/CreateWebhookCredentialDTO", - "xai": "#/components/schemas/CreateXAiCredentialDTO", - "neuphonic": "#/components/schemas/CreateNeuphonicCredentialDTO", - "hume": "#/components/schemas/CreateHumeCredentialDTO", - "mistral": "#/components/schemas/CreateMistralCredentialDTO", - "speechmatics": "#/components/schemas/CreateSpeechmaticsCredentialDTO", - "trieve": "#/components/schemas/CreateTrieveCredentialDTO", - "google.calendar.oauth2-client": "#/components/schemas/CreateGoogleCalendarOAuth2ClientCredentialDTO", - "google.calendar.oauth2-authorization": "#/components/schemas/CreateGoogleCalendarOAuth2AuthorizationCredentialDTO", - "google.sheets.oauth2-authorization": "#/components/schemas/CreateGoogleSheetsOAuth2AuthorizationCredentialDTO", - "slack.oauth2-authorization": "#/components/schemas/CreateSlackOAuth2AuthorizationCredentialDTO", - "ghl.oauth2-authorization": "#/components/schemas/CreateGoHighLevelMCPCredentialDTO", - "inworld": "#/components/schemas/CreateInworldCredentialDTO", - "minimax": "#/components/schemas/CreateMinimaxCredentialDTO" + "$ref": "#/components/schemas/FilterStructuredOutputColumnOnCallTable" } - } + ] } }, - "id": { - "type": "string" + "column": { + "type": "string", + "enum": [ + "artifact.structuredOutputs[OutputID]" + ], + "description": "This is the column that will be queried in the call table.\nStructured Output Type columns are only to query on artifact.structuredOutputs[OutputID] column.", + "example": "artifact.structuredOutputs[OutputID]" }, - "orgId": { - "type": "string" + "operation": { + "type": "string", + "enum": [ + "average", + "count", + "sum", + "min", + "max" + ], + "description": "This is the aggregation operation to perform on the column.\nWhen the column is a structured output type, the operation depends on the value of the structured output.\nIf the structured output is a string or boolean, the operation must be \"count\".\nIf the structured output is a number, the operation can be \"average\", \"sum\", \"min\", or \"max\".", + "example": "count" }, - "createdAt": { - "format": "date-time", - "type": "string" + "name": { + "type": "string", + "description": "This is the name of the query.\nIt will be used to label the query in the insight board on the UI.", + "example": "Total Calls" + } + }, + "required": [ + "type", + "table", + "column", + "operation" + ] + }, + "JSONQueryOnEventsTable": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "This is the type of query. Only allowed type is \"vapiql-json\".", + "example": "vapiql-json", + "enum": [ + "vapiql-json" + ] }, - "updatedAt": { - "format": "date-time", - "type": "string" + "table": { + "type": "string", + "description": "This is the table that will be queried.\nMust be \"events\" for event-based insights.", + "enum": [ + "events" + ] }, - "name": { + "on": { "type": "string", - "maxLength": 80 + "description": "The event type to query", + "example": "assistant.model.requestFailed", + "enum": [ + "call.started", + "call.ended", + "call.inProgress", + "call.queued", + "call.transportConnected", + "call.transportDisconnected", + "call.transportReconnected", + "call.transferInitiated", + "call.transferCompleted", + "call.transferFailed", + "call.transferCancelled", + "call.handoffInitiated", + "call.handoffCompleted", + "call.handoffFailed", + "call.assistantSwapped", + "call.assistantStarted", + "call.customerJoined", + "call.customerLeft", + "call.controlReceived", + "call.listenStarted", + "call.recordingStarted", + "call.recordingPaused", + "call.recordingResumed", + "call.voicemailDetected", + "call.voicemailNotDetected", + "call.dtmfReceived", + "call.dtmfSent", + "call.amdDetected", + "call.hookTriggered", + "call.hookSucceeded", + "call.hookFailed", + "call.statusReceived", + "call.silenceTimeout", + "call.microphoneTimeout", + "call.maxDurationReached", + "assistant.voice.requestStarted", + "assistant.voice.requestSucceeded", + "assistant.voice.requestFailed", + "assistant.voice.connectionOpened", + "assistant.voice.connectionClosed", + "assistant.voice.firstAudioReceived", + "assistant.voice.audioChunkReceived", + "assistant.voice.generationSucceeded", + "assistant.voice.generationFailed", + "assistant.voice.textPushed", + "assistant.voice.reconnecting", + "assistant.voice.cleanup", + "assistant.voice.clearing", + "assistant.voice.voiceSwitched", + "assistant.model.requestStarted", + "assistant.model.requestSucceeded", + "assistant.model.requestFailed", + "assistant.model.requestAttemptStarted", + "assistant.model.requestAttemptSucceeded", + "assistant.model.requestAttemptFailed", + "assistant.model.connectionOpened", + "assistant.model.connectionClosed", + "assistant.model.firstTokenReceived", + "assistant.model.tokenReceived", + "assistant.model.responseSucceeded", + "assistant.model.responseFailed", + "assistant.model.toolCallsReceived", + "assistant.model.reconnecting", + "assistant.model.cleanup", + "assistant.model.clearing", + "assistant.tool.started", + "assistant.tool.completed", + "assistant.tool.failed", + "assistant.tool.delayedMessageSent", + "assistant.tool.timeout", + "assistant.tool.asyncCallbackReceived", + "assistant.transcriber.requestStarted", + "assistant.transcriber.requestSucceeded", + "assistant.transcriber.requestFailed", + "assistant.transcriber.connectionOpened", + "assistant.transcriber.connectionClosed", + "assistant.transcriber.partialTranscript", + "assistant.transcriber.finalTranscript", + "assistant.transcriber.keepAlive", + "assistant.transcriber.reconnecting", + "assistant.transcriber.cleanup", + "assistant.transcriber.clearing", + "assistant.transcriber.transcriptIgnored", + "assistant.transcriber.languageSwitched", + "assistant.analysis.structuredOutputRequest", + "assistant.analysis.structuredOutputResponse", + "assistant.analysis.structuredOutputError", + "assistant.analysis.structuredOutputGenerated", + "assistant.analysis.structuredOutputSkipped", + "pipeline.turnStarted", + "pipeline.cleared", + "pipeline.botSpeechStarted", + "pipeline.botSpeechStopped", + "pipeline.userSpeechStarted", + "pipeline.userSpeechStopped", + "pipeline.endpointingTriggered", + "pipeline.firstMessageStarted", + "pipeline.firstMessageCompleted" + ] }, - "edges": { + "operation": { + "type": "string", + "description": "This is the operation to perform on matching events.\n- \"count\": Returns the raw count of matching events\n- \"percentage\": Returns (count of matching events / total calls) * 100", + "example": "count", + "enum": [ + "count", + "percentage" + ] + }, + "filters": { "type": "array", + "description": "These are the filters to apply to the events query.\nEach filter filters on a field specific to the event type.", "items": { - "$ref": "#/components/schemas/Edge" + "oneOf": [ + { + "$ref": "#/components/schemas/EventsTableStringCondition" + }, + { + "$ref": "#/components/schemas/EventsTableNumberCondition" + }, + { + "$ref": "#/components/schemas/EventsTableBooleanCondition" + } + ] } }, - "globalPrompt": { + "name": { "type": "string", - "maxLength": 5000 + "description": "This is the name of the query.\nIt will be used to label the query in the insight board on the UI.", + "example": "Model Failures" + } + }, + "required": [ + "type", + "table", + "on", + "operation" + ] + }, + "FilterStringTypeColumnOnCallTable": { + "type": "object", + "properties": { + "column": { + "type": "string", + "description": "This is the column in the call table that will be filtered on.\nString Type columns are columns where the rows store data as a string.\nMust be a valid column for the selected table.", + "example": "assistant_id", + "enum": [ + "assistantId", + "workflowId", + "squadId", + "phoneNumberId", + "type", + "customerNumber", + "status", + "endedReason", + "forwardedPhoneNumber", + "campaignId" + ] }, - "server": { - "description": "This is where Vapi will send webhooks. You can find all webhooks available along with their shape in ServerMessage schema.\n\nThe order of precedence is:\n\n1. tool.server\n2. workflow.server / assistant.server\n3. phoneNumber.server\n4. org.server", - "allOf": [ - { - "$ref": "#/components/schemas/Server" - } + "operator": { + "type": "string", + "description": "This is the operator to use for the filter.\nFor string type columns, the operator must be \"=\", \"!=\", \"contains\", \"not contains\"", + "example": "\"=\" or \"!=\"", + "enum": [ + "=", + "!=", + "contains", + "not_contains" ] }, - "compliancePlan": { - "description": "This is the compliance plan for the workflow. It allows you to configure HIPAA and other compliance settings.", - "allOf": [ - { - "$ref": "#/components/schemas/CompliancePlan" - } + "value": { + "type": "string", + "description": "This is the value to filter on." + } + }, + "required": [ + "column", + "operator", + "value" + ] + }, + "FilterNumberTypeColumnOnCallTable": { + "type": "object", + "properties": { + "column": { + "type": "string", + "description": "This is the column in the call table that will be filtered on.\nNumber Type columns are columns where the rows store data as a number.\nMust be a valid column for the selected table.", + "example": "duration", + "enum": [ + "duration", + "cost", + "averageModelLatency", + "averageVoiceLatency", + "averageTranscriberLatency", + "averageTurnLatency", + "averageEndpointingLatency" ] }, - "analysisPlan": { - "description": "This is the plan for analysis of workflow's calls. Stored in `call.analysis`.", - "allOf": [ - { - "$ref": "#/components/schemas/AnalysisPlan" - } + "operator": { + "type": "string", + "description": "This is the operator to use for the filter.\nFor number type columns, the operator must be \"=\", \">\", \"<\", \">=\", \"<=\"", + "example": "\"=\" or \">\" or \"<\" or \">=\" or \"<=\"", + "enum": [ + "=", + "!=", + ">", + "<", + ">=", + "<=" ] }, - "artifactPlan": { - "description": "This is the plan for artifacts generated during workflow's calls. Stored in `call.artifact`.", - "allOf": [ - { - "$ref": "#/components/schemas/ArtifactPlan" - } + "value": { + "type": "number", + "description": "This is the value to filter on." + } + }, + "required": [ + "column", + "operator", + "value" + ] + }, + "FilterDateTypeColumnOnCallTable": { + "type": "object", + "properties": { + "column": { + "type": "string", + "description": "This is the column in the call table that will be filtered on.\nDate Type columns are columns where the rows store data as a date.\nMust be a valid column for the selected table.", + "example": "created_at", + "enum": [ + "startedAt", + "endedAt" ] }, - "startSpeakingPlan": { - "description": "This is the plan for when the workflow nodes should start talking.\n\nYou should configure this if you're running into these issues:\n- The assistant is too slow to start talking after the customer is done speaking.\n- The assistant is too fast to start talking after the customer is done speaking.\n- The assistant is so fast that it's actually interrupting the customer.", - "allOf": [ - { - "$ref": "#/components/schemas/StartSpeakingPlan" - } + "operator": { + "type": "string", + "description": "This is the operator to use for the filter.\nFor date type columns, the operator must be \"=\", \">\", \"<\", \">=\", \"<=\"", + "example": "\"=\" or \">\" or \"<\" or \">=\" or \"<=\"", + "enum": [ + "=", + "!=", + ">", + "<", + ">=", + "<=" ] }, - "stopSpeakingPlan": { - "description": "This is the plan for when workflow nodes should stop talking on customer interruption.\n\nYou should configure this if you're running into these issues:\n- The assistant is too slow to recognize customer's interruption.\n- The assistant is too fast to recognize customer's interruption.\n- The assistant is getting interrupted by phrases that are just acknowledgments.\n- The assistant is getting interrupted by background noises.\n- The assistant is not properly stopping -- it starts talking right after getting interrupted.", - "allOf": [ - { - "$ref": "#/components/schemas/StopSpeakingPlan" - } + "value": { + "type": "string", + "description": "This is the value to filter on.\nMust be a valid ISO 8601 date-time string.", + "example": "2025-01-01T00:00:00Z" + } + }, + "required": [ + "column", + "operator", + "value" + ] + }, + "FilterStructuredOutputColumnOnCallTable": { + "type": "object", + "properties": { + "column": { + "type": "string", + "description": "This is the column in the call table that will be filtered on.\nStructured Output Type columns are only to filter on artifact.structuredOutputs[OutputID] column.", + "example": "artifact.structuredOutputs[OutputID]", + "enum": [ + "artifact.structuredOutputs[OutputID]" ] }, - "monitorPlan": { - "description": "This is the plan for real-time monitoring of the workflow's calls.\n\nUsage:\n- To enable live listening of the workflow's calls, set `monitorPlan.listenEnabled` to `true`.\n- To enable live control of the workflow's calls, set `monitorPlan.controlEnabled` to `true`.", - "allOf": [ - { - "$ref": "#/components/schemas/MonitorPlan" - } + "operator": { + "type": "string", + "description": "This is the operator to use for the filter.\nThe operator depends on the value type of the structured output.\nIf the structured output is a string or boolean, the operator must be \"=\", \"!=\"\nIf the structured output is a number, the operator must be \"=\", \">\", \"<\", \">=\", \"<=\"\nIf the structured output is an array, the operator must be \"in\" or \"not_in\"", + "example": "\"=\" or \">\" or \"<\" or \"in\" or \"not_in\"", + "enum": [ + "=", + "!=", + ">", + "<", + ">=", + "<=", + "in", + "not_in", + "contains", + "not_contains", + "is_empty", + "is_not_empty" ] }, - "backgroundSpeechDenoisingPlan": { - "description": "This enables filtering of noise and background speech while the user is talking.\n\nFeatures:\n- Smart denoising using Krisp\n- Fourier denoising\n\nBoth can be used together. Order of precedence:\n- Smart denoising\n- Fourier denoising", - "allOf": [ - { - "$ref": "#/components/schemas/BackgroundSpeechDenoisingPlan" - } + "value": { + "type": "object", + "description": "This is the value to filter on.\nThe value type depends on the structured output type being filtered." + } + }, + "required": [ + "column", + "operator", + "value" + ] + }, + "FilterStringArrayTypeColumnOnCallTable": { + "type": "object", + "properties": { + "column": { + "type": "string", + "description": "This is the column in the call table that will be filtered on.\nString Array Type columns are the same as String Type columns, but provides the ability to filter on multiple values provided as an array.\nMust be a valid column for the selected table.", + "example": "assistant_id", + "enum": [ + "assistantId", + "workflowId", + "squadId", + "phoneNumberId", + "type", + "customerNumber", + "status", + "endedReason", + "forwardedPhoneNumber", + "campaignId" ] }, - "credentialIds": { - "description": "These are the credentials that will be used for the workflow calls. By default, all the credentials are available for use in the call but you can provide a subset using this.", + "operator": { + "type": "string", + "description": "This is the operator to use for the filter.\nThe operator must be `in` or `not_in`.", + "example": "\"in\" or \"not_in\"", + "enum": [ + "in", + "not_in", + "is_empty", + "is_not_empty" + ] + }, + "value": { + "description": "These are the values to filter on.", "type": "array", "items": { "type": "string" } - }, - "keypadInputPlan": { - "description": "This is the plan for keypad input handling during workflow calls.", - "allOf": [ - { - "$ref": "#/components/schemas/KeypadInputPlan" - } - ] } }, "required": [ - "nodes", - "id", - "orgId", - "createdAt", - "updatedAt", - "name", - "edges" + "column", + "operator", + "value" ] }, - "UpdateWorkflowDTO": { + "FilterNumberArrayTypeColumnOnCallTable": { "type": "object", "properties": { - "nodes": { + "column": { + "type": "string", + "description": "This is the column in the call table that will be filtered on.\nNumber Array Type columns are the same as Number Type columns, but provides the ability to filter on multiple values provided as an array.\nMust be a valid column for the selected table.", + "example": "duration", + "enum": [ + "duration", + "cost", + "averageModelLatency", + "averageVoiceLatency", + "averageTranscriberLatency", + "averageTurnLatency", + "averageEndpointingLatency" + ] + }, + "operator": { + "type": "string", + "description": "This is the operator to use for the filter.\nThe operator must be `in` or `not_in`.", + "example": "\"in\" or \"not_in\"", + "enum": [ + "in", + "not_in", + "is_empty", + "is_not_empty" + ] + }, + "value": { + "description": "This is the value to filter on.", "type": "array", "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/ConversationNode", - "title": "ConversationNode" - }, - { - "$ref": "#/components/schemas/ToolNode", - "title": "ToolNode" - } - ] + "type": "number" } + } + }, + "required": [ + "column", + "operator", + "value" + ] + }, + "EventsTableStringCondition": { + "type": "object", + "properties": { + "column": { + "type": "string", + "description": "The string field name from the event data", + "example": "provider" }, - "model": { - "description": "This is the model for the workflow.\n\nThis can be overridden at node level using `nodes[n].model`.", - "oneOf": [ - { - "$ref": "#/components/schemas/WorkflowOpenAIModel", - "title": "WorkflowOpenAIModel" - }, - { - "$ref": "#/components/schemas/WorkflowAnthropicModel", - "title": "WorkflowAnthropicModel" - }, - { - "$ref": "#/components/schemas/WorkflowGoogleModel", - "title": "WorkflowGoogleModel" - }, - { - "$ref": "#/components/schemas/WorkflowCustomModel", - "title": "WorkflowCustomModel" - } + "operator": { + "type": "string", + "description": "String comparison operator", + "example": "=", + "enum": [ + "=", + "!=", + "contains", + "notContains" ] }, - "transcriber": { - "description": "This is the transcriber for the workflow.\n\nThis can be overridden at node level using `nodes[n].transcriber`.", - "oneOf": [ - { - "$ref": "#/components/schemas/AssemblyAITranscriber", - "title": "AssemblyAITranscriber" - }, - { - "$ref": "#/components/schemas/AzureSpeechTranscriber", - "title": "AzureSpeechTranscriber" - }, - { - "$ref": "#/components/schemas/CustomTranscriber", - "title": "CustomTranscriber" - }, - { - "$ref": "#/components/schemas/DeepgramTranscriber", - "title": "DeepgramTranscriber" - }, - { - "$ref": "#/components/schemas/ElevenLabsTranscriber", - "title": "ElevenLabsTranscriber" - }, - { - "$ref": "#/components/schemas/GladiaTranscriber", - "title": "GladiaTranscriber" - }, - { - "$ref": "#/components/schemas/GoogleTranscriber", - "title": "GoogleTranscriber" - }, - { - "$ref": "#/components/schemas/SpeechmaticsTranscriber", - "title": "SpeechmaticsTranscriber" - }, - { - "$ref": "#/components/schemas/TalkscriberTranscriber", - "title": "TalkscriberTranscriber" - }, - { - "$ref": "#/components/schemas/OpenAITranscriber", - "title": "OpenAITranscriber" - }, - { - "$ref": "#/components/schemas/CartesiaTranscriber", - "title": "CartesiaTranscriber" - } + "value": { + "type": "string", + "description": "The string value to compare", + "example": "openai" + } + }, + "required": [ + "column", + "operator", + "value" + ] + }, + "EventsTableNumberCondition": { + "type": "object", + "properties": { + "column": { + "type": "string", + "description": "The number field name from the event data", + "example": "latency" + }, + "operator": { + "type": "string", + "description": "Number comparison operator", + "example": ">=", + "enum": [ + "=", + "!=", + ">", + ">=", + "<", + "<=" + ] + }, + "value": { + "type": "number", + "description": "The number value to compare", + "example": 1000 + } + }, + "required": [ + "column", + "operator", + "value" + ] + }, + "EventsTableBooleanCondition": { + "type": "object", + "properties": { + "column": { + "type": "string", + "description": "The boolean field name from the event data", + "example": "success" + }, + "operator": { + "type": "string", + "description": "Boolean comparison operator", + "example": "=", + "enum": [ + "=" ] }, - "voice": { - "description": "This is the voice for the workflow.\n\nThis can be overridden at node level using `nodes[n].voice`.", - "oneOf": [ - { - "$ref": "#/components/schemas/AzureVoice", - "title": "AzureVoice" - }, - { - "$ref": "#/components/schemas/CartesiaVoice", - "title": "CartesiaVoice" - }, - { - "$ref": "#/components/schemas/CustomVoice", - "title": "CustomVoice" - }, - { - "$ref": "#/components/schemas/DeepgramVoice", - "title": "DeepgramVoice" - }, - { - "$ref": "#/components/schemas/ElevenLabsVoice", - "title": "ElevenLabsVoice" - }, - { - "$ref": "#/components/schemas/HumeVoice", - "title": "HumeVoice" - }, - { - "$ref": "#/components/schemas/LMNTVoice", - "title": "LMNTVoice" - }, - { - "$ref": "#/components/schemas/NeuphonicVoice", - "title": "NeuphonicVoice" - }, - { - "$ref": "#/components/schemas/OpenAIVoice", - "title": "OpenAIVoice" - }, - { - "$ref": "#/components/schemas/PlayHTVoice", - "title": "PlayHTVoice" - }, - { - "$ref": "#/components/schemas/RimeAIVoice", - "title": "RimeAIVoice" - }, - { - "$ref": "#/components/schemas/SmallestAIVoice", - "title": "SmallestAIVoice" - }, - { - "$ref": "#/components/schemas/TavusVoice", - "title": "TavusVoice" - }, - { - "$ref": "#/components/schemas/VapiVoice", - "title": "VapiVoice" - }, - { - "$ref": "#/components/schemas/SesameVoice", - "title": "SesameVoice" - }, - { - "$ref": "#/components/schemas/InworldVoice", - "title": "InworldVoice" - }, - { - "$ref": "#/components/schemas/MinimaxVoice", - "title": "MinimaxVoice" - } + "value": { + "type": "boolean", + "description": "The boolean value to compare", + "example": true + } + }, + "required": [ + "column", + "operator", + "value" + ] + }, + "BarInsightFromCallTable": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "This is the name of the Insight.", + "minLength": 1, + "maxLength": 255 + }, + "type": { + "type": "string", + "description": "This is the type of the Insight.\nIt is required to be `bar` to create a bar insight.", + "enum": [ + "bar" ] }, - "observabilityPlan": { - "description": "This is the plan for observability of workflow's calls.\n\nCurrently, only Langfuse is supported.", - "oneOf": [ - { - "$ref": "#/components/schemas/LangfuseObservabilityPlan", - "title": "Langfuse" - } - ], + "formulas": { + "type": "array", + "description": "Formulas are mathematical expressions applied on the data returned by the queries to transform them before being used to create the insight.\nThe formulas needs to be a valid mathematical expression, supported by MathJS - https://mathjs.org/docs/expressions/syntax.html\nA formula is created by using the query names as the variable.\nThe formulas must contain at least one query name in the LiquidJS format {{query_name}} or {{['query name']}} which will be substituted with the query result.\nFor example, if you have 2 queries, 'Was Booking Made' and 'Average Call Duration', you can create a formula like this:\n```\n{{['Query 1']}} / {{['Query 2']}} * 100\n```\n\n```\n({{[Query 1]}} * 10) + {{[Query 2]}}\n```\nThis will take the\n\nYou can also use the query names as the variable in the formula.", + "items": { + "$ref": "#/components/schemas/InsightFormula" + } + }, + "metadata": { + "description": "This is the metadata for the insight.", "allOf": [ { - "$ref": "#/components/schemas/LangfuseObservabilityPlan" + "$ref": "#/components/schemas/BarInsightMetadata" } ] }, - "backgroundSound": { - "description": "This is the background sound in the call. Default for phone calls is 'office' and default for web calls is 'off'.\nYou can also provide a custom sound by providing a URL to an audio file.", - "oneOf": [ - { - "type": "enum", - "enum": [ - "off", - "office" - ], - "example": "office" - }, - { - "type": "string", - "format": "uri", - "example": "https://www.soundjay.com/ambient/sounds/people-in-lounge-1.mp3" - } + "timeRange": { + "$ref": "#/components/schemas/InsightTimeRangeWithStep" + }, + "groupBy": { + "type": "string", + "description": "This is the group by column for the insight when table is `call`.\nThese are the columns to group the results by.\nAll results are grouped by the time range step by default.", + "example": [ + "assistant_id" + ], + "enum": [ + "assistantId", + "workflowId", + "squadId", + "phoneNumberId", + "type", + "endedReason", + "customerNumber", + "campaignId", + "artifact.structuredOutputs[OutputID]" ] }, - "hooks": { + "queries": { "type": "array", - "description": "This is a set of actions that will be performed on certain events.", + "description": "These are the queries to run to generate the insight.", "items": { "oneOf": [ { - "$ref": "#/components/schemas/CallHookCallEnding", - "title": "CallHookCallEnding" + "$ref": "#/components/schemas/JSONQueryOnCallTableWithStringTypeColumn", + "title": "JSONQueryOnCallTableWithStringTypeColumn" }, { - "$ref": "#/components/schemas/CallHookAssistantSpeechInterrupted", - "title": "CallHookAssistantSpeechInterrupted" + "$ref": "#/components/schemas/JSONQueryOnCallTableWithNumberTypeColumn", + "title": "JSONQueryOnCallTableWithNumberTypeColumn" }, { - "$ref": "#/components/schemas/CallHookCustomerSpeechInterrupted", - "title": "CallHookCustomerSpeechInterrupted" + "$ref": "#/components/schemas/JSONQueryOnCallTableWithStructuredOutputColumn", + "title": "JSONQueryOnCallTableWithStructuredOutputColumn" }, { - "$ref": "#/components/schemas/CallHookCustomerSpeechTimeout", - "title": "CallHookCustomerSpeechTimeout" + "$ref": "#/components/schemas/JSONQueryOnEventsTable", + "title": "JSONQueryOnEventsTable" } ] } + } + }, + "required": [ + "type", + "queries" + ] + }, + "PieInsightFromCallTable": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "This is the name of the Insight.", + "minLength": 1, + "maxLength": 255 }, - "credentials": { + "type": { + "type": "string", + "description": "This is the type of the Insight.\nIt is required to be `pie` to create a pie insight.", + "enum": [ + "pie" + ] + }, + "formulas": { "type": "array", - "description": "These are dynamic credentials that will be used for the workflow calls. By default, all the credentials are available for use in the call but you can supplement an additional credentials using this. Dynamic credentials override existing credentials.", + "description": "Formulas are mathematical expressions applied on the data returned by the queries to transform them before being used to create the insight.\nThe formulas needs to be a valid mathematical expression, supported by MathJS - https://mathjs.org/docs/expressions/syntax.html\nA formula is created by using the query names as the variable.\nThe formulas must contain at least one query name in the LiquidJS format {{query_name}} or {{['query name']}} which will be substituted with the query result.\nFor example, if you have 2 queries, 'Was Booking Made' and 'Average Call Duration', you can create a formula like this:\n```\n{{['Query 1']}} / {{['Query 2']}} * 100\n```\n\n```\n({{[Query 1]}} * 10) + {{[Query 2]}}\n```\nThis will take the\n\nYou can also use the query names as the variable in the formula.", + "items": { + "$ref": "#/components/schemas/InsightFormula" + } + }, + "timeRange": { + "$ref": "#/components/schemas/InsightTimeRange" + }, + "groupBy": { + "type": "string", + "description": "This is the group by column for the insight when table is `call`.\nThese are the columns to group the results by.\nAll results are grouped by the time range step by default.", + "example": [ + "assistant_id" + ], + "enum": [ + "assistantId", + "workflowId", + "squadId", + "phoneNumberId", + "type", + "endedReason", + "customerNumber", + "campaignId", + "artifact.structuredOutputs[OutputID]" + ] + }, + "queries": { + "type": "array", + "description": "These are the queries to run to generate the insight.", "items": { "oneOf": [ { - "$ref": "#/components/schemas/CreateAnthropicCredentialDTO", - "title": "AnthropicCredential" - }, - { - "$ref": "#/components/schemas/CreateAnyscaleCredentialDTO", - "title": "AnyscaleCredential" - }, - { - "$ref": "#/components/schemas/CreateAssemblyAICredentialDTO", - "title": "AssemblyAICredential" - }, - { - "$ref": "#/components/schemas/CreateAzureCredentialDTO", - "title": "AzureCredential" - }, - { - "$ref": "#/components/schemas/CreateAzureOpenAICredentialDTO", - "title": "AzureOpenAICredential" - }, - { - "$ref": "#/components/schemas/CreateByoSipTrunkCredentialDTO", - "title": "ByoSipTrunkCredential" - }, - { - "$ref": "#/components/schemas/CreateCartesiaCredentialDTO", - "title": "CartesiaCredential" - }, - { - "$ref": "#/components/schemas/CreateCerebrasCredentialDTO", - "title": "CerebrasCredential" - }, - { - "$ref": "#/components/schemas/CreateCloudflareCredentialDTO", - "title": "CloudflareCredential" - }, - { - "$ref": "#/components/schemas/CreateCustomLLMCredentialDTO", - "title": "CustomLLMCredential" - }, - { - "$ref": "#/components/schemas/CreateDeepgramCredentialDTO", - "title": "DeepgramCredential" - }, - { - "$ref": "#/components/schemas/CreateDeepInfraCredentialDTO", - "title": "DeepInfraCredential" - }, - { - "$ref": "#/components/schemas/CreateDeepSeekCredentialDTO", - "title": "DeepSeekCredential" - }, - { - "$ref": "#/components/schemas/CreateElevenLabsCredentialDTO", - "title": "ElevenLabsCredential" - }, - { - "$ref": "#/components/schemas/CreateGcpCredentialDTO", - "title": "GcpCredential" - }, - { - "$ref": "#/components/schemas/CreateGladiaCredentialDTO", - "title": "GladiaCredential" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelCredentialDTO", - "title": "GhlCredential" - }, - { - "$ref": "#/components/schemas/CreateGoogleCredentialDTO", - "title": "GoogleCredential" - }, - { - "$ref": "#/components/schemas/CreateGroqCredentialDTO", - "title": "GroqCredential" - }, - { - "$ref": "#/components/schemas/CreateHumeCredentialDTO", - "title": "HumeCredential" - }, - { - "$ref": "#/components/schemas/CreateInflectionAICredentialDTO", - "title": "InflectionAICredential" - }, - { - "$ref": "#/components/schemas/CreateLangfuseCredentialDTO", - "title": "LangfuseCredential" - }, - { - "$ref": "#/components/schemas/CreateLmntCredentialDTO", - "title": "LmntCredential" - }, - { - "$ref": "#/components/schemas/CreateMakeCredentialDTO", - "title": "MakeCredential" - }, - { - "$ref": "#/components/schemas/CreateMistralCredentialDTO", - "title": "MistralCredential" - }, - { - "$ref": "#/components/schemas/CreateNeuphonicCredentialDTO", - "title": "NeuphonicCredential" - }, - { - "$ref": "#/components/schemas/CreateOpenAICredentialDTO", - "title": "OpenAICredential" - }, - { - "$ref": "#/components/schemas/CreateOpenRouterCredentialDTO", - "title": "OpenRouterCredential" - }, - { - "$ref": "#/components/schemas/CreatePerplexityAICredentialDTO", - "title": "PerplexityAICredential" - }, - { - "$ref": "#/components/schemas/CreatePlayHTCredentialDTO", - "title": "PlayHTCredential" - }, - { - "$ref": "#/components/schemas/CreateRimeAICredentialDTO", - "title": "RimeAICredential" - }, - { - "$ref": "#/components/schemas/CreateRunpodCredentialDTO", - "title": "RunpodCredential" - }, - { - "$ref": "#/components/schemas/CreateS3CredentialDTO", - "title": "S3Credential" - }, - { - "$ref": "#/components/schemas/CreateSmallestAICredentialDTO", - "title": "SmallestAICredential" - }, - { - "$ref": "#/components/schemas/CreateSpeechmaticsCredentialDTO", - "title": "SpeechmaticsCredential" - }, - { - "$ref": "#/components/schemas/CreateSupabaseCredentialDTO", - "title": "SupabaseCredential" - }, - { - "$ref": "#/components/schemas/CreateTavusCredentialDTO", - "title": "TavusCredential" - }, - { - "$ref": "#/components/schemas/CreateTogetherAICredentialDTO", - "title": "TogetherAICredential" - }, - { - "$ref": "#/components/schemas/CreateTrieveCredentialDTO", - "title": "TrieveCredential" - }, - { - "$ref": "#/components/schemas/CreateTwilioCredentialDTO", - "title": "TwilioCredential" - }, - { - "$ref": "#/components/schemas/CreateVonageCredentialDTO", - "title": "VonageCredential" - }, - { - "$ref": "#/components/schemas/CreateWebhookCredentialDTO", - "title": "WebhookCredential" - }, - { - "$ref": "#/components/schemas/CreateXAiCredentialDTO", - "title": "XAiCredential" - }, - { - "$ref": "#/components/schemas/CreateGoogleCalendarOAuth2ClientCredentialDTO", - "title": "GoogleCalendarOAuth2ClientCredential" - }, - { - "$ref": "#/components/schemas/CreateGoogleCalendarOAuth2AuthorizationCredentialDTO", - "title": "GoogleCalendarOAuth2AuthorizationCredential" + "$ref": "#/components/schemas/JSONQueryOnCallTableWithStringTypeColumn", + "title": "JSONQueryOnCallTableWithStringTypeColumn" }, { - "$ref": "#/components/schemas/CreateGoogleSheetsOAuth2AuthorizationCredentialDTO", - "title": "GoogleSheetsOAuth2AuthorizationCredential" - }, - { - "$ref": "#/components/schemas/CreateSlackOAuth2AuthorizationCredentialDTO", - "title": "SlackOAuth2AuthorizationCredential" - }, - { - "$ref": "#/components/schemas/CreateGoHighLevelMCPCredentialDTO", - "title": "GoHighLevelMCPCredential" + "$ref": "#/components/schemas/JSONQueryOnCallTableWithNumberTypeColumn", + "title": "JSONQueryOnCallTableWithNumberTypeColumn" }, { - "$ref": "#/components/schemas/CreateInworldCredentialDTO", - "title": "InworldCredential" - } - ], - "discriminator": { - "propertyName": "provider", - "mapping": { - "11labs": "#/components/schemas/CreateElevenLabsCredentialDTO", - "anthropic": "#/components/schemas/CreateAnthropicCredentialDTO", - "anyscale": "#/components/schemas/CreateAnyscaleCredentialDTO", - "assembly-ai": "#/components/schemas/CreateAssemblyAICredentialDTO", - "azure-openai": "#/components/schemas/CreateAzureOpenAICredentialDTO", - "azure": "#/components/schemas/CreateAzureCredentialDTO", - "byo-sip-trunk": "#/components/schemas/CreateByoSipTrunkCredentialDTO", - "cartesia": "#/components/schemas/CreateCartesiaCredentialDTO", - "cerebras": "#/components/schemas/CreateCerebrasCredentialDTO", - "cloudflare": "#/components/schemas/CreateCloudflareCredentialDTO", - "custom-llm": "#/components/schemas/CreateCustomLLMCredentialDTO", - "deepgram": "#/components/schemas/CreateDeepgramCredentialDTO", - "deepinfra": "#/components/schemas/CreateDeepInfraCredentialDTO", - "deep-seek": "#/components/schemas/CreateDeepSeekCredentialDTO", - "gcp": "#/components/schemas/CreateGcpCredentialDTO", - "gladia": "#/components/schemas/CreateGladiaCredentialDTO", - "gohighlevel": "#/components/schemas/CreateGoHighLevelCredentialDTO", - "google": "#/components/schemas/CreateGoogleCredentialDTO", - "groq": "#/components/schemas/CreateGroqCredentialDTO", - "inflection-ai": "#/components/schemas/CreateInflectionAICredentialDTO", - "langfuse": "#/components/schemas/CreateLangfuseCredentialDTO", - "lmnt": "#/components/schemas/CreateLmntCredentialDTO", - "make": "#/components/schemas/CreateMakeCredentialDTO", - "openai": "#/components/schemas/CreateOpenAICredentialDTO", - "openrouter": "#/components/schemas/CreateOpenRouterCredentialDTO", - "perplexity-ai": "#/components/schemas/CreatePerplexityAICredentialDTO", - "playht": "#/components/schemas/CreatePlayHTCredentialDTO", - "rime-ai": "#/components/schemas/CreateRimeAICredentialDTO", - "runpod": "#/components/schemas/CreateRunpodCredentialDTO", - "s3": "#/components/schemas/CreateS3CredentialDTO", - "supabase": "#/components/schemas/CreateSupabaseCredentialDTO", - "smallest-ai": "#/components/schemas/CreateSmallestAICredentialDTO", - "tavus": "#/components/schemas/CreateTavusCredentialDTO", - "together-ai": "#/components/schemas/CreateTogetherAICredentialDTO", - "twilio": "#/components/schemas/CreateTwilioCredentialDTO", - "vonage": "#/components/schemas/CreateVonageCredentialDTO", - "webhook": "#/components/schemas/CreateWebhookCredentialDTO", - "xai": "#/components/schemas/CreateXAiCredentialDTO", - "neuphonic": "#/components/schemas/CreateNeuphonicCredentialDTO", - "hume": "#/components/schemas/CreateHumeCredentialDTO", - "mistral": "#/components/schemas/CreateMistralCredentialDTO", - "speechmatics": "#/components/schemas/CreateSpeechmaticsCredentialDTO", - "trieve": "#/components/schemas/CreateTrieveCredentialDTO", - "google.calendar.oauth2-client": "#/components/schemas/CreateGoogleCalendarOAuth2ClientCredentialDTO", - "google.calendar.oauth2-authorization": "#/components/schemas/CreateGoogleCalendarOAuth2AuthorizationCredentialDTO", - "google.sheets.oauth2-authorization": "#/components/schemas/CreateGoogleSheetsOAuth2AuthorizationCredentialDTO", - "slack.oauth2-authorization": "#/components/schemas/CreateSlackOAuth2AuthorizationCredentialDTO", - "ghl.oauth2-authorization": "#/components/schemas/CreateGoHighLevelMCPCredentialDTO", - "inworld": "#/components/schemas/CreateInworldCredentialDTO", - "minimax": "#/components/schemas/CreateMinimaxCredentialDTO" + "$ref": "#/components/schemas/JSONQueryOnCallTableWithStructuredOutputColumn", + "title": "JSONQueryOnCallTableWithStructuredOutputColumn" } - } + ] } - }, + } + }, + "required": [ + "type", + "queries" + ] + }, + "LineInsightFromCallTable": { + "type": "object", + "properties": { "name": { "type": "string", - "maxLength": 80 - }, - "edges": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Edge" - } + "description": "This is the name of the Insight.", + "minLength": 1, + "maxLength": 255 }, - "globalPrompt": { + "type": { "type": "string", - "maxLength": 5000 - }, - "server": { - "description": "This is where Vapi will send webhooks. You can find all webhooks available along with their shape in ServerMessage schema.\n\nThe order of precedence is:\n\n1. tool.server\n2. workflow.server / assistant.server\n3. phoneNumber.server\n4. org.server", - "allOf": [ - { - "$ref": "#/components/schemas/Server" - } + "description": "This is the type of the Insight.\nIt is required to be `line` to create a line insight.", + "enum": [ + "line" ] }, - "compliancePlan": { - "description": "This is the compliance plan for the workflow. It allows you to configure HIPAA and other compliance settings.", - "allOf": [ - { - "$ref": "#/components/schemas/CompliancePlan" - } - ] + "formulas": { + "type": "array", + "description": "Formulas are mathematical expressions applied on the data returned by the queries to transform them before being used to create the insight.\nThe formulas needs to be a valid mathematical expression, supported by MathJS - https://mathjs.org/docs/expressions/syntax.html\nA formula is created by using the query names as the variable.\nThe formulas must contain at least one query name in the LiquidJS format {{query_name}} or {{['query name']}} which will be substituted with the query result.\nFor example, if you have 2 queries, 'Was Booking Made' and 'Average Call Duration', you can create a formula like this:\n```\n{{['Query 1']}} / {{['Query 2']}} * 100\n```\n\n```\n({{[Query 1]}} * 10) + {{[Query 2]}}\n```\nThis will take the\n\nYou can also use the query names as the variable in the formula.", + "items": { + "$ref": "#/components/schemas/InsightFormula" + } }, - "analysisPlan": { - "description": "This is the plan for analysis of workflow's calls. Stored in `call.analysis`.", + "metadata": { + "description": "This is the metadata for the insight.", "allOf": [ { - "$ref": "#/components/schemas/AnalysisPlan" + "$ref": "#/components/schemas/LineInsightMetadata" } ] }, - "artifactPlan": { - "description": "This is the plan for artifacts generated during workflow's calls. Stored in `call.artifact`.", - "allOf": [ - { - "$ref": "#/components/schemas/ArtifactPlan" - } - ] + "timeRange": { + "$ref": "#/components/schemas/InsightTimeRangeWithStep" }, - "startSpeakingPlan": { - "description": "This is the plan for when the workflow nodes should start talking.\n\nYou should configure this if you're running into these issues:\n- The assistant is too slow to start talking after the customer is done speaking.\n- The assistant is too fast to start talking after the customer is done speaking.\n- The assistant is so fast that it's actually interrupting the customer.", - "allOf": [ - { - "$ref": "#/components/schemas/StartSpeakingPlan" - } + "groupBy": { + "type": "string", + "description": "This is the group by column for the insight when table is `call`.\nThese are the columns to group the results by.\nAll results are grouped by the time range step by default.", + "example": [ + "assistant_id" + ], + "enum": [ + "assistantId", + "workflowId", + "squadId", + "phoneNumberId", + "type", + "endedReason", + "customerNumber", + "campaignId", + "artifact.structuredOutputs[OutputID]" ] }, - "stopSpeakingPlan": { - "description": "This is the plan for when workflow nodes should stop talking on customer interruption.\n\nYou should configure this if you're running into these issues:\n- The assistant is too slow to recognize customer's interruption.\n- The assistant is too fast to recognize customer's interruption.\n- The assistant is getting interrupted by phrases that are just acknowledgments.\n- The assistant is getting interrupted by background noises.\n- The assistant is not properly stopping -- it starts talking right after getting interrupted.", - "allOf": [ - { - "$ref": "#/components/schemas/StopSpeakingPlan" - } - ] + "queries": { + "type": "array", + "description": "These are the queries to run to generate the insight.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/JSONQueryOnCallTableWithStringTypeColumn", + "title": "JSONQueryOnCallTableWithStringTypeColumn" + }, + { + "$ref": "#/components/schemas/JSONQueryOnCallTableWithNumberTypeColumn", + "title": "JSONQueryOnCallTableWithNumberTypeColumn" + }, + { + "$ref": "#/components/schemas/JSONQueryOnCallTableWithStructuredOutputColumn", + "title": "JSONQueryOnCallTableWithStructuredOutputColumn" + } + ] + } + } + }, + "required": [ + "type", + "queries" + ] + }, + "TextInsightFromCallTable": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "This is the name of the Insight.", + "minLength": 1, + "maxLength": 255 }, - "monitorPlan": { - "description": "This is the plan for real-time monitoring of the workflow's calls.\n\nUsage:\n- To enable live listening of the workflow's calls, set `monitorPlan.listenEnabled` to `true`.\n- To enable live control of the workflow's calls, set `monitorPlan.controlEnabled` to `true`.", - "allOf": [ - { - "$ref": "#/components/schemas/MonitorPlan" - } + "type": { + "type": "string", + "description": "This is the type of the Insight.\nIt is required to be `text` to create a text insight.", + "enum": [ + "text" ] }, - "backgroundSpeechDenoisingPlan": { - "description": "This enables filtering of noise and background speech while the user is talking.\n\nFeatures:\n- Smart denoising using Krisp\n- Fourier denoising\n\nBoth can be used together. Order of precedence:\n- Smart denoising\n- Fourier denoising", - "allOf": [ - { - "$ref": "#/components/schemas/BackgroundSpeechDenoisingPlan" - } - ] + "formula": { + "type": "object", + "description": "Formulas are mathematical expressions applied on the data returned by the queries to transform them before being used to create the insight.\nThe formulas needs to be a valid mathematical expression, supported by MathJS - https://mathjs.org/docs/expressions/syntax.html\nA formula is created by using the query names as the variable.\nThe formulas must contain at least one query name in the LiquidJS format {{query_name}} or {{['query name']}} which will be substituted with the query result.\nFor example, if you have 2 queries, 'Was Booking Made' and 'Average Call Duration', you can create a formula like this:\n```\n{{['Query 1']}} / {{['Query 2']}} * 100\n```\n\n```\n({{[Query 1]}} * 10) + {{[Query 2]}}\n```\nThis will take the\n\nYou can also use the query names as the variable in the formula.", + "items": { + "$ref": "#/components/schemas/InsightFormula" + } }, - "credentialIds": { - "description": "These are the credentials that will be used for the workflow calls. By default, all the credentials are available for use in the call but you can provide a subset using this.", + "timeRange": { + "$ref": "#/components/schemas/InsightTimeRange" + }, + "queries": { "type": "array", + "description": "These are the queries to run to generate the insight.\nFor Text Insights, we only allow a single query, or require a formula if multiple queries are provided", "items": { - "type": "string" + "oneOf": [ + { + "$ref": "#/components/schemas/JSONQueryOnCallTableWithStringTypeColumn", + "title": "JSONQueryOnCallTableWithStringTypeColumn" + }, + { + "$ref": "#/components/schemas/JSONQueryOnCallTableWithNumberTypeColumn", + "title": "JSONQueryOnCallTableWithNumberTypeColumn" + }, + { + "$ref": "#/components/schemas/JSONQueryOnCallTableWithStructuredOutputColumn", + "title": "JSONQueryOnCallTableWithStructuredOutputColumn" + } + ] } + } + }, + "required": [ + "type", + "queries" + ] + }, + "InsightFormula": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "This is the name of the formula.\nIt will be used to label the formula in the insight board on the UI.", + "example": "Booking Rate", + "minLength": 1, + "maxLength": 255 }, - "keypadInputPlan": { - "description": "This is the plan for keypad input handling during workflow calls.", + "formula": { + "type": "string", + "description": "This is the formula to calculate the insight from the queries.\nThe formula needs to be a valid mathematical expression.\nThe formula must contain at least one query name in the LiquidJS format {{query_name}} or {{['query name']}} which will be substituted with the query result.\nAny MathJS formula is allowed - https://mathjs.org/docs/expressions/syntax.html\n\nCommon valid math operations are +, -, *, /, %", + "minLength": 1, + "maxLength": 1000 + } + }, + "required": [ + "formula" + ] + }, + "InsightRunFormatPlan": { + "type": "object", + "properties": { + "format": { + "type": "string", + "description": "This is the format of the data to return.\nIf not provided, defaults to \"raw\".\nRaw provides the data as fetched from the database, with formulas evaluated.\nRecharts provides the data in a format that can is ready to be used by recharts.js to render charts.", + "example": "raw", + "enum": [ + "raw", + "recharts" + ] + } + } + }, + "InsightRunDTO": { + "type": "object", + "properties": { + "formatPlan": { + "$ref": "#/components/schemas/InsightRunFormatPlan" + }, + "timeRangeOverride": { + "description": "This is the optional time range override for the insight.\nIf provided, overrides every field in the insight's timeRange.\nIf this is provided with missing fields, defaults will be used, not the insight's timeRange.\nstart default - \"-7d\"\nend default - \"now\"\nstep default - \"day\"\nFor Pie and Text Insights, step will be ignored even if provided.", + "example": "{ start: \"2025-01-01\", end: \"2025-01-07\", step: \"day\" }", "allOf": [ { - "$ref": "#/components/schemas/KeypadInputPlan" + "$ref": "#/components/schemas/InsightTimeRangeWithStep" } ] + }, + "assistantId": { + "type": "string", + "description": "Optional runtime assistant scope for dashboards.\nThis is applied to call-table queries without mutating the saved insight." } } }, - "Squad": { + "InsightRunResponse": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "insightId": { + "type": "string" + }, + "orgId": { + "type": "string" + }, + "createdAt": { + "format": "date-time", + "type": "string" + }, + "updatedAt": { + "format": "date-time", + "type": "string" + } + }, + "required": [ + "id", + "insightId", + "orgId", + "createdAt", + "updatedAt" + ] + }, + "Insight": { "type": "object", "properties": { "name": { "type": "string", - "description": "This is the name of the squad." - }, - "members": { - "description": "This is the list of assistants that make up the squad.\n\nThe call will start with the first assistant in the list.", - "type": "array", - "items": { - "$ref": "#/components/schemas/SquadMemberDTO" - } + "description": "This is the name of the Insight.", + "minLength": 1, + "maxLength": 255 }, - "membersOverrides": { - "description": "This can be used to override all the assistants' settings and provide values for their template variables.\n\nBoth `membersOverrides` and `members[n].assistantOverrides` can be used together. First, `members[n].assistantOverrides` is applied. Then, `membersOverrides` is applied as a global override.", - "allOf": [ - { - "$ref": "#/components/schemas/AssistantOverrides" - } + "type": { + "type": "string", + "description": "This is the type of the Insight.", + "enum": [ + "bar", + "line", + "pie", + "text" ] }, "id": { "type": "string", - "description": "This is the unique identifier for the squad." + "description": "This is the unique identifier for the Insight." }, "orgId": { "type": "string", - "description": "This is the unique identifier for the org that this squad belongs to." + "description": "This is the unique identifier for the org that this Insight belongs to." }, "createdAt": { "format": "date-time", "type": "string", - "description": "This is the ISO 8601 date-time string of when the squad was created." + "description": "This is the ISO 8601 date-time string of when the Insight was created." }, "updatedAt": { "format": "date-time", "type": "string", - "description": "This is the ISO 8601 date-time string of when the squad was last updated." + "description": "This is the ISO 8601 date-time string of when the Insight was last updated." + }, + "systemKey": { + "type": "string", + "description": "Stable server-owned identifier for system-created insights." } }, "required": [ - "members", + "type", "id", "orgId", "createdAt", "updatedAt" ] }, - "UpdateSquadDTO": { + "InsightPaginatedResponse": { "type": "object", "properties": { - "name": { - "type": "string", - "description": "This is the name of the squad." - }, - "members": { - "description": "This is the list of assistants that make up the squad.\n\nThe call will start with the first assistant in the list.", + "results": { "type": "array", "items": { - "$ref": "#/components/schemas/SquadMemberDTO" + "$ref": "#/components/schemas/Insight" } }, - "membersOverrides": { - "description": "This can be used to override all the assistants' settings and provide values for their template variables.\n\nBoth `membersOverrides` and `members[n].assistantOverrides` can be used together. First, `members[n].assistantOverrides` is applied. Then, `membersOverrides` is applied as a global override.", - "allOf": [ - { - "$ref": "#/components/schemas/AssistantOverrides" - } - ] + "metadata": { + "$ref": "#/components/schemas/PaginationMeta" } }, "required": [ - "members" + "results", + "metadata" ] }, - "TesterPlan": { - "type": "object", - "properties": { - "assistant": { - "description": "Pass a transient assistant to use for the test assistant.\n\nMake sure to write a detailed system prompt for a test assistant, and use the {{test.script}} variable to access the test script.", - "allOf": [ - { - "$ref": "#/components/schemas/CreateAssistantDTO" - } - ] - }, - "assistantId": { - "type": "string", - "description": "Pass an assistant id that can be access\n\nMake sure to write a detailed system prompt for the test assistant, and use the {{test.script}} variable to access the test script." - }, - "assistantOverrides": { - "description": "Add any assistant overrides to the test assistant.\n\nOne use case is if you want to pass custom variables into the test using variableValues, that you can then access in the script\nand rubric using {{varName}}.", - "allOf": [ - { - "$ref": "#/components/schemas/AssistantOverrides" - } - ] - } - } - }, - "TestSuitePhoneNumber": { + "BoardLayout": { "type": "object", "properties": { - "provider": { - "type": "string", - "description": "This is the provider of the phone number.", - "enum": [ - "test-suite" - ] - }, - "number": { - "type": "string", - "description": "This is the phone number that is being tested.", - "maxLength": 50 + "columns": { + "type": "number", + "description": "This is the number of columns in the Board.\nFor now, it is fixed to 6.", + "minimum": 6, + "maximum": 6 } }, "required": [ - "provider", - "number" + "columns" ] }, - "TargetPlan": { + "Board": { "type": "object", "properties": { - "phoneNumberId": { - "type": "string", - "description": "This is the phone number that is being tested.\nDuring the actual test, it'll be called and the assistant attached to it will pick up and be tested.\nTo test an assistant directly, send assistantId instead." - }, - "phoneNumber": { - "description": "This can be any phone number (even not on Vapi).\nDuring the actual test, it'll be called.\nTo test a Vapi number, send phoneNumberId. To test an assistant directly, send assistantId instead.", - "allOf": [ - { - "$ref": "#/components/schemas/TestSuitePhoneNumber" - } - ] - }, - "assistantId": { - "type": "string", - "description": "This is the assistant being tested.\nDuring the actual test, it'll invoked directly.\nTo test the assistant over phone number, send phoneNumberId instead." + "items": { + "type": "array", + "description": "This is the contents of the Board, which is an array of objects defining the type, contents, and position of the widgets on the Board.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/BoardInsightItem" + }, + { + "$ref": "#/components/schemas/BoardMetricWidgetItem" + } + ] + } }, - "assistantOverrides": { - "description": "This is the assistant overrides applied to assistantId before it is tested.", - "allOf": [ - { - "$ref": "#/components/schemas/AssistantOverrides" - } - ] - } - } - }, - "TestSuite": { - "type": "object", - "properties": { "id": { "type": "string", - "description": "This is the unique identifier for the test suite." + "description": "This is the unique identifier for the Board." }, "orgId": { "type": "string", - "description": "This is the unique identifier for the org that this test suite belongs to." + "description": "This is the unique identifier for the org that this Board belongs to." }, "createdAt": { "format": "date-time", "type": "string", - "description": "This is the ISO 8601 date-time string of when the test suite was created." + "description": "This is the ISO 8601 date-time string of when the Board was created." }, "updatedAt": { "format": "date-time", "type": "string", - "description": "This is the ISO 8601 date-time string of when the test suite was last updated." + "description": "This is the ISO 8601 date-time string of when the Board was last updated." }, - "name": { + "systemKey": { "type": "string", - "description": "This is the name of the test suite.", - "maxLength": 80 + "description": "Server-owned key for system-provisioned boards. User create/update DTOs do\nnot accept this field." }, - "phoneNumberId": { + "name": { "type": "string", - "description": "This is the phone number ID associated with this test suite.", - "deprecated": true + "description": "This is the name of the Board.", + "minLength": 1, + "maxLength": 40 }, - "testerPlan": { - "description": "Override the default tester plan by providing custom assistant configuration for the test agent.\n\nWe recommend only using this if you are confident, as we have already set sensible defaults on the tester plan.", + "layout": { + "description": "This is the layout of the Board.", "allOf": [ { - "$ref": "#/components/schemas/TesterPlan" + "$ref": "#/components/schemas/BoardLayout" } ] }, - "targetPlan": { - "description": "These are the configuration for the assistant / phone number that is being tested.", + "timeRangeOverride": { + "description": "This is the timerange override for the board.\nBy default, individual insights have their own timerange.\nThis is a global override for the board which will be passed to all insights on the board.", "allOf": [ { - "$ref": "#/components/schemas/TargetPlan" + "$ref": "#/components/schemas/InsightTimeRangeWithStep" } ] } @@ -38102,658 +63351,1271 @@ "id", "orgId", "createdAt", - "updatedAt" + "updatedAt", + "name", + "layout" ] }, - "TestSuitesPaginatedResponse": { + "BoardItemPosition": { "type": "object", "properties": { - "results": { - "type": "array", - "items": { - "$ref": "#/components/schemas/TestSuite" - } + "x": { + "type": "number", + "minimum": 0 }, - "metadata": { - "$ref": "#/components/schemas/PaginationMeta" + "y": { + "type": "number", + "minimum": 0 } }, "required": [ - "results", - "metadata" + "x", + "y" ] }, - "CreateTestSuiteDto": { + "BoardItemSize": { "type": "object", "properties": { - "name": { + "width": { + "type": "number", + "minimum": 1 + }, + "height": { + "type": "number", + "minimum": 1 + } + }, + "required": [ + "width", + "height" + ] + }, + "BoardInsightItem": { + "type": "object", + "properties": { + "type": { "type": "string", - "description": "This is the name of the test suite.", - "maxLength": 80 + "enum": [ + "insight" + ] }, - "phoneNumberId": { + "insightId": { + "type": "string" + }, + "systemKey": { + "type": "string" + }, + "position": { + "$ref": "#/components/schemas/BoardItemPosition" + }, + "size": { + "$ref": "#/components/schemas/BoardItemSize" + } + }, + "required": [ + "type", + "insightId", + "position", + "size" + ] + }, + "BoardMetricWidgetItem": { + "type": "object", + "properties": { + "type": { "type": "string", - "description": "This is the phone number ID associated with this test suite.", - "deprecated": true + "enum": [ + "failed_calls_list", + "concurrency_chart", + "average_cost_breakdown_chart" + ] }, - "testerPlan": { - "description": "Override the default tester plan by providing custom assistant configuration for the test agent.\n\nWe recommend only using this if you are confident, as we have already set sensible defaults on the tester plan.", + "position": { + "$ref": "#/components/schemas/BoardItemPosition" + }, + "size": { + "$ref": "#/components/schemas/BoardItemSize" + }, + "insightId": { + "type": "string" + }, + "systemKey": { + "type": "string" + } + }, + "required": [ + "type", + "position", + "size" + ] + }, + "CreateBoardDTO": { + "type": "object", + "properties": { + "items": { + "type": "array", + "description": "This is the contents of the Board, which is an array of objects defining the type, contents, and position of the widgets on the Board.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/BoardInsightItem" + }, + { + "$ref": "#/components/schemas/BoardMetricWidgetItem" + } + ] + } + }, + "name": { + "type": "string", + "description": "This is the name of the Board.", + "minLength": 1, + "maxLength": 40 + }, + "layout": { + "description": "This is the layout of the Board.", "allOf": [ { - "$ref": "#/components/schemas/TesterPlan" + "$ref": "#/components/schemas/BoardLayout" } ] }, - "targetPlan": { - "description": "These are the configuration for the assistant / phone number that is being tested.", + "timeRangeOverride": { + "description": "This is the timerange override for the board.\nBy default, individual insights have their own timerange.\nThis is a global override for the board which will be passed to all insights on the board.", "allOf": [ { - "$ref": "#/components/schemas/TargetPlan" + "$ref": "#/components/schemas/InsightTimeRangeWithStep" } ] } - } + }, + "required": [ + "name", + "layout" + ] }, - "UpdateTestSuiteDto": { + "UpdateBoardDTO": { "type": "object", "properties": { - "name": { - "type": "string", - "description": "This is the name of the test suite.", - "maxLength": 80 + "items": { + "type": "array", + "description": "This is the contents of the Board, which is an array of objects defining the type, contents, and position of the widgets on the Board.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/BoardInsightItem" + }, + { + "$ref": "#/components/schemas/BoardMetricWidgetItem" + } + ] + } }, - "phoneNumberId": { + "name": { "type": "string", - "description": "This is the phone number ID associated with this test suite.", - "deprecated": true + "description": "This is the name of the Board.", + "minLength": 1, + "maxLength": 40 }, - "testerPlan": { - "description": "Override the default tester plan by providing custom assistant configuration for the test agent.\n\nWe recommend only using this if you are confident, as we have already set sensible defaults on the tester plan.", + "layout": { + "description": "This is the layout of the Board.", "allOf": [ { - "$ref": "#/components/schemas/TesterPlan" + "$ref": "#/components/schemas/BoardLayout" } ] }, - "targetPlan": { - "description": "These are the configuration for the assistant / phone number that is being tested.", + "timeRangeOverride": { + "description": "This is the timerange override for the board.\nBy default, individual insights have their own timerange.\nThis is a global override for the board which will be passed to all insights on the board.", "allOf": [ { - "$ref": "#/components/schemas/TargetPlan" + "$ref": "#/components/schemas/InsightTimeRangeWithStep" } ] } } }, - "TestSuiteTestVoice": { + "BoardPaginatedResponse": { "type": "object", "properties": { - "scorers": { + "results": { "type": "array", - "description": "These are the scorers used to evaluate the test.", + "items": { + "$ref": "#/components/schemas/Board" + } + }, + "metadata": { + "$ref": "#/components/schemas/PaginationMeta" + } + }, + "required": [ + "results", + "metadata" + ] + }, + "CreateEvalDTO": { + "type": "object", + "properties": { + "messages": { + "type": "array", + "description": "This is the mock conversation that will be used to evaluate the flow of the conversation.\n\nMock Messages are used to simulate the flow of the conversation\n\nEvaluation Messages are used as checkpoints in the flow where the model's response to previous conversation needs to be evaluated to check the content and tool calls", + "example": "[{ role: \"user\", content: \"Hello, how are you?\" }, { role: \"assistant\", judgePlan: { type: \"exact\", content: \"I am good, thank you!\" } }]", "items": { "oneOf": [ { - "$ref": "#/components/schemas/TestSuiteTestScorerAI", - "title": "AI" + "$ref": "#/components/schemas/ChatEvalAssistantMessageMock", + "title": "ChatEvalAssistantMessageMock" + }, + { + "$ref": "#/components/schemas/ChatEvalSystemMessageMock", + "title": "ChatEvalSystemMessageMock" + }, + { + "$ref": "#/components/schemas/ChatEvalToolResponseMessageMock", + "title": "ChatEvalToolResponseMessageMock" + }, + { + "$ref": "#/components/schemas/ChatEvalToolResponseMessageEvaluation", + "title": "ChatEvalToolResponseMessageEvaluation" + }, + { + "$ref": "#/components/schemas/ChatEvalUserMessageMock", + "title": "ChatEvalUserMessageMock" + }, + { + "$ref": "#/components/schemas/ChatEvalAssistantMessageEvaluation", + "title": "ChatEvalAssistantMessageEvaluation" } ] } }, - "type": { - "type": "string", - "description": "This is the type of the test, which must be voice.", - "enum": [ - "voice" - ], - "maxLength": 100 - }, - "id": { - "type": "string", - "description": "This is the unique identifier for the test." - }, - "testSuiteId": { - "type": "string", - "description": "This is the unique identifier for the test suite this test belongs to." - }, - "orgId": { - "type": "string", - "description": "This is the unique identifier for the organization this test belongs to." - }, - "createdAt": { - "format": "date-time", - "type": "string", - "description": "This is the ISO 8601 date-time string of when the test was created." - }, - "updatedAt": { - "format": "date-time", - "type": "string", - "description": "This is the ISO 8601 date-time string of when the test was last updated." - }, "name": { "type": "string", - "description": "This is the name of the test.", + "description": "This is the name of the eval.\nIt helps identify what the eval is checking for.", + "example": "Verified User Flow Eval", + "minLength": 1, "maxLength": 80 }, - "script": { + "description": { "type": "string", - "description": "This is the script to be used for the voice test.", - "maxLength": 10000 + "description": "This is the description of the eval.\nThis helps describe the eval and its purpose in detail. It will not be used to evaluate the flow of the conversation.", + "example": "This eval checks if the user flow is verified.", + "maxLength": 500 }, - "numAttempts": { - "type": "number", - "description": "This is the number of attempts allowed for the test.", - "minimum": 1, - "maximum": 10 + "type": { + "type": "string", + "description": "This is the type of the eval.\nCurrently it is fixed to `chat.mockConversation`.", + "example": "chat.mockConversation", + "enum": [ + "chat.mockConversation" + ] } }, "required": [ - "scorers", - "type", - "id", - "testSuiteId", - "orgId", - "createdAt", - "updatedAt", - "script" + "messages", + "type" ] }, - "TestSuiteTestChat": { + "Eval": { "type": "object", "properties": { - "scorers": { + "messages": { "type": "array", - "description": "These are the scorers used to evaluate the test.", + "description": "This is the mock conversation that will be used to evaluate the flow of the conversation.\n\nMock Messages are used to simulate the flow of the conversation\n\nEvaluation Messages are used as checkpoints in the flow where the model's response to previous conversation needs to be evaluated to check the content and tool calls", + "example": "[{ role: \"user\", content: \"Hello, how are you?\" }, { role: \"assistant\", judgePlan: { type: \"exact\", content: \"I am good, thank you!\" } }]", "items": { "oneOf": [ { - "$ref": "#/components/schemas/TestSuiteTestScorerAI", - "title": "AI" + "$ref": "#/components/schemas/ChatEvalAssistantMessageMock", + "title": "ChatEvalAssistantMessageMock" + }, + { + "$ref": "#/components/schemas/ChatEvalSystemMessageMock", + "title": "ChatEvalSystemMessageMock" + }, + { + "$ref": "#/components/schemas/ChatEvalToolResponseMessageMock", + "title": "ChatEvalToolResponseMessageMock" + }, + { + "$ref": "#/components/schemas/ChatEvalToolResponseMessageEvaluation", + "title": "ChatEvalToolResponseMessageEvaluation" + }, + { + "$ref": "#/components/schemas/ChatEvalUserMessageMock", + "title": "ChatEvalUserMessageMock" + }, + { + "$ref": "#/components/schemas/ChatEvalAssistantMessageEvaluation", + "title": "ChatEvalAssistantMessageEvaluation" } ] } }, - "type": { - "type": "string", - "description": "This is the type of the test, which must be chat.", - "enum": [ - "chat" - ], - "maxLength": 100 - }, "id": { - "type": "string", - "description": "This is the unique identifier for the test." - }, - "testSuiteId": { - "type": "string", - "description": "This is the unique identifier for the test suite this test belongs to." + "type": "string" }, "orgId": { - "type": "string", - "description": "This is the unique identifier for the organization this test belongs to." + "type": "string" }, "createdAt": { "format": "date-time", - "type": "string", - "description": "This is the ISO 8601 date-time string of when the test was created." + "type": "string" }, "updatedAt": { "format": "date-time", - "type": "string", - "description": "This is the ISO 8601 date-time string of when the test was last updated." + "type": "string" }, "name": { "type": "string", - "description": "This is the name of the test.", + "description": "This is the name of the eval.\nIt helps identify what the eval is checking for.", + "example": "Verified User Flow Eval", + "minLength": 1, "maxLength": 80 - }, - "script": { - "type": "string", - "description": "This is the script to be used for the chat test.", - "maxLength": 10000 - }, - "numAttempts": { - "type": "number", - "description": "This is the number of attempts allowed for the test.", - "minimum": 1, - "maximum": 10 + }, + "description": { + "type": "string", + "description": "This is the description of the eval.\nThis helps describe the eval and its purpose in detail. It will not be used to evaluate the flow of the conversation.", + "example": "This eval checks if the user flow is verified.", + "maxLength": 500 + }, + "type": { + "type": "string", + "description": "This is the type of the eval.\nCurrently it is fixed to `chat.mockConversation`.", + "example": "chat.mockConversation", + "enum": [ + "chat.mockConversation" + ] } }, "required": [ - "scorers", - "type", + "messages", "id", - "testSuiteId", "orgId", "createdAt", "updatedAt", - "script" + "type" ] }, - "CreateTestSuiteTestVoiceDto": { + "EvalModelListOptions": { "type": "object", "properties": { - "scorers": { + "provider": { + "type": "string", + "description": "This is the provider of the model.", + "enum": [ + "openai", + "anthropic", + "google", + "groq", + "custom-llm" + ] + } + }, + "required": [ + "provider" + ] + }, + "EvalUserEditable": { + "type": "object", + "properties": { + "messages": { "type": "array", - "description": "These are the scorers used to evaluate the test.", + "description": "This is the mock conversation that will be used to evaluate the flow of the conversation.\n\nMock Messages are used to simulate the flow of the conversation\n\nEvaluation Messages are used as checkpoints in the flow where the model's response to previous conversation needs to be evaluated to check the content and tool calls", + "example": "[{ role: \"user\", content: \"Hello, how are you?\" }, { role: \"assistant\", judgePlan: { type: \"exact\", content: \"I am good, thank you!\" } }]", "items": { "oneOf": [ { - "$ref": "#/components/schemas/TestSuiteTestScorerAI", - "title": "AI" + "$ref": "#/components/schemas/ChatEvalAssistantMessageMock", + "title": "ChatEvalAssistantMessageMock" + }, + { + "$ref": "#/components/schemas/ChatEvalSystemMessageMock", + "title": "ChatEvalSystemMessageMock" + }, + { + "$ref": "#/components/schemas/ChatEvalToolResponseMessageMock", + "title": "ChatEvalToolResponseMessageMock" + }, + { + "$ref": "#/components/schemas/ChatEvalToolResponseMessageEvaluation", + "title": "ChatEvalToolResponseMessageEvaluation" + }, + { + "$ref": "#/components/schemas/ChatEvalUserMessageMock", + "title": "ChatEvalUserMessageMock" + }, + { + "$ref": "#/components/schemas/ChatEvalAssistantMessageEvaluation", + "title": "ChatEvalAssistantMessageEvaluation" } ] } }, - "type": { + "name": { "type": "string", - "description": "This is the type of the test, which must be voice.", - "enum": [ - "voice" - ], - "maxLength": 100 + "description": "This is the name of the eval.\nIt helps identify what the eval is checking for.", + "example": "Verified User Flow Eval", + "minLength": 1, + "maxLength": 80 }, - "script": { + "description": { "type": "string", - "description": "This is the script to be used for the voice test.", - "maxLength": 10000 - }, - "numAttempts": { - "type": "number", - "description": "This is the number of attempts allowed for the test.", - "minimum": 1, - "maximum": 10 + "description": "This is the description of the eval.\nThis helps describe the eval and its purpose in detail. It will not be used to evaluate the flow of the conversation.", + "example": "This eval checks if the user flow is verified.", + "maxLength": 500 }, + "type": { + "type": "string", + "description": "This is the type of the eval.\nCurrently it is fixed to `chat.mockConversation`.", + "example": "chat.mockConversation", + "enum": [ + "chat.mockConversation" + ] + } + }, + "required": [ + "messages", + "type" + ] + }, + "ChatEvalAssistantMessageMockToolCall": { + "type": "object", + "properties": { "name": { "type": "string", - "description": "This is the name of the test.", - "maxLength": 80 + "description": "This is the name of the tool that will be called.\nIt should be one of the tools created in the organization.", + "example": "get_weather", + "maxLength": 100 + }, + "arguments": { + "type": "object", + "description": "This is the arguments that will be passed to the tool call.", + "example": "\"{\"city\": \"San Francisco\"}\"" } }, "required": [ - "scorers", - "type", - "script" + "name" ] }, - "CreateTestSuiteTestChatDto": { + "ChatEvalAssistantMessageMock": { "type": "object", "properties": { - "scorers": { + "role": { + "type": "string", + "enum": [ + "assistant" + ], + "description": "This is the role of the message author.\nFor a mock assistant message, the role is always 'assistant'\n@default 'assistant'", + "default": "assistant" + }, + "content": { + "type": "string", + "description": "This is the content of the assistant message.\nThis is the message that the assistant would have sent.", + "example": "The weather in San Francisco is sunny.", + "maxLength": 1000 + }, + "toolCalls": { + "description": "This is the tool calls that will be made by the assistant.", + "example": "[{ name: \"get_weather\", arguments: { city: \"San Francisco\" } }]", "type": "array", - "description": "These are the scorers used to evaluate the test.", "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/TestSuiteTestScorerAI", - "title": "AI" - } - ] + "$ref": "#/components/schemas/ChatEvalAssistantMessageMockToolCall" } - }, - "type": { + } + }, + "required": [ + "role" + ] + }, + "ChatEvalSystemMessageMock": { + "type": "object", + "properties": { + "role": { "type": "string", - "description": "This is the type of the test, which must be chat.", "enum": [ - "chat" + "system" ], - "maxLength": 100 + "description": "This is the role of the message author.\nFor a mock system message, the role is always 'system'\n@default 'system'", + "default": "system" }, - "script": { + "content": { "type": "string", - "description": "This is the script to be used for the chat test.", - "maxLength": 10000 + "description": "This is the content of the system message that would have been added in the middle of the conversation.\nDo not include the assistant prompt as a part of this message. It will automatically be fetched during runtime.", + "example": "You are a helpful assistant." + } + }, + "required": [ + "role", + "content" + ] + }, + "ChatEvalToolResponseMessageMock": { + "type": "object", + "properties": { + "role": { + "type": "string", + "enum": [ + "tool" + ], + "description": "This is the role of the message author.\nFor a mock tool response message, the role is always 'tool'\n@default 'tool'", + "default": "tool" }, - "numAttempts": { - "type": "number", - "description": "This is the number of attempts allowed for the test.", - "minimum": 1, - "maximum": 10 + "content": { + "type": "string", + "description": "This is the content of the tool response message. JSON Objects should be stringified.", + "examples": [ + "The weather in San Francisco is sunny.", + "{weather: sunny}" + ] + } + }, + "required": [ + "role", + "content" + ] + }, + "ChatEvalUserMessageMock": { + "type": "object", + "properties": { + "role": { + "type": "string", + "enum": [ + "user" + ], + "description": "This is the role of the message author.\nFor a mock user message, the role is always 'user'\n@default 'user'", + "default": "user" }, - "name": { + "content": { "type": "string", - "description": "This is the name of the test.", - "maxLength": 80 + "description": "This is the content of the user message.\nThis is the message that the user would have sent.", + "example": "Hello, how are you?", + "maxLength": 1000 } }, "required": [ - "scorers", - "type", - "script" + "role", + "content" ] }, - "UpdateTestSuiteTestVoiceDto": { + "AssistantMessageEvaluationContinuePlan": { "type": "object", "properties": { - "scorers": { + "exitOnFailureEnabled": { + "type": "boolean", + "description": "This is whether the evaluation should exit if the assistant message evaluates to false.\nBy default, it is false and the evaluation will continue.\n@default false" + }, + "contentOverride": { + "type": "string", + "description": "This is the content that will be used in the conversation for this assistant turn moving forward if provided.\nIt will override the content received from the model.", + "example": "The weather in San Francisco is sunny.", + "maxLength": 1000 + }, + "toolCallsOverride": { + "description": "This is the tool calls that will be used in the conversation for this assistant turn moving forward if provided.\nIt will override the tool calls received from the model.", + "example": "[{ name: \"get_weather\", arguments: { city: \"San Francisco\" } }]", "type": "array", - "description": "These are the scorers used to evaluate the test.", "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/TestSuiteTestScorerAI", - "title": "AI" - } - ] + "$ref": "#/components/schemas/ChatEvalAssistantMessageMockToolCall" } - }, - "type": { + } + } + }, + "ChatEvalAssistantMessageEvaluation": { + "type": "object", + "properties": { + "role": { "type": "string", - "description": "This is the type of the test, which must be voice.", "enum": [ - "voice" + "assistant" ], - "maxLength": 100 + "description": "This is the role of the message author.\nFor an assistant message evaluation, the role is always 'assistant'\n@default 'assistant'", + "default": "assistant" }, - "name": { + "judgePlan": { + "description": "This is the judge plan that instructs how to evaluate the assistant message.\nThe assistant message can be evaluated against fixed content (exact match or RegEx) or with an LLM-as-judge by defining the evaluation criteria in a prompt.", + "oneOf": [ + { + "$ref": "#/components/schemas/AssistantMessageJudgePlanExact", + "title": "AssistantMessageJudgePlanExact" + }, + { + "$ref": "#/components/schemas/AssistantMessageJudgePlanRegex", + "title": "AssistantMessageJudgePlanRegex" + }, + { + "$ref": "#/components/schemas/AssistantMessageJudgePlanAI", + "title": "AssistantMessageJudgePlanAI" + } + ] + }, + "continuePlan": { + "description": "This is the plan for how the overall evaluation will proceed after the assistant message is evaluated.\nThis lets you configure whether to stop the evaluation if this message fails, and whether to override any content for future turns", + "allOf": [ + { + "$ref": "#/components/schemas/AssistantMessageEvaluationContinuePlan" + } + ] + } + }, + "required": [ + "role", + "judgePlan" + ] + }, + "EvalOpenAIModel": { + "type": "object", + "properties": { + "provider": { "type": "string", - "description": "This is the name of the test.", - "maxLength": 80 + "description": "This is the provider of the model (`openai`).", + "enum": [ + "openai" + ] }, - "script": { + "model": { "type": "string", - "description": "This is the script to be used for the voice test.", - "maxLength": 10000 + "description": "This is the OpenAI model that will be used.\n\nWhen using Vapi OpenAI or your own Azure Credentials, you have the option to specify the region for the selected model. This shouldn't be specified unless you have a specific reason to do so. Vapi will automatically find the fastest region that make sense.\nThis is helpful when you are required to comply with Data Residency rules. Learn more about Azure regions here https://azure.microsoft.com/en-us/explore/global-infrastructure/data-residency/.", + "maxLength": 100, + "enum": [ + "gpt-5.6-sol", + "gpt-5.6-terra", + "gpt-5.6-luna", + "gpt-5.5", + "chat-latest", + "gpt-5.4", + "gpt-5.4-mini", + "gpt-5.4-nano", + "gpt-5.2", + "gpt-5.2-chat-latest", + "gpt-5.1", + "gpt-5.1-chat-latest", + "gpt-5", + "gpt-5-chat-latest", + "gpt-5-mini", + "gpt-5-nano", + "gpt-4.1-2025-04-14", + "gpt-4.1-mini-2025-04-14", + "gpt-4.1-nano-2025-04-14", + "gpt-4.1", + "gpt-4.1-mini", + "gpt-4.1-nano", + "chatgpt-4o-latest", + "o3", + "o3-mini", + "o4-mini", + "o1-mini", + "o1-mini-2024-09-12", + "gpt-4o-mini-2024-07-18", + "gpt-4o-mini", + "gpt-4o", + "gpt-4o-2024-05-13", + "gpt-4o-2024-08-06", + "gpt-4o-2024-11-20", + "gpt-4-turbo", + "gpt-4-turbo-2024-04-09", + "gpt-4-turbo-preview", + "gpt-4-0125-preview", + "gpt-4-1106-preview", + "gpt-4", + "gpt-4-0613", + "gpt-3.5-turbo", + "gpt-3.5-turbo-0125", + "gpt-3.5-turbo-1106", + "gpt-3.5-turbo-16k", + "gpt-3.5-turbo-0613", + "gpt-5.6-luna:westus3", + "gpt-5.6-terra:westus3", + "gpt-5.6-sol:westus3", + "gpt-5.4:eastus2", + "gpt-5.4:swedencentral", + "gpt-5.4-mini:eastus2", + "gpt-5.4-mini:swedencentral", + "gpt-5.4-nano:eastus2", + "gpt-5.4-nano:swedencentral", + "gpt-5.2:eastus2", + "gpt-5.2:swedencentral", + "gpt-5.1:eastus2", + "gpt-5.1:swedencentral", + "gpt-5:eastus2", + "gpt-5:swedencentral", + "gpt-5:canadaeast", + "gpt-5:eastus", + "gpt-5:westeurope", + "gpt-5:germanywestcentral", + "gpt-5:polandcentral", + "gpt-5:spaincentral", + "gpt-5-mini:eastus2", + "gpt-5-mini:swedencentral", + "gpt-5-mini:westeurope", + "gpt-5-mini:germanywestcentral", + "gpt-5-mini:polandcentral", + "gpt-5-mini:spaincentral", + "gpt-5-nano:eastus2", + "gpt-5-nano:swedencentral", + "gpt-4.1-2025-04-14:westus", + "gpt-4.1-2025-04-14:eastus2", + "gpt-4.1-2025-04-14:eastus", + "gpt-4.1-2025-04-14:westus3", + "gpt-4.1-2025-04-14:northcentralus", + "gpt-4.1-2025-04-14:southcentralus", + "gpt-4.1-2025-04-14:westeurope", + "gpt-4.1-2025-04-14:germanywestcentral", + "gpt-4.1-2025-04-14:polandcentral", + "gpt-4.1-2025-04-14:spaincentral", + "gpt-4.1-mini-2025-04-14:westus", + "gpt-4.1-mini-2025-04-14:eastus2", + "gpt-4.1-mini-2025-04-14:eastus", + "gpt-4.1-mini-2025-04-14:westus3", + "gpt-4.1-mini-2025-04-14:northcentralus", + "gpt-4.1-mini-2025-04-14:southcentralus", + "gpt-4.1-mini-2025-04-14:westeurope", + "gpt-4.1-mini-2025-04-14:germanywestcentral", + "gpt-4.1-mini-2025-04-14:polandcentral", + "gpt-4.1-mini-2025-04-14:spaincentral", + "gpt-4.1-nano-2025-04-14:westus", + "gpt-4.1-nano-2025-04-14:eastus2", + "gpt-4.1-nano-2025-04-14:westus3", + "gpt-4.1-nano-2025-04-14:northcentralus", + "gpt-4.1-nano-2025-04-14:southcentralus", + "gpt-4o-2024-11-20:swedencentral", + "gpt-4o-2024-11-20:westus", + "gpt-4o-2024-11-20:eastus2", + "gpt-4o-2024-11-20:eastus", + "gpt-4o-2024-11-20:westus3", + "gpt-4o-2024-11-20:southcentralus", + "gpt-4o-2024-11-20:westeurope", + "gpt-4o-2024-11-20:germanywestcentral", + "gpt-4o-2024-11-20:polandcentral", + "gpt-4o-2024-11-20:spaincentral", + "gpt-4o-2024-08-06:westus", + "gpt-4o-2024-08-06:westus3", + "gpt-4o-2024-08-06:eastus", + "gpt-4o-2024-08-06:eastus2", + "gpt-4o-2024-08-06:northcentralus", + "gpt-4o-2024-08-06:southcentralus", + "gpt-4o-mini-2024-07-18:westus", + "gpt-4o-mini-2024-07-18:westus3", + "gpt-4o-mini-2024-07-18:eastus", + "gpt-4o-mini-2024-07-18:eastus2", + "gpt-4o-mini-2024-07-18:northcentralus", + "gpt-4o-mini-2024-07-18:southcentralus", + "gpt-4o-2024-05-13:eastus2", + "gpt-4o-2024-05-13:eastus", + "gpt-4o-2024-05-13:northcentralus", + "gpt-4o-2024-05-13:southcentralus", + "gpt-4o-2024-05-13:westus3", + "gpt-4o-2024-05-13:westus", + "gpt-4-turbo-2024-04-09:eastus2", + "gpt-4-0125-preview:eastus", + "gpt-4-0125-preview:northcentralus", + "gpt-4-0125-preview:southcentralus", + "gpt-4-1106-preview:australiaeast", + "gpt-4-1106-preview:canadaeast", + "gpt-4-1106-preview:france", + "gpt-4-1106-preview:india", + "gpt-4-1106-preview:norway", + "gpt-4-1106-preview:swedencentral", + "gpt-4-1106-preview:uk", + "gpt-4-1106-preview:westus", + "gpt-4-1106-preview:westus3", + "gpt-4-0613:canadaeast", + "gpt-3.5-turbo-0125:canadaeast", + "gpt-3.5-turbo-0125:northcentralus", + "gpt-3.5-turbo-0125:southcentralus", + "gpt-3.5-turbo-1106:canadaeast", + "gpt-3.5-turbo-1106:westus", + "gpt-4.1:australiaeast", + "gpt-4o:australiaeast", + "gpt-5.4-mini:australiaeast" + ] }, - "numAttempts": { + "temperature": { "type": "number", - "description": "This is the number of attempts allowed for the test.", - "minimum": 1, - "maximum": 10 + "description": "This is the temperature of the model. For LLM-as-a-judge, it's recommended to set it between 0 - 0.3 to avoid hallucinations and ensure the model judges the output correctly based on the instructions.", + "minimum": 0, + "maximum": 2 + }, + "maxTokens": { + "type": "number", + "description": "This is the max tokens of the model.\nIf your Judge instructions return `true` or `false` takes only 1 token (as per the OpenAI Tokenizer), and therefore is recommended to set it to a low number to force the model to return a short response.", + "minimum": 50, + "maximum": 10000 + }, + "messages": { + "description": "These are the messages which will instruct the AI Judge on how to evaluate the assistant message.\nThe LLM-Judge must respond with \"pass\" or \"fail\" to indicate if the assistant message passes the eval.\n\nTo access the messages in the mock conversation, use the LiquidJS variable `{{messages}}`.\nThe assistant message to be evaluated will be passed as the last message in the `messages` array and can be accessed using `{{messages[-1]}}`.\n\nIt is recommended to use the system message to instruct the LLM how to evaluate the assistant message, and then use the first user message to pass the assistant message to be evaluated.", + "example": "{", + "type": "array", + "items": { + "type": "object" + } } - } + }, + "required": [ + "provider", + "model", + "messages" + ] }, - "UpdateTestSuiteTestChatDto": { + "EvalAnthropicModel": { "type": "object", "properties": { - "scorers": { - "type": "array", - "description": "These are the scorers used to evaluate the test.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/TestSuiteTestScorerAI", - "title": "AI" - } - ] - } - }, - "type": { + "provider": { "type": "string", - "description": "This is the type of the test, which must be chat.", + "description": "This is the provider of the model (`anthropic`).", "enum": [ - "chat" - ], - "maxLength": 100 + "anthropic" + ] }, - "name": { + "model": { "type": "string", - "description": "This is the name of the test.", - "maxLength": 80 + "description": "This is the specific model that will be used.", + "maxLength": 100, + "enum": [ + "claude-3-opus-20240229", + "claude-3-sonnet-20240229", + "claude-3-haiku-20240307", + "claude-3-5-sonnet-20240620", + "claude-3-5-sonnet-20241022", + "claude-3-5-haiku-20241022", + "claude-3-7-sonnet-20250219", + "claude-opus-4-20250514", + "claude-opus-4-5-20251101", + "claude-opus-4-6", + "claude-sonnet-4-20250514", + "claude-sonnet-4-5-20250929", + "claude-sonnet-4-6", + "claude-sonnet-5", + "claude-haiku-4-5-20251001" + ] }, - "script": { - "type": "string", - "description": "This is the script to be used for the chat test.", - "maxLength": 10000 + "thinking": { + "description": "This is the optional configuration for Anthropic's thinking feature.\n\n- If provided, `maxTokens` must be greater than `thinking.budgetTokens`.", + "allOf": [ + { + "$ref": "#/components/schemas/AnthropicThinkingConfig" + } + ] }, - "numAttempts": { + "temperature": { "type": "number", - "description": "This is the number of attempts allowed for the test.", - "minimum": 1, - "maximum": 10 + "description": "This is the temperature of the model. For LLM-as-a-judge, it's recommended to set it between 0 - 0.3 to avoid hallucinations and ensure the model judges the output correctly based on the instructions.", + "minimum": 0, + "maximum": 2 + }, + "maxTokens": { + "type": "number", + "description": "This is the max tokens of the model.\nIf your Judge instructions return `true` or `false` takes only 1 token (as per the OpenAI Tokenizer), and therefore is recommended to set it to a low number to force the model to return a short response.", + "minimum": 50, + "maximum": 10000 + }, + "messages": { + "description": "These are the messages which will instruct the AI Judge on how to evaluate the assistant message.\nThe LLM-Judge must respond with \"pass\" or \"fail\" to indicate if the assistant message passes the eval.\n\nTo access the messages in the mock conversation, use the LiquidJS variable `{{messages}}`.\nThe assistant message to be evaluated will be passed as the last message in the `messages` array and can be accessed using `{{messages[-1]}}`.\n\nIt is recommended to use the system message to instruct the LLM how to evaluate the assistant message, and then use the first user message to pass the assistant message to be evaluated.", + "example": "{", + "type": "array", + "items": { + "type": "object" + } } - } + }, + "required": [ + "provider", + "model", + "messages" + ] }, - "TestSuiteTestScorerAI": { + "EvalGoogleModel": { "type": "object", "properties": { - "type": { + "provider": { "type": "string", - "description": "This is the type of the scorer, which must be AI.", + "description": "This is the provider of the model (`google`).", "enum": [ - "ai" - ], - "maxLength": 100 + "google" + ] }, - "rubric": { + "model": { "type": "string", - "description": "This is the rubric used by the AI scorer.", - "maxLength": 10000 + "description": "This is the name of the model. Ex. gpt-4o", + "maxLength": 100, + "enum": [ + "gemini-3.5-flash", + "gemini-3.1-flash-lite", + "gemini-3-flash-preview", + "gemini-2.5-pro", + "gemini-2.5-flash", + "gemini-2.5-flash-lite", + "gemini-2.0-flash-thinking-exp", + "gemini-2.0-pro-exp-02-05", + "gemini-2.0-flash", + "gemini-2.0-flash-lite", + "gemini-2.0-flash-exp", + "gemini-2.0-flash-realtime-exp", + "gemini-1.5-flash", + "gemini-1.5-flash-002", + "gemini-1.5-pro", + "gemini-1.5-pro-002", + "gemini-1.0-pro" + ] + }, + "temperature": { + "type": "number", + "description": "This is the temperature of the model. For LLM-as-a-judge, it's recommended to set it between 0 - 0.3 to avoid hallucinations and ensure the model judges the output correctly based on the instructions.", + "minimum": 0, + "maximum": 2 + }, + "maxTokens": { + "type": "number", + "description": "This is the max tokens of the model.\nIf your Judge instructions return `true` or `false` takes only 1 token (as per the OpenAI Tokenizer), and therefore is recommended to set it to a low number to force the model to return a short response.", + "minimum": 50, + "maximum": 10000 + }, + "messages": { + "description": "These are the messages which will instruct the AI Judge on how to evaluate the assistant message.\nThe LLM-Judge must respond with \"pass\" or \"fail\" to indicate if the assistant message passes the eval.\n\nTo access the messages in the mock conversation, use the LiquidJS variable `{{messages}}`.\nThe assistant message to be evaluated will be passed as the last message in the `messages` array and can be accessed using `{{messages[-1]}}`.\n\nIt is recommended to use the system message to instruct the LLM how to evaluate the assistant message, and then use the first user message to pass the assistant message to be evaluated.", + "example": "{", + "type": "array", + "items": { + "type": "object" + } } }, "required": [ - "type", - "rubric" + "provider", + "model", + "messages" ] }, - "TestSuiteTestsPaginatedResponse": { + "EvalGroqModel": { "type": "object", "properties": { - "results": { + "provider": { + "type": "string", + "description": "This is the provider of the model (`groq`).", + "enum": [ + "groq" + ] + }, + "model": { + "type": "string", + "description": "This is the name of the model. Ex. gpt-4o", + "maxLength": 100, + "enum": [ + "openai/gpt-oss-20b", + "openai/gpt-oss-120b", + "deepseek-r1-distill-llama-70b", + "llama-3.3-70b-versatile", + "llama-3.1-405b-reasoning", + "llama-3.1-8b-instant", + "llama3-8b-8192", + "llama3-70b-8192", + "gemma2-9b-it", + "moonshotai/kimi-k2-instruct-0905", + "meta-llama/llama-4-scout-17b-16e-instruct", + "mistral-saba-24b", + "compound-beta", + "compound-beta-mini" + ] + }, + "temperature": { + "type": "number", + "description": "This is the temperature of the model. For LLM-as-a-judge, it's recommended to set it between 0 - 0.3 to avoid hallucinations and ensure the model judges the output correctly based on the instructions.", + "minimum": 0, + "maximum": 2 + }, + "maxTokens": { + "type": "number", + "description": "This is the max tokens of the model.\nIf your Judge instructions return `true` or `false` takes only 1 token (as per the OpenAI Tokenizer), and therefore is recommended to set it to a low number to force the model to return a short response.", + "minimum": 50, + "maximum": 10000 + }, + "messages": { + "description": "These are the messages which will instruct the AI Judge on how to evaluate the assistant message.\nThe LLM-Judge must respond with \"pass\" or \"fail\" to indicate if the assistant message passes the eval.\n\nTo access the messages in the mock conversation, use the LiquidJS variable `{{messages}}`.\nThe assistant message to be evaluated will be passed as the last message in the `messages` array and can be accessed using `{{messages[-1]}}`.\n\nIt is recommended to use the system message to instruct the LLM how to evaluate the assistant message, and then use the first user message to pass the assistant message to be evaluated.", + "example": "{", "type": "array", - "description": "A list of test suite tests.", "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/TestSuiteTestVoice" - }, - { - "$ref": "#/components/schemas/TestSuiteTestChat" - } - ] + "type": "object" } - }, - "metadata": { - "description": "Metadata about the pagination.", - "allOf": [ - { - "$ref": "#/components/schemas/PaginationMeta" - } - ] } }, "required": [ - "results", - "metadata" + "provider", + "model", + "messages" ] }, - "TestSuiteRunScorerAI": { + "EvalCustomModel": { "type": "object", "properties": { - "type": { + "provider": { "type": "string", - "description": "This is the type of the scorer, which must be AI.", + "description": "This is the provider of the model (`custom-llm`).", "enum": [ - "ai" - ], - "maxLength": 100 + "custom-llm" + ] }, - "result": { + "url": { "type": "string", - "description": "This is the result of the test suite.", - "enum": [ - "pass", - "fail" - ], - "maxLength": 100 + "description": "These is the URL we'll use for the OpenAI client's `baseURL`. Ex. https://openrouter.ai/api/v1" }, - "reasoning": { - "type": "string", - "description": "This is the reasoning provided by the AI scorer.", - "maxLength": 10000 + "headers": { + "type": "object", + "description": "These are the headers we'll use for the OpenAI client's `headers`." }, - "rubric": { + "timeoutSeconds": { + "type": "number", + "description": "This sets the timeout for the connection to the custom provider without needing to stream any tokens back. Default is 20 seconds.", + "minimum": 20, + "maximum": 600 + }, + "model": { "type": "string", - "description": "This is the rubric used by the AI scorer.", - "maxLength": 10000 + "description": "This is the name of the model. Ex. gpt-4o", + "maxLength": 100 + }, + "temperature": { + "type": "number", + "description": "This is the temperature of the model. For LLM-as-a-judge, it's recommended to set it between 0 - 0.3 to avoid hallucinations and ensure the model judges the output correctly based on the instructions.", + "minimum": 0, + "maximum": 2 + }, + "maxTokens": { + "type": "number", + "description": "This is the max tokens of the model.\nIf your Judge instructions return `true` or `false` takes only 1 token (as per the OpenAI Tokenizer), and therefore is recommended to set it to a low number to force the model to return a short response.", + "minimum": 50, + "maximum": 10000 + }, + "messages": { + "description": "These are the messages which will instruct the AI Judge on how to evaluate the assistant message.\nThe LLM-Judge must respond with \"pass\" or \"fail\" to indicate if the assistant message passes the eval.\n\nTo access the messages in the mock conversation, use the LiquidJS variable `{{messages}}`.\nThe assistant message to be evaluated will be passed as the last message in the `messages` array and can be accessed using `{{messages[-1]}}`.\n\nIt is recommended to use the system message to instruct the LLM how to evaluate the assistant message, and then use the first user message to pass the assistant message to be evaluated.", + "example": "{", + "type": "array", + "items": { + "type": "object" + } } }, "required": [ - "type", - "result", - "reasoning", - "rubric" + "provider", + "url", + "model", + "messages" ] }, - "TestSuiteRunTestAttemptCall": { + "AssistantMessageJudgePlanAI": { "type": "object", "properties": { - "artifact": { - "description": "This is the artifact of the call.", - "allOf": [ + "model": { + "description": "This is the model to use for the LLM-as-a-judge.\nIf not provided, will default to the assistant's model.\n\nThe instructions on how to evaluate the model output with this LLM-Judge must be passed as a system message in the messages array of the model.\n\nThe Mock conversation can be passed to the LLM-Judge to evaluate using the prompt {{messages}} and will be evaluated as a LiquidJS Variable. To access and judge only the last message, use {{messages[-1]}}\n\nThe LLM-Judge must respond with \"pass\" or \"fail\" and only those two responses are allowed.", + "example": "{", + "oneOf": [ { - "$ref": "#/components/schemas/Artifact" + "$ref": "#/components/schemas/EvalOpenAIModel", + "title": "EvalOpenAIModel" + }, + { + "$ref": "#/components/schemas/EvalAnthropicModel", + "title": "EvalAnthropicModel" + }, + { + "$ref": "#/components/schemas/EvalGoogleModel", + "title": "EvalGoogleModel" + }, + { + "$ref": "#/components/schemas/EvalCustomModel", + "title": "EvalCustomModel" } ] + }, + "type": { + "type": "string", + "enum": [ + "ai" + ], + "description": "This is the type of the judge plan.\nUse 'ai' to evaluate the assistant message content using LLM-as-a-judge.\n@default 'ai'" + }, + "autoIncludeMessageHistory": { + "type": "boolean", + "description": "This is the flag to enable automatically adding the liquid variable {{messages}} to the model's messages array\nThis is only applicable if the user has not provided any messages in the model's messages array\n@default true" } }, "required": [ - "artifact" + "model", + "type" ] }, - "TestSuiteRunTestAttemptMetadata": { + "ChatEvalToolResponseMessageEvaluation": { "type": "object", "properties": { - "sessionId": { + "role": { "type": "string", - "description": "This is the session ID for the test attempt." + "enum": [ + "tool" + ], + "description": "This is the role of the message author.\nFor a tool response message evaluation, the role is always 'tool'\n@default 'tool'", + "default": "tool" + }, + "judgePlan": { + "description": "This is the judge plan that instructs how to evaluate the tool response message.\nThe tool response message can be evaluated with an LLM-as-judge by defining the evaluation criteria in a prompt.", + "oneOf": [ + { + "$ref": "#/components/schemas/AssistantMessageJudgePlanAI", + "title": "AssistantMessageJudgePlanAI" + } + ], + "allOf": [ + { + "$ref": "#/components/schemas/AssistantMessageJudgePlanAI" + } + ] } }, "required": [ - "sessionId" + "role", + "judgePlan" ] }, - "TestSuiteRunTestAttempt": { + "AssistantMessageJudgePlanExact": { "type": "object", "properties": { - "scorerResults": { - "type": "array", - "description": "These are the results of the scorers used to evaluate the test attempt.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/TestSuiteRunScorerAI", - "title": "AI" - } - ] - } - }, - "call": { - "description": "This is the call made during the test attempt.", - "allOf": [ - { - "$ref": "#/components/schemas/TestSuiteRunTestAttemptCall" - } - ] + "type": { + "type": "string", + "enum": [ + "exact" + ], + "description": "This is the type of the judge plan.\nUse 'exact' for an exact match on the content and tool calls - without using LLM-as-a-judge.\n@default 'exact'" }, - "callId": { + "content": { "type": "string", - "description": "This is the call ID for the test attempt." + "description": "This is what that will be used to evaluate the model's message content.\nIf you provide a string, the assistant message content will be evaluated against it as an exact match, case-insensitive.", + "example": "The weather in San Francisco is sunny.", + "maxLength": 1000 }, - "metadata": { - "description": "This is the metadata for the test attempt.", - "allOf": [ - { - "$ref": "#/components/schemas/TestSuiteRunTestAttemptMetadata" - } - ] + "toolCalls": { + "description": "This is the tool calls that will be used to evaluate the model's message content.\nThe tool name must be a valid tool that the assistant is allowed to call.\n\nFor the Query tool, the arguments for the tool call are in the format - {knowledgeBaseNames: ['kb_name', 'kb_name_2']}\n\nFor the DTMF tool, the arguments for the tool call are in the format - {dtmf: \"1234*\"}\n\nFor the Handoff tool, the arguments for the tool call are in the format - {destination: \"assistant_id\"}\n\nFor the Transfer Call tool, the arguments for the tool call are in the format - {destination: \"phone_number_or_assistant_id\"}\n\nFor all other tools, they are called without arguments or with user-defined arguments", + "example": "[{ name: \"get_weather\", arguments: { city: \"San Francisco\" } }]", + "type": "array", + "items": { + "$ref": "#/components/schemas/ChatEvalAssistantMessageMockToolCall" + } } }, "required": [ - "scorerResults" + "type", + "content" ] }, - "TestSuiteRunTestResult": { + "AssistantMessageJudgePlanRegex": { "type": "object", "properties": { - "test": { - "description": "This is the test that was run.", - "oneOf": [ - { - "$ref": "#/components/schemas/TestSuiteTestVoice", - "title": "TestSuiteTestVoice" - } - ] + "type": { + "type": "string", + "enum": [ + "regex" + ], + "description": "This is the type of the judge plan.\nUse 'regex' for a regex match on the content and tool calls - without using LLM-as-a-judge.\n@default 'regex'" }, - "attempts": { - "description": "These are the attempts made for this test.", + "content": { + "type": "string", + "description": "This is what that will be used to evaluate the model's message content.\nThe content will be evaluated against the regex pattern provided in the Judge Plan content field.\nEvaluation is considered successful if the regex pattern matches any part of the assistant message content.", + "example": "/sunny/i", + "maxLength": 1000 + }, + "toolCalls": { + "description": "This is the tool calls that will be used to evaluate the model's message content.\nThe tool name must be a valid tool that the assistant is allowed to call.\nThe values to the arguments for the tool call should be a Regular Expression.\nEvaluation is considered successful if the regex pattern matches any part of each tool call argument.\n\nFor the Query tool, the arguments for the tool call are in the format - {knowledgeBaseNames: ['kb_name', 'kb_name_2']}\n\nFor the DTMF tool, the arguments for the tool call are in the format - {dtmf: \"1234*\"}\n\nFor the Handoff tool, the arguments for the tool call are in the format - {destination: \"assistant_id\"}\n\nFor the Transfer Call tool, the arguments for the tool call are in the format - {destination: \"phone_number_or_assistant_id\"}\n\nFor all other tools, they are called without arguments or with user-defined arguments", + "example": "[{ name: \"get_weather\", arguments: { city: \"/San Francisco/i\" } }]", "type": "array", "items": { - "$ref": "#/components/schemas/TestSuiteRunTestAttempt" + "$ref": "#/components/schemas/ChatEvalAssistantMessageMockToolCall" } } }, "required": [ - "test", - "attempts" + "type", + "content" ] }, - "TestSuiteRun": { + "GetEvalPaginatedDTO": { "type": "object", "properties": { - "status": { + "id": { + "type": "string" + }, + "page": { + "type": "number", + "description": "This is the page number to return. Defaults to 1.", + "minimum": 1 + }, + "sortOrder": { "type": "string", - "description": "This is the current status of the test suite run.", + "description": "This is the sort order for pagination. Defaults to 'DESC'.", "enum": [ - "queued", - "in-progress", - "completed", - "failed" + "ASC", + "DESC" ] }, - "id": { + "sortBy": { "type": "string", - "description": "This is the unique identifier for the test suite run." + "description": "This is the column to sort by. Defaults to 'createdAt'.", + "enum": [ + "createdAt", + "duration", + "cost" + ] }, - "orgId": { + "limit": { + "type": "number", + "description": "This is the maximum number of items to return. Defaults to 100.", + "minimum": 0, + "maximum": 1000 + }, + "createdAtGt": { + "format": "date-time", "type": "string", - "description": "This is the unique identifier for the organization this run belongs to." + "description": "This will return items where the createdAt is greater than the specified value." }, - "testSuiteId": { + "createdAtLt": { + "format": "date-time", "type": "string", - "description": "This is the unique identifier for the test suite this run belongs to." + "description": "This will return items where the createdAt is less than the specified value." }, - "createdAt": { + "createdAtGe": { "format": "date-time", "type": "string", - "description": "This is the ISO 8601 date-time string of when the test suite run was created." + "description": "This will return items where the createdAt is greater than or equal to the specified value." }, - "updatedAt": { + "createdAtLe": { "format": "date-time", "type": "string", - "description": "This is the ISO 8601 date-time string of when the test suite run was last updated." + "description": "This will return items where the createdAt is less than or equal to the specified value." }, - "testResults": { - "description": "These are the results of the tests in this test suite run.", - "type": "array", - "items": { - "$ref": "#/components/schemas/TestSuiteRunTestResult" - } + "updatedAtGt": { + "format": "date-time", + "type": "string", + "description": "This will return items where the updatedAt is greater than the specified value." }, - "name": { + "updatedAtLt": { + "format": "date-time", "type": "string", - "description": "This is the name of the test suite run.", - "maxLength": 80 + "description": "This will return items where the updatedAt is less than the specified value." + }, + "updatedAtGe": { + "format": "date-time", + "type": "string", + "description": "This will return items where the updatedAt is greater than or equal to the specified value." + }, + "updatedAtLe": { + "format": "date-time", + "type": "string", + "description": "This will return items where the updatedAt is less than or equal to the specified value." } - }, - "required": [ - "status", - "id", - "orgId", - "testSuiteId", - "createdAt", - "updatedAt", - "testResults" - ] + } }, - "TestSuiteRunsPaginatedResponse": { + "EvalPaginatedResponse": { "type": "object", "properties": { "results": { "type": "array", "items": { - "$ref": "#/components/schemas/TestSuiteRun" + "$ref": "#/components/schemas/Eval" } }, "metadata": { @@ -38765,259 +64627,301 @@ "metadata" ] }, - "CreateTestSuiteRunDto": { - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "This is the name of the test suite run.", - "maxLength": 80 - } - } - }, - "UpdateTestSuiteRunDto": { + "UpdateEvalDTO": { "type": "object", "properties": { + "messages": { + "type": "array", + "description": "This is the mock conversation that will be used to evaluate the flow of the conversation.\n\nMock Messages are used to simulate the flow of the conversation\n\nEvaluation Messages are used as checkpoints in the flow where the model's response to previous conversation needs to be evaluated to check the content and tool calls", + "example": "[{ role: \"user\", content: \"Hello, how are you?\" }, { role: \"assistant\", judgePlan: { type: \"exact\", content: \"I am good, thank you!\" } }]", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/ChatEvalAssistantMessageMock", + "title": "ChatEvalAssistantMessageMock" + }, + { + "$ref": "#/components/schemas/ChatEvalSystemMessageMock", + "title": "ChatEvalSystemMessageMock" + }, + { + "$ref": "#/components/schemas/ChatEvalToolResponseMessageMock", + "title": "ChatEvalToolResponseMessageMock" + }, + { + "$ref": "#/components/schemas/ChatEvalToolResponseMessageEvaluation", + "title": "ChatEvalToolResponseMessageEvaluation" + }, + { + "$ref": "#/components/schemas/ChatEvalUserMessageMock", + "title": "ChatEvalUserMessageMock" + }, + { + "$ref": "#/components/schemas/ChatEvalAssistantMessageEvaluation", + "title": "ChatEvalAssistantMessageEvaluation" + } + ] + } + }, "name": { "type": "string", - "description": "This is the name of the test suite run.", + "description": "This is the name of the eval.\nIt helps identify what the eval is checking for.", + "example": "Verified User Flow Eval", + "minLength": 1, "maxLength": 80 - } - } - }, - "TimeRange": { - "type": "object", - "properties": { - "step": { - "type": "string", - "description": "This is the time step for aggregations.\n\nIf not provided, defaults to returning for the entire time range.", - "enum": [ - "second", - "minute", - "hour", - "day", - "week", - "month", - "quarter", - "year", - "decade", - "century", - "millennium" - ] - }, - "start": { - "format": "date-time", - "type": "string", - "description": "This is the start date for the time range.\n\nIf not provided, defaults to the 7 days ago." }, - "end": { - "format": "date-time", + "description": { "type": "string", - "description": "This is the end date for the time range.\n\nIf not provided, defaults to now." + "description": "This is the description of the eval.\nThis helps describe the eval and its purpose in detail. It will not be used to evaluate the flow of the conversation.", + "example": "This eval checks if the user flow is verified.", + "maxLength": 500 }, - "timezone": { + "type": { "type": "string", - "description": "This is the timezone you want to set for the query.\n\nIf not provided, defaults to UTC." + "description": "This is the type of the eval.\nCurrently it is fixed to `chat.mockConversation`.", + "example": "chat.mockConversation", + "enum": [ + "chat.mockConversation" + ] } } }, - "AnalyticsOperation": { + "CreateEvalRunDTO": { "type": "object", "properties": { - "operation": { - "type": "string", - "description": "This is the aggregation operation you want to perform.", - "enum": [ - "sum", - "avg", - "count", - "min", - "max", - "history" + "eval": { + "description": "This is the transient eval that will be run", + "oneOf": [ + { + "$ref": "#/components/schemas/CreateEvalDTO", + "title": "CreateEvalDTO" + } + ], + "allOf": [ + { + "$ref": "#/components/schemas/CreateEvalDTO" + } ] }, - "column": { + "target": { + "description": "This is the target that will be run against the eval", + "oneOf": [ + { + "$ref": "#/components/schemas/EvalRunTargetAssistant", + "title": "EvalRunTargetAssistant" + }, + { + "$ref": "#/components/schemas/EvalRunTargetSquad", + "title": "EvalRunTargetSquad" + } + ] + }, + "type": { "type": "string", - "description": "This is the columns you want to perform the aggregation operation on.", + "description": "This is the type of the run.\nCurrently it is fixed to `eval`.", + "example": "eval", "enum": [ - "id", - "cost", - "costBreakdown.llm", - "costBreakdown.stt", - "costBreakdown.tts", - "costBreakdown.vapi", - "costBreakdown.transport", - "costBreakdown.analysisBreakdown.summary", - "costBreakdown.transcriber", - "costBreakdown.ttsCharacters", - "costBreakdown.llmPromptTokens", - "costBreakdown.llmCompletionTokens", - "duration", - "concurrency", - "minutesUsed" + "eval" ] }, - "alias": { + "evalId": { "type": "string", - "description": "This is the alias for column name returned. Defaults to `${operation}${column}`.", - "maxLength": 40 + "description": "This is the id of the eval that will be run.", + "example": "123e4567-e89b-12d3-a456-426614174000" } }, "required": [ - "operation", - "column" + "target", + "type" ] }, - "AnalyticsQuery": { + "EvalRunResult": { "type": "object", "properties": { - "table": { + "status": { "type": "string", - "description": "This is the table you want to query.", + "description": "This is the status of the eval run result.\nThe status is only 'pass' or 'fail' for an eval run result.\nCurrently, An eval is considered `pass` only if all the Assistant Judge messages are evaluated to pass.", + "example": "pass", "enum": [ - "call", - "subscription" + "pass", + "fail" ] }, - "groupBy": { + "messages": { "type": "array", - "description": "This is the list of columns you want to group by.", - "enum": [ - "type", - "assistantId", - "endedReason", - "analysis.successEvaluation", - "status" - ], + "description": "This is the messages of the eval run result.\nIt contains the user/system messages", "items": { - "type": "string", - "enum": [ - "type", - "assistantId", - "endedReason", - "analysis.successEvaluation", - "status" + "oneOf": [ + { + "$ref": "#/components/schemas/ChatEvalUserMessageMock", + "title": "ChatEvalUserMessageMock" + }, + { + "$ref": "#/components/schemas/ChatEvalSystemMessageMock", + "title": "ChatEvalSystemMessageMock" + }, + { + "$ref": "#/components/schemas/ChatEvalToolResponseMessageMock", + "title": "ChatEvalToolResponseMessageMock" + }, + { + "$ref": "#/components/schemas/ChatEvalAssistantMessageMock", + "title": "ChatEvalAssistantMessageMock" + } ] } }, - "name": { + "startedAt": { + "format": "date-time", "type": "string", - "description": "This is the name of the query. This will be used to identify the query in the response.", - "maxLength": 40 - }, - "timeRange": { - "description": "This is the time range for the query.", - "allOf": [ - { - "$ref": "#/components/schemas/TimeRange" - } - ] + "description": "This is the start time of the eval run result.", + "example": "2021-01-01T00:00:00.000Z" }, - "operations": { - "description": "This is the list of operations you want to perform.", - "type": "array", - "items": { - "$ref": "#/components/schemas/AnalyticsOperation" - } - } - }, - "required": [ - "table", - "name", - "operations" - ] - }, - "AnalyticsQueryDTO": { - "type": "object", - "properties": { - "queries": { - "description": "This is the list of metric queries you want to perform.", - "type": "array", - "items": { - "$ref": "#/components/schemas/AnalyticsQuery" - } + "endedAt": { + "format": "date-time", + "type": "string", + "description": "This is the end time of the eval run result.", + "example": "2021-01-01T00:00:00.000Z" } }, "required": [ - "queries" + "status", + "messages", + "startedAt", + "endedAt" ] }, - "AnalyticsQueryResult": { + "EvalRun": { "type": "object", "properties": { - "name": { + "status": { "type": "string", - "description": "This is the unique key for the query." + "description": "This is the status of the eval run. When an eval run is created, the status is 'running'.\nWhen the eval run is completed, the status is 'ended'.", + "example": "running", + "enum": [ + "running", + "ended", + "queued" + ] }, - "timeRange": { - "description": "This is the time range for the query.", + "endedReason": { + "type": "string", + "description": "This is the reason for the eval run to end.\nWhen the eval run is completed normally i.e end of mock conversation, the status is 'mockConversation.done'.\nWhen the eval fails due to an error like Chat error or incorrect configuration, the status is 'error'.\nWhen the eval runs for too long, due to model issues or tool call issues, the status is 'timeout'.\nWhen the eval run is cancelled by the user, the status is 'cancelled'.\nWhen the eval run is cancelled by Vapi for any reason, the status is 'aborted'.", + "example": "mockConversation.done", + "enum": [ + "mockConversation.done", + "error", + "timeout", + "cancelled", + "aborted" + ] + }, + "eval": { + "description": "This is the transient eval that will be run", + "oneOf": [ + { + "$ref": "#/components/schemas/CreateEvalDTO", + "title": "CreateEvalDTO" + } + ], "allOf": [ { - "$ref": "#/components/schemas/TimeRange" + "$ref": "#/components/schemas/CreateEvalDTO" + } + ] + }, + "target": { + "description": "This is the target that will be run against the eval", + "oneOf": [ + { + "$ref": "#/components/schemas/EvalRunTargetAssistant", + "title": "EvalRunTargetAssistant" + }, + { + "$ref": "#/components/schemas/EvalRunTargetSquad", + "title": "EvalRunTargetSquad" } ] }, - "result": { - "description": "This is the result of the query, a list of unique groups with result of their aggregations.\n\nExample:\n\"result\": [\n { \"date\": \"2023-01-01\", \"assistantId\": \"123\", \"endedReason\": \"customer-ended-call\", \"sumDuration\": 120, \"avgCost\": 10.5 },\n { \"date\": \"2023-01-02\", \"assistantId\": \"123\", \"endedReason\": \"customer-did-not-give-microphone-permission\", \"sumDuration\": 0, \"avgCost\": 0 },\n // Additional results\n]", + "id": { + "type": "string" + }, + "orgId": { + "type": "string" + }, + "createdAt": { + "format": "date-time", + "type": "string" + }, + "startedAt": { + "format": "date-time", + "type": "string" + }, + "endedAt": { + "format": "date-time", + "type": "string" + }, + "endedMessage": { + "type": "string", + "description": "This is the ended message when the eval run ended for any reason apart from mockConversation.done", + "example": "The Assistant returned an error" + }, + "results": { + "description": "This is the results of the eval or suite run.\nThe array will have a single item for an eval run, and multiple items each corresponding to the an eval in a suite run in the same order as the evals in the suite.", "type": "array", "items": { - "type": "object" + "$ref": "#/components/schemas/EvalRunResult" } - } - }, - "required": [ - "name", - "timeRange", - "result" - ] - }, - "CallLogPrivileged": { - "type": "object", - "properties": { - "callId": { - "type": "string", - "description": "This is the unique identifier for the call." }, - "orgId": { - "type": "string", - "description": "This is the unique identifier for the org that this call log belongs to." + "cost": { + "type": "number", + "description": "This is the cost of the eval or suite run in USD.", + "example": 0.01 }, - "log": { - "type": "string", - "description": "This is the log message associated with the call." + "costs": { + "description": "This is the break up of costs of the eval or suite run.", + "example": "[{ type: \"model\", model: \"gpt-4o\", cost: 0.01 }]", + "type": "array", + "items": { + "type": "object" + } }, - "level": { + "type": { "type": "string", - "description": "This is the level of the log message.", + "description": "This is the type of the run.\nCurrently it is fixed to `eval`.", + "example": "eval", "enum": [ - "INFO", - "LOG", - "WARN", - "ERROR", - "CHECKPOINT" + "eval" ] }, - "time": { - "format": "date-time", + "evalId": { "type": "string", - "description": "This is the ISO 8601 date-time string of when the log was created." + "description": "This is the id of the eval that will be run.", + "example": "123e4567-e89b-12d3-a456-426614174000" } }, "required": [ - "callId", + "status", + "endedReason", + "target", + "id", "orgId", - "log", - "level", - "time" + "createdAt", + "startedAt", + "endedAt", + "results", + "cost", + "costs", + "type" ] }, - "CallLogsPaginatedResponse": { + "EvalRunPaginatedResponse": { "type": "object", "properties": { "results": { "type": "array", "items": { - "$ref": "#/components/schemas/CallLogPrivileged" + "$ref": "#/components/schemas/EvalRun" } }, "metadata": { @@ -39029,250 +64933,226 @@ "metadata" ] }, - "Error": { + "GetEvalRunPaginatedDTO": { "type": "object", "properties": { - "message": { + "id": { "type": "string" - } - }, - "required": [ - "message" - ] - }, - "Log": { - "type": "object", - "properties": { - "time": { - "type": "string", - "description": "This is the timestamp at which the log was written." }, - "orgId": { - "type": "string", - "description": "This is the unique identifier for the org that this log belongs to." + "page": { + "type": "number", + "description": "This is the page number to return. Defaults to 1.", + "minimum": 1 }, - "type": { + "sortOrder": { "type": "string", - "description": "This is the type of the log.", + "description": "This is the sort order for pagination. Defaults to 'DESC'.", "enum": [ - "API", - "Webhook", - "Call", - "Provider" + "ASC", + "DESC" ] }, - "webhookType": { - "type": "string", - "description": "This is the type of the webhook, given the log is from a webhook." - }, - "resource": { + "sortBy": { "type": "string", - "description": "This is the specific resource, relevant only to API logs.", + "description": "This is the column to sort by. Defaults to 'createdAt'.", "enum": [ - "org", - "assistant", - "analytics", - "credential", - "phone-number", - "block", - "voice-library", - "provider", - "tool", - "token", - "template", - "squad", - "call", - "file", - "metric", - "log" + "createdAt", + "duration", + "cost" ] }, - "requestDurationSeconds": { + "limit": { "type": "number", - "description": "'This is how long the request took.", - "minimum": 0 + "description": "This is the maximum number of items to return. Defaults to 100.", + "minimum": 0, + "maximum": 1000 }, - "requestStartedAt": { + "createdAtGt": { + "format": "date-time", "type": "string", - "description": "This is the timestamp at which the request began." + "description": "This will return items where the createdAt is greater than the specified value." }, - "requestFinishedAt": { + "createdAtLt": { + "format": "date-time", "type": "string", - "description": "This is the timestamp at which the request finished." - }, - "requestBody": { - "type": "object", - "description": "This is the body of the request." + "description": "This will return items where the createdAt is less than the specified value." }, - "requestHttpMethod": { + "createdAtGe": { + "format": "date-time", "type": "string", - "description": "This is the request method.", - "enum": [ - "POST", - "GET", - "PUT", - "PATCH", - "DELETE" - ] + "description": "This will return items where the createdAt is greater than or equal to the specified value." }, - "requestUrl": { + "createdAtLe": { + "format": "date-time", "type": "string", - "description": "This is the request URL." + "description": "This will return items where the createdAt is less than or equal to the specified value." }, - "requestPath": { + "updatedAtGt": { + "format": "date-time", "type": "string", - "description": "This is the request path." + "description": "This will return items where the updatedAt is greater than the specified value." }, - "requestQuery": { + "updatedAtLt": { + "format": "date-time", "type": "string", - "description": "This is the request query." - }, - "responseHttpCode": { - "type": "number", - "description": "This the HTTP status code of the response." + "description": "This will return items where the updatedAt is less than the specified value." }, - "requestIpAddress": { + "updatedAtGe": { + "format": "date-time", "type": "string", - "description": "This is the request IP address." + "description": "This will return items where the updatedAt is greater than or equal to the specified value." }, - "requestOrigin": { + "updatedAtLe": { + "format": "date-time", "type": "string", - "description": "This is the origin of the request" - }, - "responseBody": { - "type": "object", - "description": "This is the body of the response." - }, - "requestHeaders": { - "type": "object", - "description": "These are the headers of the request." - }, - "error": { - "description": "This is the error, if one occurred.", + "description": "This will return items where the updatedAt is less than or equal to the specified value." + } + } + }, + "EvalRunTargetAssistant": { + "type": "object", + "properties": { + "assistant": { + "description": "This is the transient assistant that will be run against the eval", + "oneOf": [ + { + "$ref": "#/components/schemas/CreateAssistantDTO", + "title": "CreateAssistantDTO" + } + ], "allOf": [ { - "$ref": "#/components/schemas/Error" + "$ref": "#/components/schemas/CreateAssistantDTO" } ] }, - "assistantId": { - "type": "string", - "description": "This is the ID of the assistant." - }, - "phoneNumberId": { - "type": "string", - "description": "This is the ID of the phone number." - }, - "customerId": { - "type": "string", - "description": "This is the ID of the customer." + "assistantOverrides": { + "description": "This is the overrides that will be applied to the assistant.", + "example": "{", + "oneOf": [ + { + "$ref": "#/components/schemas/AssistantOverrides", + "title": "AssistantOverrides" + } + ], + "allOf": [ + { + "$ref": "#/components/schemas/AssistantOverrides" + } + ] }, - "squadId": { + "type": { "type": "string", - "description": "This is the ID of the squad." + "description": "This is the type of the target.\nCurrently it is fixed to `assistant`.", + "example": "assistant", + "enum": [ + "assistant" + ] }, - "callId": { + "assistantId": { "type": "string", - "description": "This is the ID of the call." + "description": "This is the id of the assistant that will be run against the eval", + "example": "123e4567-e89b-12d3-a456-426614174000" } }, "required": [ - "time", - "orgId", "type" ] }, - "LogsPaginatedResponse": { - "type": "object", - "properties": { - "results": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Log" - } - }, - "metadata": { - "$ref": "#/components/schemas/PaginationMeta" - } - }, - "required": [ - "results", - "metadata" - ] - }, - "StructuredOutput": { + "EvalRunTargetSquad": { "type": "object", "properties": { - "model": { - "description": "This is the model that will be used to extract the structured output.\n\nTo provide your own custom system and user prompts for structured output extraction, populate the messages array with your system and user messages. You can specify liquid templating in your system and user messages.\nBetween the system or user messages, you must reference either 'transcript' or 'messages' with the '{{}}' syntax to access the conversation history.\nBetween the system or user messages, you must reference a variation of the structured output with the '{{}}' syntax to access the structured output definition.\ni.e.:\n{{structuredOutput}}\n{{structuredOutput.name}}\n{{structuredOutput.description}}\n{{structuredOutput.schema}}\n\nIf model is not specified, GPT-4.1 will be used by default for extraction, utilizing default system and user prompts.\nIf messages or required fields are not specified, the default system and user prompts will be used.", + "squad": { + "description": "This is the transient squad that will be run against the eval", "oneOf": [ { - "$ref": "#/components/schemas/WorkflowOpenAIModel", - "title": "WorkflowOpenAIModel" - }, + "$ref": "#/components/schemas/CreateSquadDTO", + "title": "CreateSquadDTO" + } + ], + "allOf": [ { - "$ref": "#/components/schemas/WorkflowAnthropicModel", - "title": "WorkflowAnthropicModel" - }, + "$ref": "#/components/schemas/CreateSquadDTO" + } + ] + }, + "assistantOverrides": { + "description": "This is the overrides that will be applied to the assistants.", + "example": "{", + "oneOf": [ { - "$ref": "#/components/schemas/WorkflowGoogleModel", - "title": "WorkflowGoogleModel" - }, + "$ref": "#/components/schemas/AssistantOverrides", + "title": "AssistantOverrides" + } + ], + "allOf": [ { - "$ref": "#/components/schemas/WorkflowCustomModel", - "title": "WorkflowCustomModel" + "$ref": "#/components/schemas/AssistantOverrides" } ] }, + "type": { + "type": "string", + "description": "This is the type of the target.\nCurrently it is fixed to `squad`.", + "example": "squad", + "enum": [ + "squad" + ] + }, + "squadId": { + "type": "string", + "description": "This is the id of the squad that will be run against the eval", + "example": "123e4567-e89b-12d3-a456-426614174000" + } + }, + "required": [ + "type" + ] + }, + "Scorecard": { + "type": "object", + "properties": { "id": { "type": "string", - "description": "This is the unique identifier for the structured output." + "description": "This is the unique identifier for the scorecard." }, "orgId": { "type": "string", - "description": "This is the unique identifier for the org that this structured output belongs to." + "description": "This is the unique identifier for the org that this scorecard belongs to." }, "createdAt": { "format": "date-time", "type": "string", - "description": "This is the ISO 8601 date-time string of when the structured output was created." + "description": "This is the ISO 8601 date-time string of when the scorecard was created." }, "updatedAt": { "format": "date-time", "type": "string", - "description": "This is the ISO 8601 date-time string of when the structured output was last updated." + "description": "This is the ISO 8601 date-time string of when the scorecard was last updated." }, "name": { "type": "string", - "description": "This is the name of the structured output.", - "minLength": 1, - "maxLength": 40 + "description": "This is the name of the scorecard. It is only for user reference and will not be used for any evaluation.", + "maxLength": 80 }, "description": { "type": "string", - "description": "This is the description of what the structured output extracts.\n\nUse this to provide context about what data will be extracted and how it will be used." + "description": "This is the description of the scorecard. It is only for user reference and will not be used for any evaluation.", + "maxLength": 500 }, - "assistantIds": { - "description": "These are the assistant IDs that this structured output is linked to.\n\nWhen linked to assistants, this structured output will be available for extraction during those assistant's calls.", + "metrics": { + "description": "These are the metrics that will be used to evaluate the scorecard.\nEach metric will have a set of conditions and points that will be used to generate the score.", "type": "array", "items": { - "type": "string" + "$ref": "#/components/schemas/ScorecardMetric" } }, - "workflowIds": { - "description": "These are the workflow IDs that this structured output is linked to.\n\nWhen linked to workflows, this structured output will be available for extraction during those workflow's execution.", + "assistantIds": { + "description": "These are the assistant IDs that this scorecard is linked to.\nWhen linked to assistants, this scorecard will be available for evaluation during those assistants' calls.", "type": "array", "items": { "type": "string" } - }, - "schema": { - "description": "This is the JSON Schema definition for the structured output.\n\nDefines the structure and validation rules for the data that will be extracted. Supports all JSON Schema features including:\n- Objects and nested properties\n- Arrays and array validation\n- String, number, boolean, and null types\n- Enums and const values\n- Validation constraints (min/max, patterns, etc.)\n- Composition with allOf, anyOf, oneOf", - "allOf": [ - { - "$ref": "#/components/schemas/JsonSchema" - } - ] } }, "required": [ @@ -39280,17 +65160,16 @@ "orgId", "createdAt", "updatedAt", - "name", - "schema" + "metrics" ] }, - "StructuredOutputPaginatedResponse": { + "ScorecardPaginatedResponse": { "type": "object", "properties": { "results": { "type": "array", "items": { - "$ref": "#/components/schemas/StructuredOutput" + "$ref": "#/components/schemas/Scorecard" } }, "metadata": { @@ -39302,123 +65181,32 @@ "metadata" ] }, - "CreateStructuredOutputDTO": { + "UpdateScorecardDTO": { "type": "object", "properties": { - "model": { - "description": "This is the model that will be used to extract the structured output.\n\nTo provide your own custom system and user prompts for structured output extraction, populate the messages array with your system and user messages. You can specify liquid templating in your system and user messages.\nBetween the system or user messages, you must reference either 'transcript' or 'messages' with the '{{}}' syntax to access the conversation history.\nBetween the system or user messages, you must reference a variation of the structured output with the '{{}}' syntax to access the structured output definition.\ni.e.:\n{{structuredOutput}}\n{{structuredOutput.name}}\n{{structuredOutput.description}}\n{{structuredOutput.schema}}\n\nIf model is not specified, GPT-4.1 will be used by default for extraction, utilizing default system and user prompts.\nIf messages or required fields are not specified, the default system and user prompts will be used.", - "oneOf": [ - { - "$ref": "#/components/schemas/WorkflowOpenAIModel", - "title": "WorkflowOpenAIModel" - }, - { - "$ref": "#/components/schemas/WorkflowAnthropicModel", - "title": "WorkflowAnthropicModel" - }, - { - "$ref": "#/components/schemas/WorkflowGoogleModel", - "title": "WorkflowGoogleModel" - }, - { - "$ref": "#/components/schemas/WorkflowCustomModel", - "title": "WorkflowCustomModel" - } - ] - }, "name": { "type": "string", - "description": "This is the name of the structured output.", - "minLength": 1, - "maxLength": 40 - }, - "schema": { - "description": "This is the JSON Schema definition for the structured output.\n\nThis is required when creating a structured output. Defines the structure and validation rules for the data that will be extracted. Supports all JSON Schema features including:\n- Objects and nested properties\n- Arrays and array validation\n- String, number, boolean, and null types\n- Enums and const values\n- Validation constraints (min/max, patterns, etc.)\n- Composition with allOf, anyOf, oneOf", - "allOf": [ - { - "$ref": "#/components/schemas/JsonSchema" - } - ] + "description": "This is the name of the scorecard. It is only for user reference and will not be used for any evaluation.", + "maxLength": 80 }, "description": { "type": "string", - "description": "This is the description of what the structured output extracts.\n\nUse this to provide context about what data will be extracted and how it will be used." - }, - "assistantIds": { - "description": "These are the assistant IDs that this structured output is linked to.\n\nWhen linked to assistants, this structured output will be available for extraction during those assistant's calls.", - "type": "array", - "items": { - "type": "string" - } + "description": "This is the description of the scorecard. It is only for user reference and will not be used for any evaluation.", + "maxLength": 500 }, - "workflowIds": { - "description": "These are the workflow IDs that this structured output is linked to.\n\nWhen linked to workflows, this structured output will be available for extraction during those workflow's execution.", + "metrics": { + "description": "These are the metrics that will be used to evaluate the scorecard.\nEach metric will have a set of conditions and points that will be used to generate the score.", "type": "array", "items": { - "type": "string" + "$ref": "#/components/schemas/ScorecardMetric" } - } - }, - "required": [ - "name", - "schema" - ] - }, - "UpdateStructuredOutputDTO": { - "type": "object", - "properties": { - "model": { - "description": "This is the model that will be used to extract the structured output.\n\nTo provide your own custom system and user prompts for structured output extraction, populate the messages array with your system and user messages. You can specify liquid templating in your system and user messages.\nBetween the system or user messages, you must reference either 'transcript' or 'messages' with the '{{}}' syntax to access the conversation history.\nBetween the system or user messages, you must reference a variation of the structured output with the '{{}}' syntax to access the structured output definition.\ni.e.:\n{{structuredOutput}}\n{{structuredOutput.name}}\n{{structuredOutput.description}}\n{{structuredOutput.schema}}\n\nIf model is not specified, GPT-4.1 will be used by default for extraction, utilizing default system and user prompts.\nIf messages or required fields are not specified, the default system and user prompts will be used.", - "oneOf": [ - { - "$ref": "#/components/schemas/WorkflowOpenAIModel", - "title": "WorkflowOpenAIModel" - }, - { - "$ref": "#/components/schemas/WorkflowAnthropicModel", - "title": "WorkflowAnthropicModel" - }, - { - "$ref": "#/components/schemas/WorkflowGoogleModel", - "title": "WorkflowGoogleModel" - }, - { - "$ref": "#/components/schemas/WorkflowCustomModel", - "title": "WorkflowCustomModel" - } - ] - }, - "name": { - "type": "string", - "description": "This is the name of the structured output.", - "minLength": 1, - "maxLength": 40 - }, - "description": { - "type": "string", - "description": "This is the description of what the structured output extracts.\n\nUse this to provide context about what data will be extracted and how it will be used." }, "assistantIds": { - "description": "These are the assistant IDs that this structured output is linked to.\n\nWhen linked to assistants, this structured output will be available for extraction during those assistant's calls.", - "type": "array", - "items": { - "type": "string" - } - }, - "workflowIds": { - "description": "These are the workflow IDs that this structured output is linked to.\n\nWhen linked to workflows, this structured output will be available for extraction during those workflow's execution.", + "description": "These are the assistant IDs that this scorecard is linked to.\nWhen linked to assistants, this scorecard will be available for evaluation during those assistants' calls.", "type": "array", "items": { "type": "string" } - }, - "schema": { - "description": "This is the JSON Schema definition for the structured output.\n\nDefines the structure and validation rules for the data that will be extracted. Supports all JSON Schema features including:\n- Objects and nested properties\n- Arrays and array validation\n- String, number, boolean, and null types\n- Enums and const values\n- Validation constraints (min/max, patterns, etc.)\n- Composition with allOf, anyOf, oneOf", - "allOf": [ - { - "$ref": "#/components/schemas/JsonSchema" - } - ] } } }, @@ -39427,7 +65215,7 @@ "properties": { "hipaaEnabled": { "type": "boolean", - "description": "When this is enabled, no logs, recordings, or transcriptions will be stored. At the end of the call, you will still receive an end-of-call-report message to store on your server. Defaults to false.\nWhen HIPAA is enabled, only OpenAI/Custom LLM or Azure Providers will be available for LLM and Voice respectively.\nThis is due to the compliance requirements of HIPAA. Other providers may not meet these requirements.", + "description": "When this is enabled, logs, recordings, and transcriptions will be stored in HIPAA-compliant storage. Defaults to false.\nWhen HIPAA is enabled, only HIPAA-compliant providers will be available for LLM, Voice, and Transcriber respectively.\nThis is due to the compliance requirements of HIPAA. Other providers may not meet these requirements.", "example": false }, "subscriptionId": { @@ -39443,8 +65231,11 @@ "type": "string", "description": "This is the channel of the org. There is the cluster the API traffic for the org will be directed.", "enum": [ + "daily", "default", - "weekly" + "weekly", + "intuit", + "hcs" ] }, "billingLimit": { @@ -39610,6 +65401,14 @@ "type": "boolean", "description": "This is the HIPAA enabled flag for the subscription. It determines whether orgs under this\nsubscription have the option to enable HIPAA compliance." }, + "zdrEnabled": { + "type": "boolean", + "description": "This is the ZDR enabled flag for the subscription. It determines whether orgs under this\nsubscription have the option to enable ZDR." + }, + "dataRetentionEnabled": { + "type": "boolean", + "description": "This is the data retention enabled flag for the subscription. It determines whether orgs under this\nsubscription have the option to enable data retention." + }, "hipaaCommonPaperAgreementId": { "type": "string", "description": "This is the ID for the Common Paper agreement outlining the HIPAA contract." @@ -39704,10 +65503,12 @@ }, "callRetentionDays": { "type": "number", + "nullable": true, "description": "This is the call retention days for the subscription." }, "chatRetentionDays": { "type": "number", + "nullable": true, "description": "This is the chat retention days for the subscription." }, "minutesIncludedResetFrequency": { @@ -39744,9 +65545,17 @@ "properties": { "hipaaEnabled": { "type": "boolean", - "description": "When this is enabled, no logs, recordings, or transcriptions will be stored. At the end of the call, you will still receive an end-of-call-report message to store on your server. Defaults to false.\nWhen HIPAA is enabled, only OpenAI/Custom LLM or Azure Providers will be available for LLM and Voice respectively.\nThis is due to the compliance requirements of HIPAA. Other providers may not meet these requirements.", + "description": "When this is enabled, logs, recordings, and transcriptions will be stored in HIPAA-compliant storage. Defaults to false.\nWhen HIPAA is enabled, only HIPAA-compliant providers will be available for LLM, Voice, and Transcriber respectively.\nThis is due to the compliance requirements of HIPAA. Other providers may not meet these requirements.", "example": false }, + "workosRepairPending": { + "type": "boolean", + "description": "The org was created locally, but WorkOS access is still being repaired.\nClients should keep the current session/org and refresh the org list." + }, + "workosRepairQueued": { + "type": "boolean", + "description": "Whether the pending WorkOS repair was accepted by Kafka." + }, "subscription": { "$ref": "#/components/schemas/Subscription" }, @@ -39802,8 +65611,11 @@ "type": "string", "description": "This is the channel of the org. There is the cluster the API traffic for the org will be directed.", "enum": [ + "daily", "default", - "weekly" + "weekly", + "intuit", + "hcs" ] }, "billingLimit": { @@ -39847,7 +65659,7 @@ "properties": { "hipaaEnabled": { "type": "boolean", - "description": "When this is enabled, no logs, recordings, or transcriptions will be stored. At the end of the call, you will still receive an end-of-call-report message to store on your server. Defaults to false.\nWhen HIPAA is enabled, only OpenAI/Custom LLM or Azure Providers will be available for LLM and Voice respectively.\nThis is due to the compliance requirements of HIPAA. Other providers may not meet these requirements.", + "description": "When this is enabled, logs, recordings, and transcriptions will be stored in HIPAA-compliant storage. Defaults to false.\nWhen HIPAA is enabled, only HIPAA-compliant providers will be available for LLM, Voice, and Transcriber respectively.\nThis is due to the compliance requirements of HIPAA. Other providers may not meet these requirements.", "example": false }, "subscriptionId": { @@ -39863,8 +65675,11 @@ "type": "string", "description": "This is the channel of the org. There is the cluster the API traffic for the org will be directed.", "enum": [ + "daily", "default", - "weekly" + "weekly", + "intuit", + "hcs" ] }, "billingLimit": { @@ -39942,12 +65757,21 @@ } }, "role": { - "enum": [ - "admin", - "editor", - "viewer" - ], - "type": "string" + "pattern": "ORG_ROLE_OR_CUSTOM_ROLE_PATTERN", + "oneOf": [ + { + "type": "string", + "enum": [ + "admin", + "editor", + "viewer" + ] + }, + { + "type": "string", + "pattern": "^org-[a-z0-9-]+$" + } + ] }, "redirectTo": { "type": "string" @@ -39958,6 +65782,46 @@ "role" ] }, + "PendingInvitationDTO": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "email": { + "type": "string" + } + }, + "required": [ + "id", + "email" + ] + }, + "PendingInvitationsResponseDTO": { + "type": "object", + "properties": { + "invitations": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PendingInvitationDTO" + } + } + }, + "required": [ + "invitations" + ] + }, + "RevokeInvitationResponseDTO": { + "type": "object", + "properties": { + "success": { + "type": "boolean" + } + }, + "required": [ + "success" + ] + }, "UpdateUserRoleDTO": { "type": "object", "properties": { @@ -39965,12 +65829,21 @@ "type": "string" }, "role": { - "enum": [ - "admin", - "editor", - "viewer" - ], - "type": "string" + "pattern": "ORG_ROLE_OR_CUSTOM_ROLE_PATTERN", + "oneOf": [ + { + "type": "string", + "enum": [ + "admin", + "editor", + "viewer" + ] + }, + { + "type": "string", + "pattern": "^org-[a-z0-9-]+$" + } + ] } }, "required": [ @@ -40097,8 +65970,7 @@ "id", "orgId", "createdAt", - "updatedAt", - "value" + "updatedAt" ] }, "UpdateTokenDTO": { @@ -40117,29 +65989,172 @@ "description": "This is the name of the token. This is just for your own reference.", "maxLength": 40 }, - "restrictions": { - "description": "This are the restrictions for the token.", + "restrictions": { + "description": "This are the restrictions for the token.", + "allOf": [ + { + "$ref": "#/components/schemas/TokenRestrictions" + } + ] + } + } + }, + "AnthropicCredential": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "anthropic" + ] + }, + "apiKey": { + "type": "string", + "maxLength": 10000, + "description": "This is not returned in the API." + }, + "id": { + "type": "string", + "description": "This is the unique identifier for the credential." + }, + "orgId": { + "type": "string", + "description": "This is the unique identifier for the org that this credential belongs to." + }, + "createdAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the credential was created." + }, + "updatedAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the assistant was last updated." + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + }, + "required": [ + "provider", + "apiKey", + "id", + "orgId", + "createdAt", + "updatedAt" + ] + }, + "AWSStsAuthenticationArtifact": { + "type": "object", + "properties": { + "externalId": { + "type": "string", + "description": "This is the optional external ID for the AWS credential" + } + }, + "required": [ + "externalId" + ] + }, + "AWSStsAssumeRoleUser": { + "type": "object", + "properties": { + "AssumedRoleId": { + "type": "string", + "description": "This is the assumed role ID" + }, + "Arn": { + "type": "string", + "description": "This is the assumed role ARN" + } + } + }, + "AWSStsCredentials": { + "type": "object", + "properties": { + "AccessKeyId": { + "type": "string", + "description": "This is the access key ID for the AWS credential" + }, + "Expiration": { + "format": "date-time", + "type": "string", + "description": "This is the expiration date for the AWS credential" + }, + "SecretAccessKey": { + "type": "string", + "description": "This is the secret access key for the AWS credential" + }, + "SessionToken": { + "type": "string", + "description": "This is the session token for the AWS credential" + } + } + }, + "AWSStsAuthenticationSession": { + "type": "object", + "properties": { + "assumedRoleUser": { + "description": "This is the assumed role user", + "allOf": [ + { + "$ref": "#/components/schemas/AWSStsAssumeRoleUser" + } + ] + }, + "credentials": { + "description": "This is the credentials for the AWS STS assume role", "allOf": [ { - "$ref": "#/components/schemas/TokenRestrictions" + "$ref": "#/components/schemas/AWSStsCredentials" } ] + }, + "packedPolicySize": { + "type": "number", + "description": "This is the size of the policy" + }, + "sourcedIDEntity": { + "type": "string", + "description": "This is the sourced ID entity" } } }, - "AnthropicCredential": { + "AnthropicBedrockCredential": { "type": "object", "properties": { "provider": { "type": "string", "enum": [ - "anthropic" + "anthropic-bedrock" ] }, - "apiKey": { + "region": { "type": "string", - "maxLength": 10000, - "description": "This is not returned in the API." + "description": "AWS region where Bedrock is configured.", + "enum": [ + "us-east-1", + "us-west-2", + "eu-central-1", + "eu-west-1", + "eu-west-3", + "ap-northeast-1", + "ap-southeast-2" + ] + }, + "authenticationPlan": { + "description": "Authentication method - either direct IAM credentials or cross-account role assumption.", + "oneOf": [ + { + "$ref": "#/components/schemas/AWSIAMCredentialsAuthenticationPlan" + }, + { + "$ref": "#/components/schemas/AWSStsAuthenticationPlan" + } + ] }, "id": { "type": "string", @@ -40159,6 +66174,22 @@ "type": "string", "description": "This is the ISO 8601 date-time string of when the assistant was last updated." }, + "authenticationArtifact": { + "description": "Stores the external ID (generated or user-provided) for future AssumeRole calls.", + "allOf": [ + { + "$ref": "#/components/schemas/AWSStsAuthenticationArtifact" + } + ] + }, + "authenticationSession": { + "description": "Cached authentication session from AssumeRole (temporary credentials).\nManaged by the system, auto-refreshed when expired.", + "allOf": [ + { + "$ref": "#/components/schemas/AWSStsAuthenticationSession" + } + ] + }, "name": { "type": "string", "description": "This is the name of credential. This is just for your reference.", @@ -40168,7 +66199,8 @@ }, "required": [ "provider", - "apiKey", + "region", + "authenticationPlan", "id", "orgId", "createdAt", @@ -40292,22 +66324,29 @@ "type": "string", "description": "This is the region of the Azure resource.", "enum": [ - "australia", + "australiaeast", "canadaeast", "canadacentral", + "centralus", "eastus2", "eastus", "france", + "germanywestcentral", "india", "japaneast", "japanwest", - "uaenorth", "northcentralus", "norway", + "polandcentral", "southcentralus", + "spaincentral", "swedencentral", "switzerland", + "switzerlandnorth", + "switzerlandwest", + "uaenorth", "uk", + "westeurope", "westus", "westus3" ] @@ -40376,22 +66415,29 @@ "region": { "type": "string", "enum": [ - "australia", + "australiaeast", "canadaeast", "canadacentral", + "centralus", "eastus2", "eastus", "france", + "germanywestcentral", "india", "japaneast", "japanwest", - "uaenorth", "northcentralus", "norway", + "polandcentral", "southcentralus", + "spaincentral", "swedencentral", "switzerland", + "switzerlandnorth", + "switzerlandwest", + "uaenorth", "uk", + "westeurope", "westus", "westus3" ] @@ -40399,6 +66445,16 @@ "models": { "type": "array", "enum": [ + "gpt-5.6-luna-2026-07-09", + "gpt-5.6-terra-2026-07-09", + "gpt-5.6-sol-2026-07-09", + "gpt-5.4", + "gpt-5.4-mini", + "gpt-5.4-nano", + "gpt-5.2", + "gpt-5.2-chat", + "gpt-5.1", + "gpt-5.1-chat", "gpt-5", "gpt-5-mini", "gpt-5-nano", @@ -40414,7 +66470,10 @@ "gpt-4-1106-preview", "gpt-4-0613", "gpt-35-turbo-0125", - "gpt-35-turbo-1106" + "gpt-35-turbo-1106", + "gpt-4o", + "gpt-4.1", + "gpt-5.4-mini-2026-03-17" ], "example": [ "gpt-4-0125-preview", @@ -40423,6 +66482,16 @@ "items": { "type": "string", "enum": [ + "gpt-5.6-luna-2026-07-09", + "gpt-5.6-terra-2026-07-09", + "gpt-5.6-sol-2026-07-09", + "gpt-5.4", + "gpt-5.4-mini", + "gpt-5.4-nano", + "gpt-5.2", + "gpt-5.2-chat", + "gpt-5.1", + "gpt-5.1-chat", "gpt-5", "gpt-5-mini", "gpt-5-nano", @@ -40438,7 +66507,10 @@ "gpt-4-1106-preview", "gpt-4-0613", "gpt-35-turbo-0125", - "gpt-35-turbo-1106" + "gpt-35-turbo-1106", + "gpt-4o", + "gpt-4.1", + "gpt-5.4-mini-2026-03-17" ] } }, @@ -40554,14 +66626,6 @@ "type": "string", "description": "This can be used to enable the SIP diversion header for authenticating the calling number if the SIP trunk supports it. This is an advanced property.", "maxLength": 10000 - }, - "sbcConfiguration": { - "description": "This is an advanced configuration for enterprise deployments. This uses the onprem SBC to trunk into the SIP trunk's `gateways`, rather than the managed SBC provided by Vapi.", - "allOf": [ - { - "$ref": "#/components/schemas/SbcConfiguration" - } - ] } }, "required": [ @@ -40608,6 +66672,10 @@ "description": "This is the name of credential. This is just for your reference.", "minLength": 1, "maxLength": 40 + }, + "apiUrl": { + "type": "string", + "description": "This can be used to point to an onprem Cartesia instance. Defaults to api.cartesia.ai." } }, "required": [ @@ -40915,18 +66983,481 @@ "updatedAt" ] }, - "DeepSeekCredential": { + "DeepSeekCredential": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "deep-seek" + ] + }, + "apiKey": { + "type": "string", + "description": "This is not returned in the API." + }, + "id": { + "type": "string", + "description": "This is the unique identifier for the credential." + }, + "orgId": { + "type": "string", + "description": "This is the unique identifier for the org that this credential belongs to." + }, + "createdAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the credential was created." + }, + "updatedAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the assistant was last updated." + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + }, + "required": [ + "provider", + "apiKey", + "id", + "orgId", + "createdAt", + "updatedAt" + ] + }, + "ElevenLabsCredential": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "11labs" + ] + }, + "apiKey": { + "type": "string", + "maxLength": 10000, + "description": "This is not returned in the API." + }, + "apiUrl": { + "type": "string", + "enum": [ + "https://api.elevenlabs.io", + "https://api.eu.residency.elevenlabs.io" + ], + "description": "ElevenLabs-only API environment for this key: the global endpoint or the EU data residency endpoint. In EU deployments, new credentials must explicitly use the EU data residency endpoint; existing credentials may omit this field on update to retain their saved endpoint. Outside EU deployments, Vapi detects an omitted endpoint automatically and null on update clears and re-detects the endpoint.", + "nullable": true + }, + "id": { + "type": "string", + "description": "This is the unique identifier for the credential." + }, + "orgId": { + "type": "string", + "description": "This is the unique identifier for the org that this credential belongs to." + }, + "createdAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the credential was created." + }, + "updatedAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the assistant was last updated." + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + }, + "required": [ + "provider", + "apiKey", + "id", + "orgId", + "createdAt", + "updatedAt" + ] + }, + "GcpCredential": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "gcp" + ] + }, + "fallbackIndex": { + "type": "number", + "description": "This is the order in which this storage provider is tried during upload retries. Lower numbers are tried first in increasing order.", + "minimum": 1 + }, + "id": { + "type": "string", + "description": "This is the unique identifier for the credential." + }, + "orgId": { + "type": "string", + "description": "This is the unique identifier for the org that this credential belongs to." + }, + "createdAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the credential was created." + }, + "updatedAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the assistant was last updated." + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + }, + "gcpKey": { + "description": "This is the GCP key. This is the JSON that can be generated in the Google Cloud Console at https://console.cloud.google.com/iam-admin/serviceaccounts/details//keys.\n\nThe schema is identical to the JSON that GCP outputs.", + "allOf": [ + { + "$ref": "#/components/schemas/GcpKey" + } + ] + }, + "region": { + "type": "string", + "description": "This is the region of the GCP resource.", + "maxLength": 40 + }, + "bucketPlan": { + "$ref": "#/components/schemas/BucketPlan" + } + }, + "required": [ + "provider", + "id", + "orgId", + "createdAt", + "updatedAt", + "gcpKey" + ] + }, + "GladiaCredential": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "gladia" + ] + }, + "apiKey": { + "type": "string", + "description": "This is not returned in the API." + }, + "id": { + "type": "string", + "description": "This is the unique identifier for the credential." + }, + "orgId": { + "type": "string", + "description": "This is the unique identifier for the org that this credential belongs to." + }, + "createdAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the credential was created." + }, + "updatedAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the assistant was last updated." + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + }, + "required": [ + "provider", + "apiKey", + "id", + "orgId", + "createdAt", + "updatedAt" + ] + }, + "GoHighLevelCredential": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "gohighlevel" + ] + }, + "apiKey": { + "type": "string", + "description": "This is not returned in the API." + }, + "id": { + "type": "string", + "description": "This is the unique identifier for the credential." + }, + "orgId": { + "type": "string", + "description": "This is the unique identifier for the org that this credential belongs to." + }, + "createdAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the credential was created." + }, + "updatedAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the assistant was last updated." + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + }, + "required": [ + "provider", + "apiKey", + "id", + "orgId", + "createdAt", + "updatedAt" + ] + }, + "GoogleCredential": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "description": "This is the key for Gemini in Google AI Studio. Get it from here: https://aistudio.google.com/app/apikey", + "enum": [ + "google" + ] + }, + "apiKey": { + "type": "string", + "maxLength": 10000, + "description": "This is not returned in the API." + }, + "id": { + "type": "string", + "description": "This is the unique identifier for the credential." + }, + "orgId": { + "type": "string", + "description": "This is the unique identifier for the org that this credential belongs to." + }, + "createdAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the credential was created." + }, + "updatedAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the assistant was last updated." + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + }, + "required": [ + "provider", + "apiKey", + "id", + "orgId", + "createdAt", + "updatedAt" + ] + }, + "GroqCredential": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "groq" + ] + }, + "apiKey": { + "type": "string", + "description": "This is not returned in the API." + }, + "id": { + "type": "string", + "description": "This is the unique identifier for the credential." + }, + "orgId": { + "type": "string", + "description": "This is the unique identifier for the org that this credential belongs to." + }, + "createdAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the credential was created." + }, + "updatedAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the assistant was last updated." + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + }, + "required": [ + "provider", + "apiKey", + "id", + "orgId", + "createdAt", + "updatedAt" + ] + }, + "HumeCredential": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "hume" + ] + }, + "apiKey": { + "type": "string", + "maxLength": 10000, + "description": "This is not returned in the API." + }, + "id": { + "type": "string", + "description": "This is the unique identifier for the credential." + }, + "orgId": { + "type": "string", + "description": "This is the unique identifier for the org that this credential belongs to." + }, + "createdAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the credential was created." + }, + "updatedAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the assistant was last updated." + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + }, + "required": [ + "provider", + "apiKey", + "id", + "orgId", + "createdAt", + "updatedAt" + ] + }, + "InflectionAICredential": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "description": "This is the api key for Pi in InflectionAI's console. Get it from here: https://developers.inflection.ai/keys, billing will need to be setup", + "enum": [ + "inflection-ai" + ] + }, + "apiKey": { + "type": "string", + "maxLength": 10000, + "description": "This is not returned in the API." + }, + "id": { + "type": "string", + "description": "This is the unique identifier for the credential." + }, + "orgId": { + "type": "string", + "description": "This is the unique identifier for the org that this credential belongs to." + }, + "createdAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the credential was created." + }, + "updatedAt": { + "format": "date-time", + "type": "string", + "description": "This is the ISO 8601 date-time string of when the assistant was last updated." + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + }, + "required": [ + "provider", + "apiKey", + "id", + "orgId", + "createdAt", + "updatedAt" + ] + }, + "LangfuseCredential": { "type": "object", "properties": { "provider": { "type": "string", "enum": [ - "deep-seek" + "langfuse" ] }, + "publicKey": { + "type": "string", + "description": "The public key for Langfuse project. Eg: pk-lf-..." + }, "apiKey": { "type": "string", - "description": "This is not returned in the API." + "description": "The secret key for Langfuse project. Eg: sk-lf-... .This is not returned in the API." + }, + "apiUrl": { + "type": "string", + "description": "The host URL for Langfuse project. Eg: https://cloud.langfuse.com" }, "id": { "type": "string", @@ -40955,25 +67486,26 @@ }, "required": [ "provider", + "publicKey", "apiKey", + "apiUrl", "id", "orgId", "createdAt", "updatedAt" ] }, - "ElevenLabsCredential": { + "LmntCredential": { "type": "object", "properties": { "provider": { "type": "string", "enum": [ - "11labs" + "lmnt" ] }, "apiKey": { "type": "string", - "maxLength": 10000, "description": "This is not returned in the API." }, "id": { @@ -41010,78 +67542,22 @@ "updatedAt" ] }, - "GcpCredential": { + "MakeCredential": { "type": "object", "properties": { "provider": { "type": "string", "enum": [ - "gcp" + "make" ] }, - "fallbackIndex": { - "type": "number", - "description": "This is the order in which this storage provider is tried during upload retries. Lower numbers are tried first in increasing order.", - "minimum": 1 - }, - "id": { - "type": "string", - "description": "This is the unique identifier for the credential." - }, - "orgId": { - "type": "string", - "description": "This is the unique identifier for the org that this credential belongs to." - }, - "createdAt": { - "format": "date-time", - "type": "string", - "description": "This is the ISO 8601 date-time string of when the credential was created." - }, - "updatedAt": { - "format": "date-time", - "type": "string", - "description": "This is the ISO 8601 date-time string of when the assistant was last updated." - }, - "name": { + "teamId": { "type": "string", - "description": "This is the name of credential. This is just for your reference.", - "minLength": 1, - "maxLength": 40 - }, - "gcpKey": { - "description": "This is the GCP key. This is the JSON that can be generated in the Google Cloud Console at https://console.cloud.google.com/iam-admin/serviceaccounts/details//keys.\n\nThe schema is identical to the JSON that GCP outputs.", - "allOf": [ - { - "$ref": "#/components/schemas/GcpKey" - } - ] + "description": "Team ID" }, "region": { "type": "string", - "description": "This is the region of the GCP resource.", - "maxLength": 40 - }, - "bucketPlan": { - "$ref": "#/components/schemas/BucketPlan" - } - }, - "required": [ - "provider", - "id", - "orgId", - "createdAt", - "updatedAt", - "gcpKey" - ] - }, - "GladiaCredential": { - "type": "object", - "properties": { - "provider": { - "type": "string", - "enum": [ - "gladia" - ] + "description": "Region of your application. For example: eu1, eu2, us1, us2" }, "apiKey": { "type": "string", @@ -41114,6 +67590,8 @@ }, "required": [ "provider", + "teamId", + "region", "apiKey", "id", "orgId", @@ -41121,18 +67599,25 @@ "updatedAt" ] }, - "GoHighLevelCredential": { + "MicrosoftCredential": { "type": "object", "properties": { "provider": { "type": "string", "enum": [ - "gohighlevel" + "microsoft" ] }, "apiKey": { "type": "string", - "description": "This is not returned in the API." + "description": "This is not returned in the API.", + "maxLength": 10000 + }, + "region": { + "type": "string", + "description": "Azure region for the Speech resource. Defaults to `eastus` when omitted. MAI-Voice-2 is preview and region-limited.", + "maxLength": 64, + "example": "eastus" }, "id": { "type": "string", @@ -41168,19 +67653,18 @@ "updatedAt" ] }, - "GoogleCredential": { + "MistralCredential": { "type": "object", "properties": { "provider": { "type": "string", - "description": "This is the key for Gemini in Google AI Studio. Get it from here: https://aistudio.google.com/app/apikey", "enum": [ - "google" + "mistral" ] }, "apiKey": { "type": "string", - "maxLength": 10000, + "maxLength": 100, "description": "This is not returned in the API." }, "id": { @@ -41217,13 +67701,13 @@ "updatedAt" ] }, - "GroqCredential": { + "NeuphonicCredential": { "type": "object", "properties": { "provider": { "type": "string", "enum": [ - "groq" + "neuphonic" ] }, "apiKey": { @@ -41264,18 +67748,17 @@ "updatedAt" ] }, - "HumeCredential": { + "OpenAICredential": { "type": "object", "properties": { "provider": { "type": "string", "enum": [ - "hume" + "openai" ] }, "apiKey": { "type": "string", - "maxLength": 10000, "description": "This is not returned in the API." }, "id": { @@ -41312,19 +67795,17 @@ "updatedAt" ] }, - "InflectionAICredential": { + "OpenRouterCredential": { "type": "object", "properties": { "provider": { "type": "string", - "description": "This is the api key for Pi in InflectionAI's console. Get it from here: https://developers.inflection.ai/keys, billing will need to be setup", "enum": [ - "inflection-ai" + "openrouter" ] }, "apiKey": { "type": "string", - "maxLength": 10000, "description": "This is not returned in the API." }, "id": { @@ -41361,26 +67842,18 @@ "updatedAt" ] }, - "LangfuseCredential": { + "PerplexityAICredential": { "type": "object", "properties": { "provider": { "type": "string", "enum": [ - "langfuse" + "perplexity-ai" ] }, - "publicKey": { - "type": "string", - "description": "The public key for Langfuse project. Eg: pk-lf-..." - }, "apiKey": { "type": "string", - "description": "The secret key for Langfuse project. Eg: sk-lf-... .This is not returned in the API." - }, - "apiUrl": { - "type": "string", - "description": "The host URL for Langfuse project. Eg: https://cloud.langfuse.com" + "description": "This is not returned in the API." }, "id": { "type": "string", @@ -41409,22 +67882,20 @@ }, "required": [ "provider", - "publicKey", "apiKey", - "apiUrl", "id", "orgId", "createdAt", "updatedAt" ] }, - "LmntCredential": { + "PlayHTCredential": { "type": "object", "properties": { "provider": { "type": "string", "enum": [ - "lmnt" + "playht" ] }, "apiKey": { @@ -41454,6 +67925,9 @@ "description": "This is the name of credential. This is just for your reference.", "minLength": 1, "maxLength": 40 + }, + "userId": { + "type": "string" } }, "required": [ @@ -41462,26 +67936,19 @@ "id", "orgId", "createdAt", - "updatedAt" + "updatedAt", + "userId" ] }, - "MakeCredential": { + "RimeAICredential": { "type": "object", "properties": { "provider": { "type": "string", "enum": [ - "make" + "rime-ai" ] }, - "teamId": { - "type": "string", - "description": "Team ID" - }, - "region": { - "type": "string", - "description": "Region of your application. For example: eu1, eu2, us1, us2" - }, "apiKey": { "type": "string", "description": "This is not returned in the API." @@ -41513,8 +67980,6 @@ }, "required": [ "provider", - "teamId", - "region", "apiKey", "id", "orgId", @@ -41522,18 +67987,17 @@ "updatedAt" ] }, - "MistralCredential": { + "RunpodCredential": { "type": "object", "properties": { "provider": { "type": "string", "enum": [ - "mistral" + "runpod" ] }, "apiKey": { "type": "string", - "maxLength": 100, "description": "This is not returned in the API." }, "id": { @@ -41570,17 +68034,18 @@ "updatedAt" ] }, - "NeuphonicCredential": { + "WellSaidCredential": { "type": "object", "properties": { "provider": { "type": "string", "enum": [ - "neuphonic" + "wellsaid" ] }, "apiKey": { "type": "string", + "maxLength": 10000, "description": "This is not returned in the API." }, "id": { @@ -41617,18 +68082,40 @@ "updatedAt" ] }, - "OpenAICredential": { + "S3Credential": { "type": "object", "properties": { "provider": { "type": "string", "enum": [ - "openai" - ] + "s3" + ], + "description": "Credential provider. Only allowed value is s3" }, - "apiKey": { + "awsAccessKeyId": { "type": "string", - "description": "This is not returned in the API." + "description": "AWS access key ID." + }, + "awsSecretAccessKey": { + "type": "string", + "description": "AWS access key secret. This is not returned in the API." + }, + "region": { + "type": "string", + "description": "AWS region in which the S3 bucket is located." + }, + "s3BucketName": { + "type": "string", + "description": "AWS S3 bucket name." + }, + "s3PathPrefix": { + "type": "string", + "description": "The path prefix for the uploaded recording. Ex. \"recordings/\"" + }, + "fallbackIndex": { + "type": "number", + "minimum": 1, + "description": "This is the order in which this storage provider is tried during upload retries. Lower numbers are tried first in increasing order." }, "id": { "type": "string", @@ -41657,72 +68144,72 @@ }, "required": [ "provider", - "apiKey", + "awsAccessKeyId", + "awsSecretAccessKey", + "region", + "s3BucketName", + "s3PathPrefix", "id", "orgId", "createdAt", "updatedAt" ] }, - "OpenRouterCredential": { + "S3CompatibleBucketPlan": { "type": "object", "properties": { - "provider": { - "type": "string", - "enum": [ - "openrouter" - ] - }, - "apiKey": { + "url": { "type": "string", - "description": "This is not returned in the API." + "description": "S3-compatible endpoint URL, such as https://s3.us-west-004.backblazeb2.com. Must be public HTTPS." }, - "id": { + "region": { "type": "string", - "description": "This is the unique identifier for the credential." + "maxLength": 64, + "description": "SigV4 signing region expected by the object store. Most stores accept us-east-1." }, - "orgId": { + "accessKeyId": { "type": "string", - "description": "This is the unique identifier for the org that this credential belongs to." + "description": "S3 access key ID." }, - "createdAt": { - "format": "date-time", + "secretAccessKey": { "type": "string", - "description": "This is the ISO 8601 date-time string of when the credential was created." + "description": "S3 secret access key. This is not returned in the API.", + "writeOnly": true }, - "updatedAt": { - "format": "date-time", + "name": { "type": "string", - "description": "This is the ISO 8601 date-time string of when the assistant was last updated." + "description": "Bucket name." }, - "name": { + "path": { "type": "string", - "description": "This is the name of credential. This is just for your reference.", - "minLength": 1, - "maxLength": 40 + "description": "Optional key prefix inside the bucket, such as recordings/." } }, "required": [ - "provider", - "apiKey", - "id", - "orgId", - "createdAt", - "updatedAt" + "url", + "region", + "accessKeyId", + "secretAccessKey", + "name" ] }, - "PerplexityAICredential": { + "S3CompatibleStorageCredential": { "type": "object", "properties": { "provider": { "type": "string", "enum": [ - "perplexity-ai" - ] + "s3-compatible" + ], + "description": "This is for S3-compatible storage such as MinIO, Garage, Ceph, or Backblaze B2." }, - "apiKey": { - "type": "string", - "description": "This is not returned in the API." + "bucketPlan": { + "$ref": "#/components/schemas/S3CompatibleBucketPlan" + }, + "fallbackIndex": { + "type": "number", + "minimum": 1, + "description": "This is the order in which this storage provider is tried during upload retries. Lower numbers are tried first in increasing order." }, "id": { "type": "string", @@ -41751,20 +68238,20 @@ }, "required": [ "provider", - "apiKey", + "bucketPlan", "id", "orgId", "createdAt", "updatedAt" ] }, - "PlayHTCredential": { + "SmallestAICredential": { "type": "object", "properties": { "provider": { "type": "string", "enum": [ - "playht" + "smallest-ai" ] }, "apiKey": { @@ -41794,9 +68281,6 @@ "description": "This is the name of credential. This is just for your reference.", "minLength": 1, "maxLength": 40 - }, - "userId": { - "type": "string" } }, "required": [ @@ -41805,23 +68289,26 @@ "id", "orgId", "createdAt", - "updatedAt", - "userId" + "updatedAt" ] }, - "RimeAICredential": { + "SonioxCredential": { "type": "object", "properties": { "provider": { "type": "string", "enum": [ - "rime-ai" + "soniox" ] }, "apiKey": { "type": "string", "description": "This is not returned in the API." }, + "apiUrl": { + "type": "string", + "description": "Custom Soniox WebSocket endpoint (e.g. EU server wss://stt-rt.eu.soniox.com/transcribe-websocket). Defaults to the region-appropriate endpoint when omitted." + }, "id": { "type": "string", "description": "This is the unique identifier for the credential." @@ -41856,13 +68343,13 @@ "updatedAt" ] }, - "RunpodCredential": { + "SpeechmaticsCredential": { "type": "object", "properties": { "provider": { "type": "string", "enum": [ - "runpod" + "speechmatics" ] }, "apiKey": { @@ -41903,35 +68390,15 @@ "updatedAt" ] }, - "S3Credential": { + "SupabaseCredential": { "type": "object", "properties": { "provider": { "type": "string", "enum": [ - "s3" + "supabase" ], - "description": "Credential provider. Only allowed value is s3" - }, - "awsAccessKeyId": { - "type": "string", - "description": "AWS access key ID." - }, - "awsSecretAccessKey": { - "type": "string", - "description": "AWS access key secret. This is not returned in the API." - }, - "region": { - "type": "string", - "description": "AWS region in which the S3 bucket is located." - }, - "s3BucketName": { - "type": "string", - "description": "AWS S3 bucket name." - }, - "s3PathPrefix": { - "type": "string", - "description": "The path prefix for the uploaded recording. Ex. \"recordings/\"" + "description": "This is for supabase storage." }, "fallbackIndex": { "type": "number", @@ -41961,28 +68428,26 @@ "description": "This is the name of credential. This is just for your reference.", "minLength": 1, "maxLength": 40 + }, + "bucketPlan": { + "$ref": "#/components/schemas/SupabaseBucketPlan" } }, "required": [ "provider", - "awsAccessKeyId", - "awsSecretAccessKey", - "region", - "s3BucketName", - "s3PathPrefix", "id", "orgId", "createdAt", "updatedAt" ] }, - "SmallestAICredential": { + "TavusCredential": { "type": "object", "properties": { "provider": { "type": "string", "enum": [ - "smallest-ai" + "tavus" ] }, "apiKey": { @@ -42023,13 +68488,13 @@ "updatedAt" ] }, - "SpeechmaticsCredential": { + "TogetherAICredential": { "type": "object", "properties": { "provider": { "type": "string", "enum": [ - "speechmatics" + "together-ai" ] }, "apiKey": { @@ -42070,20 +68535,26 @@ "updatedAt" ] }, - "SupabaseCredential": { + "TwilioCredential": { "type": "object", "properties": { "provider": { "type": "string", "enum": [ - "supabase" - ], - "description": "This is for supabase storage." + "twilio" + ] }, - "fallbackIndex": { - "type": "number", - "minimum": 1, - "description": "This is the order in which this storage provider is tried during upload retries. Lower numbers are tried first in increasing order." + "authToken": { + "type": "string", + "description": "This is not returned in the API." + }, + "apiKey": { + "type": "string", + "description": "This is not returned in the API." + }, + "apiSecret": { + "type": "string", + "description": "This is not returned in the API." }, "id": { "type": "string", @@ -42109,8 +68580,8 @@ "minLength": 1, "maxLength": 40 }, - "bucketPlan": { - "$ref": "#/components/schemas/SupabaseBucketPlan" + "accountSid": { + "type": "string" } }, "required": [ @@ -42118,19 +68589,25 @@ "id", "orgId", "createdAt", - "updatedAt" + "updatedAt", + "accountSid" ] }, - "TavusCredential": { + "VonageCredential": { "type": "object", "properties": { + "vonageApplicationPrivateKey": { + "type": "string", + "description": "This is not returned in the API.", + "maxLength": 10000 + }, "provider": { "type": "string", "enum": [ - "tavus" + "vonage" ] }, - "apiKey": { + "apiSecret": { "type": "string", "description": "This is not returned in the API." }, @@ -42152,34 +68629,63 @@ "type": "string", "description": "This is the ISO 8601 date-time string of when the assistant was last updated." }, + "vonageApplicationId": { + "type": "string", + "description": "This is the Vonage Application ID for the credential.\n\nOnly relevant for Vonage credentials.", + "maxLength": 10000 + }, "name": { "type": "string", "description": "This is the name of credential. This is just for your reference.", "minLength": 1, "maxLength": 40 + }, + "apiKey": { + "type": "string" } }, "required": [ + "vonageApplicationPrivateKey", "provider", - "apiKey", + "apiSecret", "id", "orgId", "createdAt", - "updatedAt" + "updatedAt", + "vonageApplicationId", + "apiKey" ] }, - "TogetherAICredential": { + "WebhookCredential": { "type": "object", "properties": { "provider": { "type": "string", "enum": [ - "together-ai" + "webhook" ] }, - "apiKey": { - "type": "string", - "description": "This is not returned in the API." + "authenticationPlan": { + "description": "This is the authentication plan. Supports OAuth2 RFC 6749, HMAC signing, and Bearer authentication.", + "oneOf": [ + { + "$ref": "#/components/schemas/OAuth2AuthenticationPlan" + }, + { + "$ref": "#/components/schemas/HMACAuthenticationPlan" + }, + { + "$ref": "#/components/schemas/BearerAuthenticationPlan" + } + ], + "discriminator": { + "propertyName": "type", + "mapping": { + "oauth2": "#/components/schemas/OAuth2AuthenticationPlan", + "hmac": "#/components/schemas/HMACAuthenticationPlan", + "bearer": "#/components/schemas/BearerAuthenticationPlan" + } + } }, "id": { "type": "string", @@ -42199,6 +68705,14 @@ "type": "string", "description": "This is the ISO 8601 date-time string of when the assistant was last updated." }, + "authenticationSession": { + "description": "This is the authentication session for the credential. Available for credentials that have an authentication plan.", + "allOf": [ + { + "$ref": "#/components/schemas/Oauth2AuthenticationSession" + } + ] + }, "name": { "type": "string", "description": "This is the name of credential. This is just for your reference.", @@ -42208,25 +68722,131 @@ }, "required": [ "provider", - "apiKey", + "authenticationPlan", "id", "orgId", "createdAt", - "updatedAt" + "updatedAt", + "authenticationSession" ] }, - "TrieveCredential": { + "SpkiPemPublicKeyConfig": { "type": "object", "properties": { - "provider": { + "name": { + "type": "string", + "description": "Optional name of the key for identification purposes.", + "maxLength": 100 + }, + "format": { "type": "string", + "description": "The format of the public key.", "enum": [ - "trieve" + "spki-pem" ] }, - "apiKey": { + "pem": { "type": "string", - "description": "This is not returned in the API." + "description": "The PEM-encoded public key." + } + }, + "required": [ + "format", + "pem" + ] + }, + "PublicKeyEncryptionPlan": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The type of encryption plan.", + "enum": [ + "public-key" + ] + }, + "algorithm": { + "type": "string", + "description": "The encryption algorithm to use.", + "enum": [ + "RSA-OAEP-256" + ] + }, + "publicKey": { + "description": "The public key configuration.", + "oneOf": [ + { + "$ref": "#/components/schemas/SpkiPemPublicKeyConfig" + } + ], + "discriminator": { + "propertyName": "format", + "mapping": { + "spki-pem": "#/components/schemas/SpkiPemPublicKeyConfig" + } + }, + "allOf": [ + { + "$ref": "#/components/schemas/SpkiPemPublicKeyConfig" + } + ] + } + }, + "required": [ + "type", + "algorithm", + "publicKey" + ] + }, + "CustomCredential": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "custom-credential" + ] + }, + "authenticationPlan": { + "description": "This is the authentication plan. Supports OAuth2 RFC 6749, HMAC signing, and Bearer authentication.", + "oneOf": [ + { + "$ref": "#/components/schemas/OAuth2AuthenticationPlan" + }, + { + "$ref": "#/components/schemas/HMACAuthenticationPlan" + }, + { + "$ref": "#/components/schemas/BearerAuthenticationPlan" + } + ], + "discriminator": { + "propertyName": "type", + "mapping": { + "oauth2": "#/components/schemas/OAuth2AuthenticationPlan", + "hmac": "#/components/schemas/HMACAuthenticationPlan", + "bearer": "#/components/schemas/BearerAuthenticationPlan" + } + } + }, + "encryptionPlan": { + "description": "This is the encryption plan for encrypting sensitive data. Currently supports public-key encryption.", + "oneOf": [ + { + "$ref": "#/components/schemas/PublicKeyEncryptionPlan" + } + ], + "discriminator": { + "propertyName": "type", + "mapping": { + "public-key": "#/components/schemas/PublicKeyEncryptionPlan" + } + }, + "allOf": [ + { + "$ref": "#/components/schemas/PublicKeyEncryptionPlan" + } + ] }, "id": { "type": "string", @@ -42246,6 +68866,14 @@ "type": "string", "description": "This is the ISO 8601 date-time string of when the assistant was last updated." }, + "authenticationSession": { + "description": "This is the authentication session for the credential. Available for credentials that have an authentication plan.", + "allOf": [ + { + "$ref": "#/components/schemas/Oauth2AuthenticationSession" + } + ] + }, "name": { "type": "string", "description": "This is the name of credential. This is just for your reference.", @@ -42255,32 +68883,27 @@ }, "required": [ "provider", - "apiKey", + "authenticationPlan", "id", "orgId", "createdAt", - "updatedAt" + "updatedAt", + "authenticationSession" ] }, - "TwilioCredential": { + "XAiCredential": { "type": "object", "properties": { "provider": { "type": "string", + "description": "This is the api key for Grok in XAi's console. Get it from here: https://console.x.ai", "enum": [ - "twilio" + "xai" ] }, - "authToken": { - "type": "string", - "description": "This is not returned in the API." - }, "apiKey": { "type": "string", - "description": "This is not returned in the API." - }, - "apiSecret": { - "type": "string", + "maxLength": 10000, "description": "This is not returned in the API." }, "id": { @@ -42306,38 +68929,26 @@ "description": "This is the name of credential. This is just for your reference.", "minLength": 1, "maxLength": 40 - }, - "accountSid": { - "type": "string" } }, "required": [ "provider", + "apiKey", "id", "orgId", "createdAt", - "updatedAt", - "accountSid" + "updatedAt" ] }, - "VonageCredential": { + "GoogleCalendarOAuth2ClientCredential": { "type": "object", "properties": { - "vonageApplicationPrivateKey": { - "type": "string", - "description": "This is not returned in the API.", - "maxLength": 10000 - }, "provider": { "type": "string", "enum": [ - "vonage" + "google.calendar.oauth2-client" ] }, - "apiSecret": { - "type": "string", - "description": "This is not returned in the API." - }, "id": { "type": "string", "description": "This is the unique identifier for the credential." @@ -42356,59 +68967,33 @@ "type": "string", "description": "This is the ISO 8601 date-time string of when the assistant was last updated." }, - "vonageApplicationId": { - "type": "string", - "description": "This is the Vonage Application ID for the credential.\n\nOnly relevant for Vonage credentials.", - "maxLength": 10000 - }, "name": { "type": "string", "description": "This is the name of credential. This is just for your reference.", "minLength": 1, "maxLength": 40 - }, - "apiKey": { - "type": "string" } }, "required": [ - "vonageApplicationPrivateKey", "provider", - "apiSecret", "id", "orgId", "createdAt", - "updatedAt", - "vonageApplicationId", - "apiKey" + "updatedAt" ] }, - "WebhookCredential": { + "GoogleCalendarOAuth2AuthorizationCredential": { "type": "object", "properties": { "provider": { "type": "string", "enum": [ - "webhook" + "google.calendar.oauth2-authorization" ] }, - "authenticationPlan": { - "description": "This is the authentication plan. Supports OAuth2 RFC 6749 and HMAC signing.", - "oneOf": [ - { - "$ref": "#/components/schemas/OAuth2AuthenticationPlan" - }, - { - "$ref": "#/components/schemas/HMACAuthenticationPlan" - } - ], - "discriminator": { - "propertyName": "type", - "mapping": { - "oauth2": "#/components/schemas/OAuth2AuthenticationPlan", - "hmac": "#/components/schemas/HMACAuthenticationPlan" - } - } + "authorizationId": { + "type": "string", + "description": "The authorization ID for the OAuth2 authorization" }, "id": { "type": "string", @@ -42428,14 +69013,6 @@ "type": "string", "description": "This is the ISO 8601 date-time string of when the assistant was last updated." }, - "authenticationSession": { - "description": "This is the authentication session for the credential. Available for credentials that have an authentication plan.", - "allOf": [ - { - "$ref": "#/components/schemas/Oauth2AuthenticationSession" - } - ] - }, "name": { "type": "string", "description": "This is the name of credential. This is just for your reference.", @@ -42445,28 +69022,25 @@ }, "required": [ "provider", - "authenticationPlan", + "authorizationId", "id", "orgId", "createdAt", - "updatedAt", - "authenticationSession" + "updatedAt" ] }, - "XAiCredential": { + "GoogleSheetsOAuth2AuthorizationCredential": { "type": "object", "properties": { "provider": { "type": "string", - "description": "This is the api key for Grok in XAi's console. Get it from here: https://console.x.ai", "enum": [ - "xai" + "google.sheets.oauth2-authorization" ] }, - "apiKey": { + "authorizationId": { "type": "string", - "maxLength": 10000, - "description": "This is not returned in the API." + "description": "The authorization ID for the OAuth2 authorization" }, "id": { "type": "string", @@ -42495,22 +69069,26 @@ }, "required": [ "provider", - "apiKey", + "authorizationId", "id", "orgId", "createdAt", "updatedAt" ] }, - "GoogleCalendarOAuth2ClientCredential": { + "SlackOAuth2AuthorizationCredential": { "type": "object", "properties": { "provider": { "type": "string", "enum": [ - "google.calendar.oauth2-client" + "slack.oauth2-authorization" ] }, + "authorizationId": { + "type": "string", + "description": "The authorization ID for the OAuth2 authorization" + }, "id": { "type": "string", "description": "This is the unique identifier for the credential." @@ -42538,24 +69116,29 @@ }, "required": [ "provider", + "authorizationId", "id", "orgId", "createdAt", "updatedAt" ] }, - "GoogleCalendarOAuth2AuthorizationCredential": { + "GoHighLevelMCPCredential": { "type": "object", "properties": { "provider": { "type": "string", "enum": [ - "google.calendar.oauth2-authorization" + "ghl.oauth2-authorization" ] }, - "authorizationId": { - "type": "string", - "description": "The authorization ID for the OAuth2 authorization" + "authenticationSession": { + "description": "This is the authentication session for the credential.", + "allOf": [ + { + "$ref": "#/components/schemas/Oauth2AuthenticationSession" + } + ] }, "id": { "type": "string", @@ -42584,25 +69167,26 @@ }, "required": [ "provider", - "authorizationId", + "authenticationSession", "id", "orgId", "createdAt", "updatedAt" ] }, - "GoogleSheetsOAuth2AuthorizationCredential": { + "InworldCredential": { "type": "object", "properties": { "provider": { "type": "string", "enum": [ - "google.sheets.oauth2-authorization" + "inworld" ] }, - "authorizationId": { + "apiKey": { "type": "string", - "description": "The authorization ID for the OAuth2 authorization" + "description": "This is the Inworld Basic (Base64) authentication token. This is not returned in the API.", + "example": "your-base64-token-here" }, "id": { "type": "string", @@ -42631,25 +69215,25 @@ }, "required": [ "provider", - "authorizationId", + "apiKey", "id", "orgId", "createdAt", "updatedAt" ] }, - "SlackOAuth2AuthorizationCredential": { + "EmailCredential": { "type": "object", "properties": { "provider": { "type": "string", "enum": [ - "slack.oauth2-authorization" + "email" ] }, - "authorizationId": { + "email": { "type": "string", - "description": "The authorization ID for the OAuth2 authorization" + "description": "The recipient email address for alerts" }, "id": { "type": "string", @@ -42678,29 +69262,25 @@ }, "required": [ "provider", - "authorizationId", + "email", "id", "orgId", "createdAt", "updatedAt" ] }, - "GoHighLevelMCPCredential": { + "SlackWebhookCredential": { "type": "object", "properties": { "provider": { "type": "string", "enum": [ - "ghl.oauth2-authorization" + "slack-webhook" ] }, - "authenticationSession": { - "description": "This is the authentication session for the credential.", - "allOf": [ - { - "$ref": "#/components/schemas/Oauth2AuthenticationSession" - } - ] + "webhookUrl": { + "type": "string", + "description": "Slack incoming webhook URL. See https://api.slack.com/messaging/webhooks for setup instructions. This is not returned in the API." }, "id": { "type": "string", @@ -42729,44 +69309,26 @@ }, "required": [ "provider", - "authenticationSession", + "webhookUrl", "id", "orgId", "createdAt", "updatedAt" ] }, - "InworldCredential": { + "CreateCerebrasCredentialDTO": { "type": "object", "properties": { "provider": { "type": "string", "enum": [ - "inworld" + "cerebras" ] }, "apiKey": { "type": "string", - "description": "This is the Inworld Basic (Base64) authentication token. This is not returned in the API.", - "example": "your-base64-token-here" - }, - "id": { - "type": "string", - "description": "This is the unique identifier for the credential." - }, - "orgId": { - "type": "string", - "description": "This is the unique identifier for the org that this credential belongs to." - }, - "createdAt": { - "format": "date-time", - "type": "string", - "description": "This is the ISO 8601 date-time string of when the credential was created." - }, - "updatedAt": { - "format": "date-time", - "type": "string", - "description": "This is the ISO 8601 date-time string of when the assistant was last updated." + "maxLength": 10000, + "description": "This is not returned in the API." }, "name": { "type": "string", @@ -42777,20 +69339,17 @@ }, "required": [ "provider", - "apiKey", - "id", - "orgId", - "createdAt", - "updatedAt" + "apiKey" ] }, - "CreateCerebrasCredentialDTO": { + "CreateGoogleCredentialDTO": { "type": "object", "properties": { "provider": { "type": "string", + "description": "This is the key for Gemini in Google AI Studio. Get it from here: https://aistudio.google.com/app/apikey", "enum": [ - "cerebras" + "google" ] }, "apiKey": { @@ -42810,14 +69369,13 @@ "apiKey" ] }, - "CreateGoogleCredentialDTO": { + "CreateHumeCredentialDTO": { "type": "object", "properties": { "provider": { "type": "string", - "description": "This is the key for Gemini in Google AI Studio. Get it from here: https://aistudio.google.com/app/apikey", "enum": [ - "google" + "hume" ] }, "apiKey": { @@ -42837,13 +69395,14 @@ "apiKey" ] }, - "CreateHumeCredentialDTO": { + "CreateInflectionAICredentialDTO": { "type": "object", "properties": { "provider": { "type": "string", + "description": "This is the api key for Pi in InflectionAI's console. Get it from here: https://developers.inflection.ai/keys, billing will need to be setup", "enum": [ - "hume" + "inflection-ai" ] }, "apiKey": { @@ -42863,20 +69422,25 @@ "apiKey" ] }, - "CreateInflectionAICredentialDTO": { + "CreateMicrosoftCredentialDTO": { "type": "object", "properties": { "provider": { "type": "string", - "description": "This is the api key for Pi in InflectionAI's console. Get it from here: https://developers.inflection.ai/keys, billing will need to be setup", "enum": [ - "inflection-ai" + "microsoft" ] }, "apiKey": { "type": "string", - "maxLength": 10000, - "description": "This is not returned in the API." + "description": "This is not returned in the API.", + "maxLength": 10000 + }, + "region": { + "type": "string", + "description": "Azure region for the Speech resource. Defaults to `eastus` when omitted. MAI-Voice-2 is preview and region-limited.", + "maxLength": 64, + "example": "eastus" }, "name": { "type": "string", @@ -42941,17 +69505,18 @@ "apiKey" ] }, - "CreateSpeechmaticsCredentialDTO": { + "CreateWellSaidCredentialDTO": { "type": "object", "properties": { "provider": { "type": "string", "enum": [ - "speechmatics" + "wellsaid" ] }, "apiKey": { "type": "string", + "maxLength": 10000, "description": "This is not returned in the API." }, "name": { @@ -42966,19 +69531,53 @@ "apiKey" ] }, - "CreateTrieveCredentialDTO": { + "CreateS3CompatibleCredentialDTO": { "type": "object", "properties": { "provider": { "type": "string", "enum": [ - "trieve" + "s3-compatible" + ], + "description": "This is for S3-compatible storage such as MinIO, Garage, Ceph, or Backblaze B2." + }, + "bucketPlan": { + "$ref": "#/components/schemas/S3CompatibleBucketPlan" + }, + "fallbackIndex": { + "type": "number", + "minimum": 1, + "description": "This is the order in which this storage provider is tried during upload retries. Lower numbers are tried first in increasing order." + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + }, + "required": [ + "provider", + "bucketPlan" + ] + }, + "CreateSonioxCredentialDTO": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "soniox" ] }, "apiKey": { "type": "string", "description": "This is not returned in the API." }, + "apiUrl": { + "type": "string", + "description": "Custom Soniox WebSocket endpoint (e.g. EU server wss://stt-rt.eu.soniox.com/transcribe-websocket). Defaults to the region-appropriate endpoint when omitted." + }, "name": { "type": "string", "description": "This is the name of credential. This is just for your reference.", @@ -42991,6 +69590,93 @@ "apiKey" ] }, + "CreateSpeechmaticsCredentialDTO": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "speechmatics" + ] + }, + "apiKey": { + "type": "string", + "description": "This is not returned in the API." + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + }, + "required": [ + "provider", + "apiKey" + ] + }, + "CreateCustomCredentialDTO": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "custom-credential" + ] + }, + "authenticationPlan": { + "description": "This is the authentication plan. Supports OAuth2 RFC 6749, HMAC signing, and Bearer authentication.", + "oneOf": [ + { + "$ref": "#/components/schemas/OAuth2AuthenticationPlan" + }, + { + "$ref": "#/components/schemas/HMACAuthenticationPlan" + }, + { + "$ref": "#/components/schemas/BearerAuthenticationPlan" + } + ], + "discriminator": { + "propertyName": "type", + "mapping": { + "oauth2": "#/components/schemas/OAuth2AuthenticationPlan", + "hmac": "#/components/schemas/HMACAuthenticationPlan", + "bearer": "#/components/schemas/BearerAuthenticationPlan" + } + } + }, + "encryptionPlan": { + "description": "This is the encryption plan for encrypting sensitive data. Currently supports public-key encryption.", + "oneOf": [ + { + "$ref": "#/components/schemas/PublicKeyEncryptionPlan" + } + ], + "discriminator": { + "propertyName": "type", + "mapping": { + "public-key": "#/components/schemas/PublicKeyEncryptionPlan" + } + }, + "allOf": [ + { + "$ref": "#/components/schemas/PublicKeyEncryptionPlan" + } + ] + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + }, + "required": [ + "provider", + "authenticationPlan" + ] + }, "CreateGoHighLevelMCPCredentialDTO": { "type": "object", "properties": { @@ -43046,9 +69732,65 @@ "apiKey" ] }, + "CreateEmailCredentialDTO": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "email" + ] + }, + "email": { + "type": "string", + "description": "The recipient email address for alerts" + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + }, + "required": [ + "provider", + "email" + ] + }, + "CreateSlackWebhookCredentialDTO": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "slack-webhook" + ] + }, + "webhookUrl": { + "type": "string", + "description": "Slack incoming webhook URL. See https://api.slack.com/messaging/webhooks for setup instructions. This is not returned in the API." + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + }, + "required": [ + "provider", + "webhookUrl" + ] + }, "UpdateAnthropicCredentialDTO": { "type": "object", "properties": { + "provider": { + "type": "string", + "enum": [ + "anthropic" + ] + }, "apiKey": { "type": "string", "maxLength": 10000, @@ -43062,9 +69804,56 @@ } } }, + "UpdateAnthropicBedrockCredentialDTO": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "anthropic-bedrock" + ] + }, + "region": { + "type": "string", + "description": "AWS region where Bedrock is configured.", + "enum": [ + "us-east-1", + "us-west-2", + "eu-central-1", + "eu-west-1", + "eu-west-3", + "ap-northeast-1", + "ap-southeast-2" + ] + }, + "authenticationPlan": { + "description": "Authentication method - either direct IAM credentials or cross-account role assumption.", + "oneOf": [ + { + "$ref": "#/components/schemas/AWSIAMCredentialsAuthenticationPlan" + }, + { + "$ref": "#/components/schemas/AWSStsAuthenticationPlan" + } + ] + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + } + }, "UpdateAnyscaleCredentialDTO": { "type": "object", "properties": { + "provider": { + "type": "string", + "enum": [ + "anyscale" + ] + }, "apiKey": { "type": "string", "maxLength": 10000, @@ -43081,6 +69870,12 @@ "UpdateAssemblyAICredentialDTO": { "type": "object", "properties": { + "provider": { + "type": "string", + "enum": [ + "assembly-ai" + ] + }, "apiKey": { "type": "string", "description": "This is not returned in the API." @@ -43096,6 +69891,12 @@ "UpdateAzureCredentialDTO": { "type": "object", "properties": { + "provider": { + "type": "string", + "enum": [ + "azure" + ] + }, "service": { "type": "string", "description": "This is the service being used in Azure.", @@ -43109,22 +69910,29 @@ "type": "string", "description": "This is the region of the Azure resource.", "enum": [ - "australia", + "australiaeast", "canadaeast", "canadacentral", + "centralus", "eastus2", "eastus", "france", + "germanywestcentral", "india", "japaneast", "japanwest", - "uaenorth", "northcentralus", "norway", + "polandcentral", "southcentralus", + "spaincentral", "swedencentral", "switzerland", + "switzerlandnorth", + "switzerlandwest", + "uaenorth", "uk", + "westeurope", "westus", "westus3" ] @@ -43158,25 +69966,38 @@ "UpdateAzureOpenAICredentialDTO": { "type": "object", "properties": { + "provider": { + "type": "string", + "enum": [ + "azure-openai" + ] + }, "region": { "type": "string", "enum": [ - "australia", + "australiaeast", "canadaeast", "canadacentral", + "centralus", "eastus2", "eastus", "france", + "germanywestcentral", "india", "japaneast", "japanwest", - "uaenorth", "northcentralus", "norway", + "polandcentral", "southcentralus", + "spaincentral", "swedencentral", "switzerland", + "switzerlandnorth", + "switzerlandwest", + "uaenorth", "uk", + "westeurope", "westus", "westus3" ] @@ -43184,6 +70005,16 @@ "models": { "type": "array", "enum": [ + "gpt-5.6-luna-2026-07-09", + "gpt-5.6-terra-2026-07-09", + "gpt-5.6-sol-2026-07-09", + "gpt-5.4", + "gpt-5.4-mini", + "gpt-5.4-nano", + "gpt-5.2", + "gpt-5.2-chat", + "gpt-5.1", + "gpt-5.1-chat", "gpt-5", "gpt-5-mini", "gpt-5-nano", @@ -43199,7 +70030,10 @@ "gpt-4-1106-preview", "gpt-4-0613", "gpt-35-turbo-0125", - "gpt-35-turbo-1106" + "gpt-35-turbo-1106", + "gpt-4o", + "gpt-4.1", + "gpt-5.4-mini-2026-03-17" ], "example": [ "gpt-4-0125-preview", @@ -43208,6 +70042,16 @@ "items": { "type": "string", "enum": [ + "gpt-5.6-luna-2026-07-09", + "gpt-5.6-terra-2026-07-09", + "gpt-5.6-sol-2026-07-09", + "gpt-5.4", + "gpt-5.4-mini", + "gpt-5.4-nano", + "gpt-5.2", + "gpt-5.2-chat", + "gpt-5.1", + "gpt-5.1-chat", "gpt-5", "gpt-5-mini", "gpt-5-nano", @@ -43223,7 +70067,10 @@ "gpt-4-1106-preview", "gpt-4-0613", "gpt-35-turbo-0125", - "gpt-35-turbo-1106" + "gpt-35-turbo-1106", + "gpt-4o", + "gpt-4.1", + "gpt-5.4-mini-2026-03-17" ] } }, @@ -43251,6 +70098,13 @@ "UpdateByoSipTrunkCredentialDTO": { "type": "object", "properties": { + "provider": { + "type": "string", + "description": "This can be used to bring your own SIP trunks or to connect to a Carrier.", + "enum": [ + "byo-sip-trunk" + ] + }, "name": { "type": "string", "description": "This is the name of credential. This is just for your reference.", @@ -43285,20 +70139,18 @@ "type": "string", "description": "This can be used to enable the SIP diversion header for authenticating the calling number if the SIP trunk supports it. This is an advanced property.", "maxLength": 10000 - }, - "sbcConfiguration": { - "description": "This is an advanced configuration for enterprise deployments. This uses the onprem SBC to trunk into the SIP trunk's `gateways`, rather than the managed SBC provided by Vapi.", - "allOf": [ - { - "$ref": "#/components/schemas/SbcConfiguration" - } - ] } } }, "UpdateCartesiaCredentialDTO": { "type": "object", "properties": { + "provider": { + "type": "string", + "enum": [ + "cartesia" + ] + }, "apiKey": { "type": "string", "description": "This is not returned in the API." @@ -43308,12 +70160,22 @@ "description": "This is the name of credential. This is just for your reference.", "minLength": 1, "maxLength": 40 + }, + "apiUrl": { + "type": "string", + "description": "This can be used to point to an onprem Cartesia instance. Defaults to api.cartesia.ai." } } }, "UpdateCerebrasCredentialDTO": { "type": "object", "properties": { + "provider": { + "type": "string", + "enum": [ + "cerebras" + ] + }, "apiKey": { "type": "string", "maxLength": 10000, @@ -43330,6 +70192,13 @@ "UpdateCloudflareCredentialDTO": { "type": "object", "properties": { + "provider": { + "type": "string", + "enum": [ + "cloudflare" + ], + "description": "Credential provider. Only allowed value is cloudflare" + }, "accountId": { "type": "string", "description": "Cloudflare Account Id." @@ -43366,6 +70235,12 @@ "UpdateCustomLLMCredentialDTO": { "type": "object", "properties": { + "provider": { + "type": "string", + "enum": [ + "custom-llm" + ] + }, "apiKey": { "type": "string", "maxLength": 10000, @@ -43390,6 +70265,12 @@ "UpdateDeepgramCredentialDTO": { "type": "object", "properties": { + "provider": { + "type": "string", + "enum": [ + "deepgram" + ] + }, "apiKey": { "type": "string", "description": "This is not returned in the API." @@ -43409,6 +70290,12 @@ "UpdateDeepInfraCredentialDTO": { "type": "object", "properties": { + "provider": { + "type": "string", + "enum": [ + "deepinfra" + ] + }, "apiKey": { "type": "string", "description": "This is not returned in the API." @@ -43424,6 +70311,12 @@ "UpdateDeepSeekCredentialDTO": { "type": "object", "properties": { + "provider": { + "type": "string", + "enum": [ + "deep-seek" + ] + }, "apiKey": { "type": "string", "description": "This is not returned in the API." @@ -43439,11 +70332,26 @@ "UpdateElevenLabsCredentialDTO": { "type": "object", "properties": { + "provider": { + "type": "string", + "enum": [ + "11labs" + ] + }, "apiKey": { "type": "string", "maxLength": 10000, "description": "This is not returned in the API." }, + "apiUrl": { + "type": "string", + "enum": [ + "https://api.elevenlabs.io", + "https://api.eu.residency.elevenlabs.io" + ], + "description": "ElevenLabs-only API environment for this key: the global endpoint or the EU data residency endpoint. In EU deployments, new credentials must explicitly use the EU data residency endpoint; existing credentials may omit this field on update to retain their saved endpoint. Outside EU deployments, Vapi detects an omitted endpoint automatically and null on update clears and re-detects the endpoint.", + "nullable": true + }, "name": { "type": "string", "description": "This is the name of credential. This is just for your reference.", @@ -43455,6 +70363,12 @@ "UpdateGcpCredentialDTO": { "type": "object", "properties": { + "provider": { + "type": "string", + "enum": [ + "gcp" + ] + }, "fallbackIndex": { "type": "number", "description": "This is the order in which this storage provider is tried during upload retries. Lower numbers are tried first in increasing order.", @@ -43487,6 +70401,12 @@ "UpdateGladiaCredentialDTO": { "type": "object", "properties": { + "provider": { + "type": "string", + "enum": [ + "gladia" + ] + }, "apiKey": { "type": "string", "description": "This is not returned in the API." @@ -43502,6 +70422,12 @@ "UpdateGoHighLevelCredentialDTO": { "type": "object", "properties": { + "provider": { + "type": "string", + "enum": [ + "gohighlevel" + ] + }, "apiKey": { "type": "string", "description": "This is not returned in the API." @@ -43517,6 +70443,13 @@ "UpdateGoogleCredentialDTO": { "type": "object", "properties": { + "provider": { + "type": "string", + "description": "This is the key for Gemini in Google AI Studio. Get it from here: https://aistudio.google.com/app/apikey", + "enum": [ + "google" + ] + }, "apiKey": { "type": "string", "maxLength": 10000, @@ -43533,6 +70466,12 @@ "UpdateGroqCredentialDTO": { "type": "object", "properties": { + "provider": { + "type": "string", + "enum": [ + "groq" + ] + }, "apiKey": { "type": "string", "description": "This is not returned in the API." @@ -43548,6 +70487,12 @@ "UpdateHumeCredentialDTO": { "type": "object", "properties": { + "provider": { + "type": "string", + "enum": [ + "hume" + ] + }, "apiKey": { "type": "string", "maxLength": 10000, @@ -43564,6 +70509,13 @@ "UpdateInflectionAICredentialDTO": { "type": "object", "properties": { + "provider": { + "type": "string", + "description": "This is the api key for Pi in InflectionAI's console. Get it from here: https://developers.inflection.ai/keys, billing will need to be setup", + "enum": [ + "inflection-ai" + ] + }, "apiKey": { "type": "string", "maxLength": 10000, @@ -43580,6 +70532,12 @@ "UpdateLangfuseCredentialDTO": { "type": "object", "properties": { + "provider": { + "type": "string", + "enum": [ + "langfuse" + ] + }, "publicKey": { "type": "string", "description": "The public key for Langfuse project. Eg: pk-lf-..." @@ -43603,6 +70561,12 @@ "UpdateLmntCredentialDTO": { "type": "object", "properties": { + "provider": { + "type": "string", + "enum": [ + "lmnt" + ] + }, "apiKey": { "type": "string", "description": "This is not returned in the API." @@ -43618,6 +70582,12 @@ "UpdateMakeCredentialDTO": { "type": "object", "properties": { + "provider": { + "type": "string", + "enum": [ + "make" + ] + }, "teamId": { "type": "string", "description": "Team ID" @@ -43638,9 +70608,43 @@ } } }, + "UpdateMicrosoftCredentialDTO": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "microsoft" + ] + }, + "apiKey": { + "type": "string", + "description": "This is not returned in the API.", + "maxLength": 10000 + }, + "region": { + "type": "string", + "description": "Azure region for the Speech resource. Defaults to `eastus` when omitted. MAI-Voice-2 is preview and region-limited.", + "maxLength": 64, + "example": "eastus" + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + } + }, "UpdateMistralCredentialDTO": { "type": "object", "properties": { + "provider": { + "type": "string", + "enum": [ + "mistral" + ] + }, "apiKey": { "type": "string", "maxLength": 100, @@ -43657,6 +70661,12 @@ "UpdateNeuphonicCredentialDTO": { "type": "object", "properties": { + "provider": { + "type": "string", + "enum": [ + "neuphonic" + ] + }, "apiKey": { "type": "string", "description": "This is not returned in the API." @@ -43672,6 +70682,12 @@ "UpdateOpenAICredentialDTO": { "type": "object", "properties": { + "provider": { + "type": "string", + "enum": [ + "openai" + ] + }, "apiKey": { "type": "string", "description": "This is not returned in the API." @@ -43687,6 +70703,12 @@ "UpdateOpenRouterCredentialDTO": { "type": "object", "properties": { + "provider": { + "type": "string", + "enum": [ + "openrouter" + ] + }, "apiKey": { "type": "string", "description": "This is not returned in the API." @@ -43702,6 +70724,12 @@ "UpdatePerplexityAICredentialDTO": { "type": "object", "properties": { + "provider": { + "type": "string", + "enum": [ + "perplexity-ai" + ] + }, "apiKey": { "type": "string", "description": "This is not returned in the API." @@ -43717,6 +70745,12 @@ "UpdatePlayHTCredentialDTO": { "type": "object", "properties": { + "provider": { + "type": "string", + "enum": [ + "playht" + ] + }, "apiKey": { "type": "string", "description": "This is not returned in the API." @@ -43735,6 +70769,12 @@ "UpdateRimeAICredentialDTO": { "type": "object", "properties": { + "provider": { + "type": "string", + "enum": [ + "rime-ai" + ] + }, "apiKey": { "type": "string", "description": "This is not returned in the API." @@ -43750,8 +70790,36 @@ "UpdateRunpodCredentialDTO": { "type": "object", "properties": { + "provider": { + "type": "string", + "enum": [ + "runpod" + ] + }, + "apiKey": { + "type": "string", + "description": "This is not returned in the API." + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + } + }, + "UpdateWellSaidCredentialDTO": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "wellsaid" + ] + }, "apiKey": { "type": "string", + "maxLength": 10000, "description": "This is not returned in the API." }, "name": { @@ -43765,6 +70833,13 @@ "UpdateS3CredentialDTO": { "type": "object", "properties": { + "provider": { + "type": "string", + "enum": [ + "s3" + ], + "description": "Credential provider. Only allowed value is s3" + }, "awsAccessKeyId": { "type": "string", "description": "AWS access key ID." @@ -43798,61 +70873,54 @@ } } }, - "UpdateSmallestAICredentialDTO": { + "UpdateS3CompatibleBucketPlanDTO": { "type": "object", "properties": { - "apiKey": { + "url": { "type": "string", - "description": "This is not returned in the API." + "description": "S3-compatible endpoint URL, such as https://s3.us-west-004.backblazeb2.com. Must be public HTTPS." }, - "name": { + "region": { "type": "string", - "description": "This is the name of credential. This is just for your reference.", - "minLength": 1, - "maxLength": 40 - } - } - }, - "UpdateSpeechmaticsCredentialDTO": { - "type": "object", - "properties": { - "apiKey": { + "maxLength": 64, + "description": "SigV4 signing region expected by the object store. Most stores accept us-east-1." + }, + "accessKeyId": { "type": "string", - "description": "This is not returned in the API." + "description": "S3 access key ID." + }, + "secretAccessKey": { + "type": "string", + "description": "S3 secret access key. This is not returned in the API.", + "writeOnly": true }, "name": { "type": "string", - "description": "This is the name of credential. This is just for your reference.", - "minLength": 1, - "maxLength": 40 + "description": "Bucket name." + }, + "path": { + "type": "string", + "description": "Optional key prefix inside the bucket, such as recordings/." } } }, - "UpdateSupabaseCredentialDTO": { + "UpdateS3CompatibleCredentialDTO": { "type": "object", "properties": { + "provider": { + "type": "string", + "enum": [ + "s3-compatible" + ], + "description": "This is for S3-compatible storage such as MinIO, Garage, Ceph, or Backblaze B2." + }, "fallbackIndex": { "type": "number", "minimum": 1, "description": "This is the order in which this storage provider is tried during upload retries. Lower numbers are tried first in increasing order." }, - "name": { - "type": "string", - "description": "This is the name of credential. This is just for your reference.", - "minLength": 1, - "maxLength": 40 - }, "bucketPlan": { - "$ref": "#/components/schemas/SupabaseBucketPlan" - } - } - }, - "UpdateTavusCredentialDTO": { - "type": "object", - "properties": { - "apiKey": { - "type": "string", - "description": "This is not returned in the API." + "$ref": "#/components/schemas/UpdateS3CompatibleBucketPlanDTO" }, "name": { "type": "string", @@ -43865,21 +70933,12 @@ "UpdateTogetherAICredentialDTO": { "type": "object", "properties": { - "apiKey": { + "provider": { "type": "string", - "description": "This is not returned in the API." + "enum": [ + "together-ai" + ] }, - "name": { - "type": "string", - "description": "This is the name of credential. This is just for your reference.", - "minLength": 1, - "maxLength": 40 - } - } - }, - "UpdateTrieveCredentialDTO": { - "type": "object", - "properties": { "apiKey": { "type": "string", "description": "This is not returned in the API." @@ -43895,6 +70954,12 @@ "UpdateTwilioCredentialDTO": { "type": "object", "properties": { + "provider": { + "type": "string", + "enum": [ + "twilio" + ] + }, "authToken": { "type": "string", "description": "This is not returned in the API." @@ -43921,6 +70986,12 @@ "UpdateVonageCredentialDTO": { "type": "object", "properties": { + "provider": { + "type": "string", + "enum": [ + "vonage" + ] + }, "apiSecret": { "type": "string", "description": "This is not returned in the API." @@ -43939,24 +71010,92 @@ "UpdateWebhookCredentialDTO": { "type": "object", "properties": { + "provider": { + "type": "string", + "enum": [ + "webhook" + ] + }, + "authenticationPlan": { + "description": "This is the authentication plan. Supports OAuth2 RFC 6749, HMAC signing, and Bearer authentication.", + "oneOf": [ + { + "$ref": "#/components/schemas/OAuth2AuthenticationPlan" + }, + { + "$ref": "#/components/schemas/HMACAuthenticationPlan" + }, + { + "$ref": "#/components/schemas/BearerAuthenticationPlan" + } + ], + "discriminator": { + "propertyName": "type", + "mapping": { + "oauth2": "#/components/schemas/OAuth2AuthenticationPlan", + "hmac": "#/components/schemas/HMACAuthenticationPlan", + "bearer": "#/components/schemas/BearerAuthenticationPlan" + } + } + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + } + }, + "UpdateCustomCredentialDTO": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "custom-credential" + ] + }, "authenticationPlan": { - "description": "This is the authentication plan. Supports OAuth2 RFC 6749 and HMAC signing.", + "description": "This is the authentication plan. Supports OAuth2 RFC 6749, HMAC signing, and Bearer authentication.", "oneOf": [ { "$ref": "#/components/schemas/OAuth2AuthenticationPlan" }, { "$ref": "#/components/schemas/HMACAuthenticationPlan" + }, + { + "$ref": "#/components/schemas/BearerAuthenticationPlan" } ], "discriminator": { "propertyName": "type", "mapping": { "oauth2": "#/components/schemas/OAuth2AuthenticationPlan", - "hmac": "#/components/schemas/HMACAuthenticationPlan" + "hmac": "#/components/schemas/HMACAuthenticationPlan", + "bearer": "#/components/schemas/BearerAuthenticationPlan" } } }, + "encryptionPlan": { + "description": "This is the encryption plan for encrypting sensitive data. Currently supports public-key encryption.", + "oneOf": [ + { + "$ref": "#/components/schemas/PublicKeyEncryptionPlan" + } + ], + "discriminator": { + "propertyName": "type", + "mapping": { + "public-key": "#/components/schemas/PublicKeyEncryptionPlan" + } + }, + "allOf": [ + { + "$ref": "#/components/schemas/PublicKeyEncryptionPlan" + } + ] + }, "name": { "type": "string", "description": "This is the name of credential. This is just for your reference.", @@ -43968,6 +71107,13 @@ "UpdateXAiCredentialDTO": { "type": "object", "properties": { + "provider": { + "type": "string", + "description": "This is the api key for Grok in XAi's console. Get it from here: https://console.x.ai", + "enum": [ + "xai" + ] + }, "apiKey": { "type": "string", "maxLength": 10000, @@ -43984,6 +71130,12 @@ "UpdateGoogleCalendarOAuth2ClientCredentialDTO": { "type": "object", "properties": { + "provider": { + "type": "string", + "enum": [ + "google.calendar.oauth2-client" + ] + }, "name": { "type": "string", "description": "This is the name of credential. This is just for your reference.", @@ -43995,6 +71147,12 @@ "UpdateGoogleCalendarOAuth2AuthorizationCredentialDTO": { "type": "object", "properties": { + "provider": { + "type": "string", + "enum": [ + "google.calendar.oauth2-authorization" + ] + }, "authorizationId": { "type": "string", "description": "The authorization ID for the OAuth2 authorization" @@ -44010,6 +71168,12 @@ "UpdateGoogleSheetsOAuth2AuthorizationCredentialDTO": { "type": "object", "properties": { + "provider": { + "type": "string", + "enum": [ + "google.sheets.oauth2-authorization" + ] + }, "authorizationId": { "type": "string", "description": "The authorization ID for the OAuth2 authorization" @@ -44025,6 +71189,12 @@ "UpdateSlackOAuth2AuthorizationCredentialDTO": { "type": "object", "properties": { + "provider": { + "type": "string", + "enum": [ + "slack.oauth2-authorization" + ] + }, "authorizationId": { "type": "string", "description": "The authorization ID for the OAuth2 authorization" @@ -44040,6 +71210,12 @@ "UpdateGoHighLevelMCPCredentialDTO": { "type": "object", "properties": { + "provider": { + "type": "string", + "enum": [ + "ghl.oauth2-authorization" + ] + }, "authenticationSession": { "description": "This is the authentication session for the credential.", "allOf": [ @@ -44059,6 +71235,12 @@ "UpdateInworldCredentialDTO": { "type": "object", "properties": { + "provider": { + "type": "string", + "enum": [ + "inworld" + ] + }, "apiKey": { "type": "string", "description": "This is the Inworld Basic (Base64) authentication token. This is not returned in the API.", @@ -44072,6 +71254,73 @@ } } }, + "UpdateEmailCredentialDTO": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "email" + ] + }, + "email": { + "type": "string", + "description": "The recipient email address for alerts" + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + } + }, + "UpdateSlackWebhookCredentialDTO": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "slack-webhook" + ] + }, + "webhookUrl": { + "type": "string", + "description": "Slack incoming webhook URL. See https://api.slack.com/messaging/webhooks for setup instructions. This is not returned in the API." + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + } + }, + "UpdateSonioxCredentialDTO": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "enum": [ + "soniox" + ] + }, + "apiKey": { + "type": "string", + "description": "This is not returned in the API." + }, + "apiUrl": { + "type": "string", + "description": "Custom Soniox WebSocket endpoint (e.g. EU server wss://stt-rt.eu.soniox.com/transcribe-websocket). Defaults to the region-appropriate endpoint when omitted." + }, + "name": { + "type": "string", + "description": "This is the name of credential. This is just for your reference.", + "minLength": 1, + "maxLength": 40 + } + } + }, "CredentialSessionResponse": { "type": "object", "properties": { @@ -44086,11 +71335,18 @@ "CredentialEndUser": { "type": "object", "properties": { + "endUserEmail": { + "type": "string", + "nullable": true + }, "endUserId": { "type": "string" }, "organizationId": { "type": "string" + }, + "tags": { + "type": "object" } }, "required": [ @@ -44163,6 +71419,9 @@ }, "error": { "$ref": "#/components/schemas/CredentialSessionError" + }, + "tags": { + "type": "object" } }, "required": [ @@ -44258,22 +71517,82 @@ "algorithm" ] }, - "CredentialSessionDTO": { + "BearerAuthenticationPlan": { "type": "object", "properties": { - "provider": { + "type": { "type": "string", "enum": [ - "google.calendar.oauth2-client", - "google.calendar.oauth2-authorization", - "google.sheets.oauth2-authorization", - "slack.oauth2-authorization" - ], - "description": "The type of credential to generate a session for. Only Nango user-facing providers are supported." + "bearer" + ] + }, + "token": { + "type": "string", + "description": "This is the bearer token value." + }, + "headerName": { + "type": "string", + "description": "This is the header name where the bearer token will be sent. Defaults to 'Authorization'." + }, + "bearerPrefixEnabled": { + "type": "boolean", + "description": "Whether to include the 'Bearer ' prefix in the header value. Defaults to true." } }, "required": [ - "provider" + "type", + "token" + ] + }, + "AWSIAMCredentialsAuthenticationPlan": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "aws-iam" + ] + }, + "awsAccessKeyId": { + "type": "string", + "description": "AWS Access Key ID. This is not returned in the API.", + "maxLength": 128 + }, + "awsSecretAccessKey": { + "type": "string", + "description": "AWS Secret Access Key. This is not returned in the API.", + "maxLength": 256 + } + }, + "required": [ + "type", + "awsAccessKeyId", + "awsSecretAccessKey" + ] + }, + "AWSStsAuthenticationPlan": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "This is the type of authentication plan", + "enum": [ + "aws-sts" + ] + }, + "roleArn": { + "type": "string", + "description": "This is the role ARN for the AWS credential" + }, + "externalId": { + "type": "string", + "description": "Optional external ID for additional security in the role trust policy.", + "maxLength": 256 + } + }, + "required": [ + "type", + "roleArn" ] }, "ToolTemplateSetup": { @@ -44575,6 +71894,10 @@ "$ref": "#/components/schemas/CreateBashToolDTO", "title": "BashTool" }, + { + "$ref": "#/components/schemas/CreateCodeToolDTO", + "title": "CodeTool" + }, { "$ref": "#/components/schemas/CreateComputerToolDTO", "title": "ComputerTool" @@ -44646,6 +71969,14 @@ { "$ref": "#/components/schemas/CreateTransferCallToolDTO", "title": "TransferCallTool" + }, + { + "$ref": "#/components/schemas/CreateSipRequestToolDTO", + "title": "SipRequestTool" + }, + { + "$ref": "#/components/schemas/CreateVoicemailToolDTO", + "title": "VoicemailTool" } ] }, @@ -44738,6 +72069,10 @@ "$ref": "#/components/schemas/CreateBashToolDTO", "title": "BashTool" }, + { + "$ref": "#/components/schemas/CreateCodeToolDTO", + "title": "CodeTool" + }, { "$ref": "#/components/schemas/CreateComputerToolDTO", "title": "ComputerTool" @@ -44809,6 +72144,14 @@ { "$ref": "#/components/schemas/CreateTransferCallToolDTO", "title": "TransferCallTool" + }, + { + "$ref": "#/components/schemas/CreateSipRequestToolDTO", + "title": "SipRequestTool" + }, + { + "$ref": "#/components/schemas/CreateVoicemailToolDTO", + "title": "VoicemailTool" } ] }, @@ -44923,6 +72266,10 @@ "$ref": "#/components/schemas/CreateBashToolDTO", "title": "BashTool" }, + { + "$ref": "#/components/schemas/CreateCodeToolDTO", + "title": "CodeTool" + }, { "$ref": "#/components/schemas/CreateComputerToolDTO", "title": "ComputerTool" @@ -44994,6 +72341,14 @@ { "$ref": "#/components/schemas/CreateTransferCallToolDTO", "title": "TransferCallTool" + }, + { + "$ref": "#/components/schemas/CreateSipRequestToolDTO", + "title": "SipRequestTool" + }, + { + "$ref": "#/components/schemas/CreateVoicemailToolDTO", + "title": "VoicemailTool" } ] }, @@ -45096,7 +72451,11 @@ "tavus", "sesame", "inworld", - "minimax" + "minimax", + "wellsaid", + "orpheus", + "xai", + "microsoft" ] }, "providerId": { @@ -45143,6 +72502,10 @@ "type": "string", "description": "The preview URL of the voice." }, + "sortOrder": { + "type": "number", + "description": "The sort order of the voice for display purposes. Lower values appear first." + }, "description": { "type": "string", "description": "The description of the voice." @@ -45176,6 +72539,14 @@ "format": "date-time", "type": "string", "description": "The ISO 8601 date-time string of when the voice library was last updated." + }, + "isCloned": { + "type": "boolean", + "description": "Whether this voice was cloned by the org from their own audio, as opposed\nto a seeded/preset voice. Drives the cloned filter and tag. Backed by a\nNOT NULL DEFAULT false column, so it is always present at read time." + }, + "cloneBackend": { + "type": "string", + "description": "The provider that produced the clone (e.g. 'xai'). The voice `provider`\nstays 'vapi'; this records the underlying backend. Unset for non-cloned voices." } }, "required": [ @@ -45210,7 +72581,11 @@ "tavus", "sesame", "inworld", - "minimax" + "minimax", + "wellsaid", + "orpheus", + "xai", + "microsoft" ], "items": { "type": "string", @@ -45231,7 +72606,11 @@ "tavus", "sesame", "inworld", - "minimax" + "minimax", + "wellsaid", + "orpheus", + "xai", + "microsoft" ] } } @@ -45240,16 +72619,105 @@ "CreateSesameVoiceDTO": { "type": "object", "properties": { + "file": { + "type": "string", + "description": "This is the audio file of the utterance to clone the voice from.\nConsumed by multer via FileInterceptor('file'), so it never reaches\nclass-validator; declared here (like CreateFileDTO.file) so the OpenAPI\nspec is truthful about the multipart request body.", + "format": "binary" + }, "voiceName": { "type": "string", - "description": "The name of the voice." + "description": "The name of the voice.", + "minLength": 1 }, "transcription": { "type": "string", - "description": "The transcript of the utterance." + "description": "The transcript of the utterance.", + "minLength": 1 + } + }, + "required": [ + "file", + "voiceName", + "transcription" + ] + }, + "UpdateVoiceLibraryMetadataDTO": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Updated display name for the voice." + }, + "description": { + "type": "string", + "description": "Updated description for the voice." } } }, + "CartesiaPronunciationDictItem": { + "type": "object", + "properties": { + "text": { + "type": "string", + "description": "The text to be replaced in pronunciation", + "example": "Vapi" + }, + "alias": { + "type": "string", + "description": "The pronunciation alias or IPA representation\nCan be a \"sounds-like\" guidance (e.g., \"VAH-pee\") or IPA notation (e.g., \"<<ˈ|v|ɑ|ˈ|p|i>>\")", + "example": "VAH-pee" + } + }, + "required": [ + "text", + "alias" + ] + }, + "CartesiaPronunciationDictionary": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Unique identifier for the pronunciation dictionary", + "example": "dict_abc123" + }, + "name": { + "type": "string", + "description": "Name of the pronunciation dictionary", + "example": "My Dictionary" + }, + "ownerId": { + "type": "string", + "description": "ID of the user who owns this dictionary", + "example": "user_xyz789" + }, + "pinned": { + "type": "boolean", + "description": "Whether this dictionary is pinned for the user", + "example": false + }, + "items": { + "description": "List of text-to-pronunciation mappings", + "type": "array", + "items": { + "$ref": "#/components/schemas/CartesiaPronunciationDictItem" + } + }, + "createdAt": { + "type": "string", + "description": "ISO 8601 timestamp of when the dictionary was created", + "example": "2024-01-15T10:30:00Z" + } + }, + "required": [ + "id", + "name", + "ownerId", + "pinned", + "items", + "createdAt" + ] + }, "ElevenLabsPronunciationDictionary": { "type": "object", "properties": { @@ -45332,6 +72800,7 @@ "type": "string", "description": "This is the provider that manages this resource.", "enum": [ + "cartesia", "11labs" ] }, @@ -45347,12 +72816,8 @@ "description": "This is the provider-specific identifier for the resource." }, "resource": { - "description": "This is the full resource data from the provider's API.", - "allOf": [ - { - "$ref": "#/components/schemas/ElevenLabsPronunciationDictionary" - } - ] + "type": "object", + "description": "This is the full resource data from the provider's API." } }, "required": [ @@ -45387,6 +72852,16 @@ "VoiceLibraryVoiceResponse": { "type": "object", "properties": { + "age": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "number" + } + ] + }, "voiceId": { "type": "string" }, @@ -45402,9 +72877,6 @@ "gender": { "type": "string" }, - "age": { - "type": "object" - }, "accent": { "type": "string" } @@ -45465,6 +72937,238 @@ "files" ] }, + "VapiVoiceCloneDTO": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Display name for the cloned voice." + }, + "language": { + "type": "string", + "description": "Optional language (ISO-639 / BCP-47). When omitted, xAI infers it from the\nreference audio." + }, + "files": { + "description": "Reference audio to clone the voice from (up to 120 seconds). Supported formats: MP3, WAV, OGG/Opus, WebM, AAC, M4A, FLAC, WMA.", + "type": "array", + "items": { + "type": "string", + "format": "binary" + } + } + }, + "required": [ + "name", + "files" + ] + }, + "VariableValueGroupBy": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "This is the key of the variable value to group by.", + "maxLength": 100 + } + }, + "required": [ + "key" + ] + }, + "TimeRange": { + "type": "object", + "properties": { + "step": { + "type": "string", + "description": "This is the time step for aggregations.\n\nIf not provided, defaults to returning for the entire time range.", + "enum": [ + "second", + "minute", + "hour", + "day", + "week", + "month", + "quarter", + "year", + "decade", + "century", + "millennium" + ] + }, + "start": { + "format": "date-time", + "type": "string", + "description": "This is the start date for the time range.\n\nIf not provided, defaults to the 7 days ago." + }, + "end": { + "format": "date-time", + "type": "string", + "description": "This is the end date for the time range.\n\nIf not provided, defaults to now." + }, + "timezone": { + "type": "string", + "description": "This is the timezone you want to set for the query.\n\nIf not provided, defaults to UTC." + } + } + }, + "AnalyticsOperation": { + "type": "object", + "properties": { + "operation": { + "type": "string", + "description": "This is the aggregation operation you want to perform.", + "enum": [ + "sum", + "avg", + "count", + "min", + "max", + "history" + ] + }, + "column": { + "type": "string", + "description": "This is the columns you want to perform the aggregation operation on.", + "enum": [ + "id", + "cost", + "costBreakdown.llm", + "costBreakdown.stt", + "costBreakdown.tts", + "costBreakdown.vapi", + "costBreakdown.transport", + "costBreakdown.analysisBreakdown.summary", + "costBreakdown.transcriber", + "costBreakdown.ttsCharacters", + "costBreakdown.llmPromptTokens", + "costBreakdown.llmCompletionTokens", + "costBreakdown.llmCachedPromptTokens", + "duration", + "concurrency", + "minutesUsed" + ] + }, + "alias": { + "type": "string", + "description": "This is the alias for column name returned. Defaults to `${operation}${column}`.", + "maxLength": 40 + } + }, + "required": [ + "operation", + "column" + ] + }, + "AnalyticsQuery": { + "type": "object", + "properties": { + "table": { + "type": "string", + "description": "This is the table you want to query.", + "enum": [ + "call", + "subscription" + ] + }, + "groupBy": { + "type": "array", + "description": "This is the list of columns you want to group by.", + "enum": [ + "type", + "assistantId", + "endedReason", + "analysis.successEvaluation", + "status" + ], + "items": { + "type": "string", + "enum": [ + "type", + "assistantId", + "endedReason", + "analysis.successEvaluation", + "status" + ] + } + }, + "groupByVariableValue": { + "description": "This is the list of variable value keys you want to group by.", + "type": "array", + "items": { + "$ref": "#/components/schemas/VariableValueGroupBy" + } + }, + "name": { + "type": "string", + "description": "This is the name of the query. This will be used to identify the query in the response.", + "maxLength": 40 + }, + "timeRange": { + "description": "This is the time range for the query.", + "allOf": [ + { + "$ref": "#/components/schemas/TimeRange" + } + ] + }, + "operations": { + "description": "This is the list of operations you want to perform.", + "type": "array", + "items": { + "$ref": "#/components/schemas/AnalyticsOperation" + } + } + }, + "required": [ + "table", + "name", + "operations" + ] + }, + "AnalyticsQueryDTO": { + "type": "object", + "properties": { + "queries": { + "description": "This is the list of metric queries you want to perform.", + "type": "array", + "items": { + "$ref": "#/components/schemas/AnalyticsQuery" + } + } + }, + "required": [ + "queries" + ] + }, + "AnalyticsQueryResult": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "This is the unique key for the query." + }, + "timeRange": { + "description": "This is the time range for the query.", + "allOf": [ + { + "$ref": "#/components/schemas/TimeRange" + } + ] + }, + "result": { + "description": "This is the result of the query, a list of unique groups with result of their aggregations.\n\nExample:\n\"result\": [\n { \"date\": \"2023-01-01\", \"assistantId\": \"123\", \"endedReason\": \"customer-ended-call\", \"sumDuration\": 120, \"avgCost\": 10.5 },\n { \"date\": \"2023-01-02\", \"assistantId\": \"123\", \"endedReason\": \"customer-did-not-give-microphone-permission\", \"sumDuration\": 0, \"avgCost\": 0 },\n // Additional results\n]", + "type": "array", + "items": { + "type": "object" + } + } + }, + "required": [ + "name", + "timeRange", + "result" + ] + }, "ClientMessageWorkflowNodeStarted": { "type": "object", "properties": { @@ -45493,6 +73197,11 @@ } ] }, + "assistantVersion": { + "type": "string", + "nullable": true, + "description": "This is the version label (e.g. `v3`) of the assistant the call was\nconfigured with. `null` for inline assistants, squad/workflow calls,\npre-resolution assistant-request messages, and orgs not on\nassistant versioning." + }, "type": { "type": "string", "description": "This is the type of the message. \"workflow.node.started\" is sent when the active node changes.", @@ -45538,6 +73247,88 @@ "node" ] }, + "ClientMessageAssistantStarted": { + "type": "object", + "properties": { + "phoneNumber": { + "description": "This is the phone number that the message is associated with.", + "oneOf": [ + { + "$ref": "#/components/schemas/CreateByoPhoneNumberDTO", + "title": "ByoPhoneNumber" + }, + { + "$ref": "#/components/schemas/CreateTwilioPhoneNumberDTO", + "title": "TwilioPhoneNumber" + }, + { + "$ref": "#/components/schemas/CreateVonagePhoneNumberDTO", + "title": "VonagePhoneNumber" + }, + { + "$ref": "#/components/schemas/CreateVapiPhoneNumberDTO", + "title": "VapiPhoneNumber" + }, + { + "$ref": "#/components/schemas/CreateTelnyxPhoneNumberDTO", + "title": "TelnyxPhoneNumber" + } + ] + }, + "assistantVersion": { + "type": "string", + "nullable": true, + "description": "This is the version label (e.g. `v3`) of the assistant the call was\nconfigured with. `null` for inline assistants, squad/workflow calls,\npre-resolution assistant-request messages, and orgs not on\nassistant versioning." + }, + "type": { + "type": "string", + "description": "This is the type of the message. \"assistant.started\" is sent when the assistant is started.", + "enum": [ + "assistant.started" + ] + }, + "timestamp": { + "type": "number", + "description": "This is the timestamp of the message." + }, + "call": { + "description": "This is the call that the message is associated with.", + "allOf": [ + { + "$ref": "#/components/schemas/Call" + } + ] + }, + "customer": { + "description": "This is the customer that the message is associated with.", + "allOf": [ + { + "$ref": "#/components/schemas/CreateCustomerDTO" + } + ] + }, + "assistant": { + "description": "This is the assistant that the message is associated with.", + "allOf": [ + { + "$ref": "#/components/schemas/CreateAssistantDTO" + } + ] + }, + "newAssistant": { + "description": "This is the assistant that was updated.", + "allOf": [ + { + "$ref": "#/components/schemas/CreateAssistantDTO" + } + ] + } + }, + "required": [ + "type", + "newAssistant" + ] + }, "ClientMessageConversationUpdate": { "type": "object", "properties": { @@ -45566,6 +73357,11 @@ } ] }, + "assistantVersion": { + "type": "string", + "nullable": true, + "description": "This is the version label (e.g. `v3`) of the assistant the call was\nconfigured with. `null` for inline assistants, squad/workflow calls,\npre-resolution assistant-request messages, and orgs not on\nassistant versioning." + }, "type": { "type": "string", "description": "This is the type of the message. \"conversation-update\" is sent when an update is committed to the conversation history.", @@ -45670,6 +73466,11 @@ } ] }, + "assistantVersion": { + "type": "string", + "nullable": true, + "description": "This is the version label (e.g. `v3`) of the assistant the call was\nconfigured with. `null` for inline assistants, squad/workflow calls,\npre-resolution assistant-request messages, and orgs not on\nassistant versioning." + }, "type": { "type": "string", "description": "This is the type of the message. \"hang\" is sent when the assistant is hanging due to a delay. The delay can be caused by many factors, such as:\n- the model is too slow to respond\n- the voice is too slow to respond\n- the tool call is still waiting for a response from your server\n- etc.", @@ -45738,6 +73539,11 @@ } ] }, + "assistantVersion": { + "type": "string", + "nullable": true, + "description": "This is the version label (e.g. `v3`) of the assistant the call was\nconfigured with. `null` for inline assistants, squad/workflow calls,\npre-resolution assistant-request messages, and orgs not on\nassistant versioning." + }, "type": { "type": "string", "description": "This is the type of the message. \"metadata\" is sent to forward metadata to the client.", @@ -45811,6 +73617,11 @@ } ] }, + "assistantVersion": { + "type": "string", + "nullable": true, + "description": "This is the version label (e.g. `v3`) of the assistant the call was\nconfigured with. `null` for inline assistants, squad/workflow calls,\npre-resolution assistant-request messages, and orgs not on\nassistant versioning." + }, "type": { "type": "string", "description": "This is the type of the message. \"model-output\" is sent as the model outputs tokens.", @@ -45818,6 +73629,10 @@ "model-output" ] }, + "turnId": { + "type": "string", + "description": "This is the unique identifier for the current LLM turn. All tokens from the same\nLLM response share the same turnId. Use this to group tokens and discard on interruption." + }, "timestamp": { "type": "number", "description": "This is the timestamp of the message." @@ -45884,6 +73699,11 @@ } ] }, + "assistantVersion": { + "type": "string", + "nullable": true, + "description": "This is the version label (e.g. `v3`) of the assistant the call was\nconfigured with. `null` for inline assistants, squad/workflow calls,\npre-resolution assistant-request messages, and orgs not on\nassistant versioning." + }, "type": { "type": "string", "description": "This is the type of the message. \"speech-update\" is sent whenever assistant or user start or stop speaking.", @@ -45974,6 +73794,11 @@ } ] }, + "assistantVersion": { + "type": "string", + "nullable": true, + "description": "This is the version label (e.g. `v3`) of the assistant the call was\nconfigured with. `null` for inline assistants, squad/workflow calls,\npre-resolution assistant-request messages, and orgs not on\nassistant versioning." + }, "type": { "type": "string", "description": "This is the type of the message. \"transcript\" is sent as transcriber outputs partial or final transcript.", @@ -46030,6 +73855,14 @@ "type": "string", "description": "This is the transcript content." }, + "assistantId": { + "type": "string", + "description": "The ID of the assistant that produced this transcript. Present on\nassistant-role events when an active assistant ID is available." + }, + "assistantName": { + "type": "string", + "description": "The name of the assistant that produced this transcript. Present on\nassistant-role events when an active assistant name is available." + }, "isFiltered": { "type": "boolean", "description": "Indicates if the transcript was filtered for security reasons." @@ -46081,6 +73914,11 @@ } ] }, + "assistantVersion": { + "type": "string", + "nullable": true, + "description": "This is the version label (e.g. `v3`) of the assistant the call was\nconfigured with. `null` for inline assistants, squad/workflow calls,\npre-resolution assistant-request messages, and orgs not on\nassistant versioning." + }, "type": { "type": "string", "description": "This is the type of the message. \"tool-calls\" is sent to call a tool.", @@ -46193,6 +74031,11 @@ } ] }, + "assistantVersion": { + "type": "string", + "nullable": true, + "description": "This is the version label (e.g. `v3`) of the assistant the call was\nconfigured with. `null` for inline assistants, squad/workflow calls,\npre-resolution assistant-request messages, and orgs not on\nassistant versioning." + }, "type": { "type": "string", "description": "This is the type of the message. \"tool-calls-result\" is sent to forward the result of a tool call to the client.", @@ -46266,6 +74109,11 @@ } ] }, + "assistantVersion": { + "type": "string", + "nullable": true, + "description": "This is the version label (e.g. `v3`) of the assistant the call was\nconfigured with. `null` for inline assistants, squad/workflow calls,\npre-resolution assistant-request messages, and orgs not on\nassistant versioning." + }, "type": { "type": "string", "description": "This is the type of the message. \"transfer-update\" is sent whenever a transfer happens.", @@ -46375,6 +74223,11 @@ } ] }, + "assistantVersion": { + "type": "string", + "nullable": true, + "description": "This is the version label (e.g. `v3`) of the assistant the call was\nconfigured with. `null` for inline assistants, squad/workflow calls,\npre-resolution assistant-request messages, and orgs not on\nassistant versioning." + }, "type": { "type": "string", "description": "This is the type of the message. \"user-interrupted\" is sent when the user interrupts the assistant.", @@ -46382,6 +74235,10 @@ "user-interrupted" ] }, + "turnId": { + "type": "string", + "description": "This is the turnId of the LLM response that was interrupted. Matches the turnId\non model-output messages so clients can discard the interrupted turn's tokens." + }, "timestamp": { "type": "number", "description": "This is the timestamp of the message." @@ -46443,11 +74300,279 @@ } ] }, + "assistantVersion": { + "type": "string", + "nullable": true, + "description": "This is the version label (e.g. `v3`) of the assistant the call was\nconfigured with. `null` for inline assistants, squad/workflow calls,\npre-resolution assistant-request messages, and orgs not on\nassistant versioning." + }, + "type": { + "type": "string", + "description": "This is the type of the message. \"language-change-detected\" is sent when the transcriber is automatically switched based on the detected language.", + "enum": [ + "language-change-detected" + ] + }, + "timestamp": { + "type": "number", + "description": "This is the timestamp of the message." + }, + "call": { + "description": "This is the call that the message is associated with.", + "allOf": [ + { + "$ref": "#/components/schemas/Call" + } + ] + }, + "customer": { + "description": "This is the customer that the message is associated with.", + "allOf": [ + { + "$ref": "#/components/schemas/CreateCustomerDTO" + } + ] + }, + "assistant": { + "description": "This is the assistant that the message is associated with.", + "allOf": [ + { + "$ref": "#/components/schemas/CreateAssistantDTO" + } + ] + }, + "language": { + "type": "string", + "description": "This is the language the transcriber is switched to." + } + }, + "required": [ + "type", + "language" + ] + }, + "ClientMessageVoiceInput": { + "type": "object", + "properties": { + "phoneNumber": { + "description": "This is the phone number that the message is associated with.", + "oneOf": [ + { + "$ref": "#/components/schemas/CreateByoPhoneNumberDTO", + "title": "ByoPhoneNumber" + }, + { + "$ref": "#/components/schemas/CreateTwilioPhoneNumberDTO", + "title": "TwilioPhoneNumber" + }, + { + "$ref": "#/components/schemas/CreateVonagePhoneNumberDTO", + "title": "VonagePhoneNumber" + }, + { + "$ref": "#/components/schemas/CreateVapiPhoneNumberDTO", + "title": "VapiPhoneNumber" + }, + { + "$ref": "#/components/schemas/CreateTelnyxPhoneNumberDTO", + "title": "TelnyxPhoneNumber" + } + ] + }, + "assistantVersion": { + "type": "string", + "nullable": true, + "description": "This is the version label (e.g. `v3`) of the assistant the call was\nconfigured with. `null` for inline assistants, squad/workflow calls,\npre-resolution assistant-request messages, and orgs not on\nassistant versioning." + }, + "type": { + "type": "string", + "description": "This is the type of the message. \"voice-input\" is sent when a generation is requested from voice provider.", + "enum": [ + "voice-input" + ] + }, + "timestamp": { + "type": "number", + "description": "This is the timestamp of the message." + }, + "call": { + "description": "This is the call that the message is associated with.", + "allOf": [ + { + "$ref": "#/components/schemas/Call" + } + ] + }, + "customer": { + "description": "This is the customer that the message is associated with.", + "allOf": [ + { + "$ref": "#/components/schemas/CreateCustomerDTO" + } + ] + }, + "assistant": { + "description": "This is the assistant that the message is associated with.", + "allOf": [ + { + "$ref": "#/components/schemas/CreateAssistantDTO" + } + ] + }, + "input": { + "type": "string", + "description": "This is the voice input content" + } + }, + "required": [ + "type", + "input" + ] + }, + "ClientMessageAssistantSpeech": { + "type": "object", + "properties": { + "phoneNumber": { + "description": "This is the phone number that the message is associated with.", + "oneOf": [ + { + "$ref": "#/components/schemas/CreateByoPhoneNumberDTO", + "title": "ByoPhoneNumber" + }, + { + "$ref": "#/components/schemas/CreateTwilioPhoneNumberDTO", + "title": "TwilioPhoneNumber" + }, + { + "$ref": "#/components/schemas/CreateVonagePhoneNumberDTO", + "title": "VonagePhoneNumber" + }, + { + "$ref": "#/components/schemas/CreateVapiPhoneNumberDTO", + "title": "VapiPhoneNumber" + }, + { + "$ref": "#/components/schemas/CreateTelnyxPhoneNumberDTO", + "title": "TelnyxPhoneNumber" + } + ] + }, + "assistantVersion": { + "type": "string", + "nullable": true, + "description": "This is the version label (e.g. `v3`) of the assistant the call was\nconfigured with. `null` for inline assistants, squad/workflow calls,\npre-resolution assistant-request messages, and orgs not on\nassistant versioning." + }, + "type": { + "type": "string", + "description": "This is the type of the message. \"assistant-speech\" is sent as assistant audio is being played.", + "enum": [ + "assistant.speechStarted" + ] + }, + "text": { + "type": "string", + "description": "The full assistant text for the current turn. This is the complete text,\nnot an incremental delta — consumers should use `timing` metadata (e.g.\n`wordsSpoken`) to determine which portion has been spoken so far." + }, + "turn": { + "type": "number", + "description": "This is the turn number of the assistant speech event (0-indexed)." + }, + "source": { + "type": "string", + "description": "Indicates how the text was sourced.", + "enum": [ + "model", + "force-say", + "custom-voice" + ] + }, + "timing": { + "description": "Optional timing metadata. Shape depends on `timing.type`:\n\n- `word-alignment` (ElevenLabs): per-character timing at playback\n cadence. words[] includes space entries. Best consumed by tracking\n a running character count: join timing.words, add to a char cursor,\n and highlight text up to that position. No interpolation needed.\n\n- `word-progress` (Minimax with voice.subtitleType: 'word'): cursor-\n based word count per TTS segment. Use wordsSpoken as the anchor,\n interpolate forward using segmentDurationMs or timing.words until\n the next event arrives.\n\nWhen absent, the event is a text-only fallback for providers without\nword-level timing (e.g. Cartesia, Deepgram, Azure). Text emits once\nper TTS chunk when audio is playing. Optionally interpolate a word\ncursor at ~3.5 words/sec between events for approximate tracking.", + "oneOf": [ + { + "$ref": "#/components/schemas/AssistantSpeechWordAlignmentTiming", + "title": "WordAlignmentTiming" + }, + { + "$ref": "#/components/schemas/AssistantSpeechWordProgressTiming", + "title": "WordProgressTiming" + } + ], + "discriminator": { + "propertyName": "type" + } + }, + "timestamp": { + "type": "number", + "description": "This is the timestamp of the message." + }, + "call": { + "description": "This is the call that the message is associated with.", + "allOf": [ + { + "$ref": "#/components/schemas/Call" + } + ] + }, + "customer": { + "description": "This is the customer that the message is associated with.", + "allOf": [ + { + "$ref": "#/components/schemas/CreateCustomerDTO" + } + ] + }, + "assistant": { + "description": "This is the assistant that the message is associated with.", + "allOf": [ + { + "$ref": "#/components/schemas/CreateAssistantDTO" + } + ] + } + }, + "required": [ + "type", + "text" + ] + }, + "ClientMessageChatCreated": { + "type": "object", + "properties": { + "phoneNumber": { + "description": "This is the phone number that the message is associated with.", + "oneOf": [ + { + "$ref": "#/components/schemas/CreateByoPhoneNumberDTO", + "title": "ByoPhoneNumber" + }, + { + "$ref": "#/components/schemas/CreateTwilioPhoneNumberDTO", + "title": "TwilioPhoneNumber" + }, + { + "$ref": "#/components/schemas/CreateVonagePhoneNumberDTO", + "title": "VonagePhoneNumber" + }, + { + "$ref": "#/components/schemas/CreateVapiPhoneNumberDTO", + "title": "VapiPhoneNumber" + }, + { + "$ref": "#/components/schemas/CreateTelnyxPhoneNumberDTO", + "title": "TelnyxPhoneNumber" + } + ] + }, + "assistantVersion": { + "type": "string", + "nullable": true, + "description": "This is the version label (e.g. `v3`) of the assistant the call was\nconfigured with. `null` for inline assistants, squad/workflow calls,\npre-resolution assistant-request messages, and orgs not on\nassistant versioning." + }, "type": { "type": "string", - "description": "This is the type of the message. \"language-change-detected\" is sent when the transcriber is automatically switched based on the detected language.", + "description": "This is the type of the message. \"chat.created\" is sent when a new chat is created.", "enum": [ - "language-change-detected" + "chat.created" ] }, "timestamp": { @@ -46478,17 +74603,21 @@ } ] }, - "language": { - "type": "string", - "description": "This is the language the transcriber is switched to." + "chat": { + "description": "This is the chat that was created.", + "allOf": [ + { + "$ref": "#/components/schemas/Chat" + } + ] } }, "required": [ "type", - "language" + "chat" ] }, - "ClientMessageVoiceInput": { + "ClientMessageChatDeleted": { "type": "object", "properties": { "phoneNumber": { @@ -46516,11 +74645,16 @@ } ] }, + "assistantVersion": { + "type": "string", + "nullable": true, + "description": "This is the version label (e.g. `v3`) of the assistant the call was\nconfigured with. `null` for inline assistants, squad/workflow calls,\npre-resolution assistant-request messages, and orgs not on\nassistant versioning." + }, "type": { "type": "string", - "description": "This is the type of the message. \"voice-input\" is sent when a generation is requested from voice provider.", + "description": "This is the type of the message. \"chat.deleted\" is sent when a chat is deleted.", "enum": [ - "voice-input" + "chat.deleted" ] }, "timestamp": { @@ -46551,17 +74685,21 @@ } ] }, - "input": { - "type": "string", - "description": "This is the voice input content" + "chat": { + "description": "This is the chat that was deleted.", + "allOf": [ + { + "$ref": "#/components/schemas/Chat" + } + ] } }, "required": [ "type", - "input" + "chat" ] }, - "ClientMessageChatCreated": { + "ClientMessageSessionCreated": { "type": "object", "properties": { "phoneNumber": { @@ -46589,11 +74727,16 @@ } ] }, + "assistantVersion": { + "type": "string", + "nullable": true, + "description": "This is the version label (e.g. `v3`) of the assistant the call was\nconfigured with. `null` for inline assistants, squad/workflow calls,\npre-resolution assistant-request messages, and orgs not on\nassistant versioning." + }, "type": { "type": "string", - "description": "This is the type of the message. \"chat.created\" is sent when a new chat is created.", + "description": "This is the type of the message. \"session.created\" is sent when a new session is created.", "enum": [ - "chat.created" + "session.created" ] }, "timestamp": { @@ -46624,21 +74767,21 @@ } ] }, - "chat": { - "description": "This is the chat that was created.", + "session": { + "description": "This is the session that was created.", "allOf": [ { - "$ref": "#/components/schemas/Chat" + "$ref": "#/components/schemas/Session" } ] } }, "required": [ "type", - "chat" + "session" ] }, - "ClientMessageChatDeleted": { + "ClientMessageSessionUpdated": { "type": "object", "properties": { "phoneNumber": { @@ -46666,11 +74809,16 @@ } ] }, + "assistantVersion": { + "type": "string", + "nullable": true, + "description": "This is the version label (e.g. `v3`) of the assistant the call was\nconfigured with. `null` for inline assistants, squad/workflow calls,\npre-resolution assistant-request messages, and orgs not on\nassistant versioning." + }, "type": { "type": "string", - "description": "This is the type of the message. \"chat.deleted\" is sent when a chat is deleted.", + "description": "This is the type of the message. \"session.updated\" is sent when a session is updated.", "enum": [ - "chat.deleted" + "session.updated" ] }, "timestamp": { @@ -46701,21 +74849,21 @@ } ] }, - "chat": { - "description": "This is the chat that was deleted.", + "session": { + "description": "This is the session that was updated.", "allOf": [ { - "$ref": "#/components/schemas/Chat" + "$ref": "#/components/schemas/Session" } ] } }, "required": [ "type", - "chat" + "session" ] }, - "ClientMessageSessionCreated": { + "ClientMessageSessionDeleted": { "type": "object", "properties": { "phoneNumber": { @@ -46743,11 +74891,16 @@ } ] }, + "assistantVersion": { + "type": "string", + "nullable": true, + "description": "This is the version label (e.g. `v3`) of the assistant the call was\nconfigured with. `null` for inline assistants, squad/workflow calls,\npre-resolution assistant-request messages, and orgs not on\nassistant versioning." + }, "type": { "type": "string", - "description": "This is the type of the message. \"session.created\" is sent when a new session is created.", + "description": "This is the type of the message. \"session.deleted\" is sent when a session is deleted.", "enum": [ - "session.created" + "session.deleted" ] }, "timestamp": { @@ -46779,7 +74932,7 @@ ] }, "session": { - "description": "This is the session that was created.", + "description": "This is the session that was deleted.", "allOf": [ { "$ref": "#/components/schemas/Session" @@ -46792,7 +74945,7 @@ "session" ] }, - "ClientMessageSessionUpdated": { + "ClientMessageCallDeleted": { "type": "object", "properties": { "phoneNumber": { @@ -46820,11 +74973,16 @@ } ] }, + "assistantVersion": { + "type": "string", + "nullable": true, + "description": "This is the version label (e.g. `v3`) of the assistant the call was\nconfigured with. `null` for inline assistants, squad/workflow calls,\npre-resolution assistant-request messages, and orgs not on\nassistant versioning." + }, "type": { "type": "string", - "description": "This is the type of the message. \"session.updated\" is sent when a session is updated.", + "description": "This is the type of the message. \"call.deleted\" is sent when a call is deleted.", "enum": [ - "session.updated" + "call.deleted" ] }, "timestamp": { @@ -46854,22 +75012,13 @@ "$ref": "#/components/schemas/CreateAssistantDTO" } ] - }, - "session": { - "description": "This is the session that was updated.", - "allOf": [ - { - "$ref": "#/components/schemas/Session" - } - ] } }, "required": [ - "type", - "session" + "type" ] }, - "ClientMessageSessionDeleted": { + "ClientMessageCallDeleteFailed": { "type": "object", "properties": { "phoneNumber": { @@ -46897,11 +75046,16 @@ } ] }, + "assistantVersion": { + "type": "string", + "nullable": true, + "description": "This is the version label (e.g. `v3`) of the assistant the call was\nconfigured with. `null` for inline assistants, squad/workflow calls,\npre-resolution assistant-request messages, and orgs not on\nassistant versioning." + }, "type": { "type": "string", - "description": "This is the type of the message. \"session.deleted\" is sent when a session is deleted.", + "description": "This is the type of the message. \"call.deleted\" is sent when a call is deleted.", "enum": [ - "session.deleted" + "call.delete.failed" ] }, "timestamp": { @@ -46931,19 +75085,10 @@ "$ref": "#/components/schemas/CreateAssistantDTO" } ] - }, - "session": { - "description": "This is the session that was deleted.", - "allOf": [ - { - "$ref": "#/components/schemas/Session" - } - ] } }, "required": [ - "type", - "session" + "type" ] }, "ClientMessage": { @@ -46956,6 +75101,10 @@ "$ref": "#/components/schemas/ClientMessageWorkflowNodeStarted", "title": "WorkflowNodeStarted" }, + { + "$ref": "#/components/schemas/ClientMessageAssistantStarted", + "title": "AssistantStarted" + }, { "$ref": "#/components/schemas/ClientMessageConversationUpdate", "title": "ConversationUpdate" @@ -47004,6 +75153,10 @@ "$ref": "#/components/schemas/ClientMessageVoiceInput", "title": "VoiceInput" }, + { + "$ref": "#/components/schemas/ClientMessageAssistantSpeech", + "title": "AssistantSpeech" + }, { "$ref": "#/components/schemas/ClientMessageChatCreated", "title": "ChatCreated" @@ -47023,6 +75176,14 @@ { "$ref": "#/components/schemas/ClientMessageSessionDeleted", "title": "SessionDeleted" + }, + { + "$ref": "#/components/schemas/ClientMessageCallDeleted", + "title": "CallDeleted" + }, + { + "$ref": "#/components/schemas/ClientMessageCallDeleteFailed", + "title": "CallDeleteFailed" } ] } @@ -47059,6 +75220,11 @@ } ] }, + "assistantVersion": { + "type": "string", + "nullable": true, + "description": "This is the version label (e.g. `v3`) of the assistant the call was\nconfigured with. `null` for inline assistants, squad/workflow calls,\npre-resolution assistant-request messages, and orgs not on\nassistant versioning." + }, "type": { "type": "string", "description": "This is the type of the message. \"assistant-request\" is sent to fetch assistant configuration for an incoming call.", @@ -47143,6 +75309,11 @@ } ] }, + "assistantVersion": { + "type": "string", + "nullable": true, + "description": "This is the version label (e.g. `v3`) of the assistant the call was\nconfigured with. `null` for inline assistants, squad/workflow calls,\npre-resolution assistant-request messages, and orgs not on\nassistant versioning." + }, "type": { "type": "string", "description": "This is the type of the message. \"conversation-update\" is sent when an update is committed to the conversation history.", @@ -47263,6 +75434,11 @@ } ] }, + "assistantVersion": { + "type": "string", + "nullable": true, + "description": "This is the version label (e.g. `v3`) of the assistant the call was\nconfigured with. `null` for inline assistants, squad/workflow calls,\npre-resolution assistant-request messages, and orgs not on\nassistant versioning." + }, "type": { "type": "string", "description": "This is the type of the message. \"end-of-call-report\" is sent when the call ends and post-processing is complete.", @@ -47292,12 +75468,15 @@ "call.start.error-vapi-number-outbound-daily-limit", "call.start.error-get-transport", "call.start.error-subscription-wallet-does-not-exist", + "call.start.error-fraud-check-failed", "call.start.error-subscription-frozen", "call.start.error-subscription-insufficient-credits", "call.start.error-subscription-upgrade-failed", "call.start.error-subscription-concurrency-limit-reached", + "call.start.error-enterprise-feature-not-available-recording-consent", + "call.start.assistant-version-error-validation", "assistant-not-valid", - "database-error", + "call.start.error-vapifault-database-error", "assistant-not-found", "pipeline-error-openai-voice-failed", "pipeline-error-cartesia-voice-failed", @@ -47308,11 +75487,16 @@ "pipeline-error-azure-voice-failed", "pipeline-error-rime-ai-voice-failed", "pipeline-error-smallest-ai-voice-failed", + "pipeline-error-vapi-voice-failed", "pipeline-error-neuphonic-voice-failed", "pipeline-error-hume-voice-failed", "pipeline-error-sesame-voice-failed", "pipeline-error-inworld-voice-failed", "pipeline-error-minimax-voice-failed", + "pipeline-error-wellsaid-voice-failed", + "pipeline-error-xai-voice-failed", + "pipeline-error-microsoft-voice-failed", + "pipeline-error-microsoft-voice-request-canceled", "pipeline-error-tavus-video-failed", "call.in-progress.error-vapifault-openai-voice-failed", "call.in-progress.error-vapifault-cartesia-voice-failed", @@ -47323,11 +75507,15 @@ "call.in-progress.error-vapifault-azure-voice-failed", "call.in-progress.error-vapifault-rime-ai-voice-failed", "call.in-progress.error-vapifault-smallest-ai-voice-failed", + "call.in-progress.error-vapifault-vapi-voice-failed", "call.in-progress.error-vapifault-neuphonic-voice-failed", "call.in-progress.error-vapifault-hume-voice-failed", "call.in-progress.error-vapifault-sesame-voice-failed", "call.in-progress.error-vapifault-inworld-voice-failed", "call.in-progress.error-vapifault-minimax-voice-failed", + "call.in-progress.error-vapifault-wellsaid-voice-failed", + "call.in-progress.error-vapifault-xai-voice-failed", + "call.in-progress.error-vapifault-microsoft-voice-failed", "call.in-progress.error-vapifault-tavus-video-failed", "pipeline-error-vapi-llm-failed", "pipeline-error-vapi-400-bad-request-validation-failed", @@ -47336,6 +75524,7 @@ "pipeline-error-vapi-429-exceeded-quota", "pipeline-error-vapi-500-server-error", "pipeline-error-vapi-503-server-overloaded-error", + "call.in-progress.error-providerfault-vapi-llm-failed", "call.in-progress.error-vapifault-vapi-llm-failed", "call.in-progress.error-vapifault-vapi-400-bad-request-validation-failed", "call.in-progress.error-vapifault-vapi-401-unauthorized", @@ -47343,7 +75532,12 @@ "call.in-progress.error-vapifault-vapi-429-exceeded-quota", "call.in-progress.error-providerfault-vapi-500-server-error", "call.in-progress.error-providerfault-vapi-503-server-overloaded-error", + "pipeline-error-vapi-transcriber-failed", + "call.in-progress.error-vapifault-vapi-transcriber-failed", + "call.in-progress.error-providerfault-vapi-transcriber-failed", + "call.in-progress.error-providerfault-vapi-voice-failed", "pipeline-error-deepgram-transcriber-failed", + "pipeline-error-deepgram-transcriber-api-key-missing", "call.in-progress.error-vapifault-deepgram-transcriber-failed", "pipeline-error-gladia-transcriber-failed", "call.in-progress.error-vapifault-gladia-transcriber-failed", @@ -47365,6 +75559,34 @@ "call.in-progress.error-vapifault-talkscriber-transcriber-failed", "pipeline-error-azure-speech-transcriber-failed", "call.in-progress.error-vapifault-azure-speech-transcriber-failed", + "pipeline-error-eleven-labs-transcriber-failed", + "call.in-progress.error-vapifault-eleven-labs-transcriber-failed", + "pipeline-error-google-transcriber-failed", + "call.in-progress.error-vapifault-google-transcriber-failed", + "pipeline-error-openai-transcriber-failed", + "call.in-progress.error-vapifault-openai-transcriber-failed", + "pipeline-error-soniox-transcriber-auth-failed", + "pipeline-error-soniox-transcriber-rate-limited", + "pipeline-error-soniox-transcriber-invalid-config", + "pipeline-error-soniox-transcriber-server-error", + "pipeline-error-soniox-transcriber-failed", + "call.in-progress.error-vapifault-soniox-transcriber-auth-failed", + "call.in-progress.error-vapifault-soniox-transcriber-rate-limited", + "call.in-progress.error-vapifault-soniox-transcriber-invalid-config", + "call.in-progress.error-vapifault-soniox-transcriber-server-error", + "call.in-progress.error-vapifault-soniox-transcriber-failed", + "pipeline-error-xai-transcriber-auth-failed", + "pipeline-error-xai-transcriber-rate-limited", + "pipeline-error-xai-transcriber-invalid-config", + "pipeline-error-xai-transcriber-server-error", + "pipeline-error-xai-transcriber-failed", + "call.in-progress.error-vapifault-xai-transcriber-auth-failed", + "call.in-progress.error-vapifault-xai-transcriber-rate-limited", + "call.in-progress.error-vapifault-xai-transcriber-invalid-config", + "call.in-progress.error-vapifault-xai-transcriber-server-error", + "call.in-progress.error-vapifault-xai-transcriber-failed", + "pipeline-error-cartesia-transcriber-failed", + "call.in-progress.error-vapifault-cartesia-transcriber-failed", "call.in-progress.error-pipeline-no-available-llm-model", "worker-shutdown", "vonage-disconnected", @@ -47379,15 +75601,21 @@ "call.in-progress.error-vapifault-worker-died", "call.in-progress.twilio-completed-call", "call.in-progress.sip-completed-call", - "call.in-progress.error-vapifault-openai-llm-failed", - "call.in-progress.error-vapifault-azure-openai-llm-failed", - "call.in-progress.error-vapifault-groq-llm-failed", - "call.in-progress.error-vapifault-google-llm-failed", - "call.in-progress.error-vapifault-xai-llm-failed", - "call.in-progress.error-vapifault-mistral-llm-failed", - "call.in-progress.error-vapifault-inflection-ai-llm-failed", - "call.in-progress.error-vapifault-cerebras-llm-failed", - "call.in-progress.error-vapifault-deep-seek-llm-failed", + "call.in-progress.error-sip-inbound-call-failed-to-connect", + "call.in-progress.error-providerfault-outbound-sip-503-service-unavailable", + "call.in-progress.error-sip-outbound-call-failed-to-connect", + "call.ringing.error-sip-inbound-call-failed-to-connect", + "call.in-progress.error-providerfault-openai-llm-failed", + "call.in-progress.error-providerfault-azure-openai-llm-failed", + "call.in-progress.error-providerfault-groq-llm-failed", + "call.in-progress.error-providerfault-google-llm-failed", + "call.in-progress.error-providerfault-xai-llm-failed", + "call.in-progress.error-providerfault-mistral-llm-failed", + "call.in-progress.error-providerfault-minimax-llm-failed", + "call.in-progress.error-providerfault-inflection-ai-llm-failed", + "call.in-progress.error-providerfault-cerebras-llm-failed", + "call.in-progress.error-providerfault-deep-seek-llm-failed", + "call.in-progress.error-providerfault-baseten-llm-failed", "call.in-progress.error-vapifault-chat-pipeline-failed-to-start", "pipeline-error-openai-400-bad-request-validation-failed", "pipeline-error-openai-401-unauthorized", @@ -47447,6 +75675,19 @@ "call.in-progress.error-vapifault-xai-429-exceeded-quota", "call.in-progress.error-providerfault-xai-500-server-error", "call.in-progress.error-providerfault-xai-503-server-overloaded-error", + "pipeline-error-baseten-400-bad-request-validation-failed", + "pipeline-error-baseten-401-unauthorized", + "pipeline-error-baseten-403-model-access-denied", + "pipeline-error-baseten-429-exceeded-quota", + "pipeline-error-baseten-500-server-error", + "pipeline-error-baseten-503-server-overloaded-error", + "pipeline-error-baseten-llm-failed", + "call.in-progress.error-vapifault-baseten-400-bad-request-validation-failed", + "call.in-progress.error-vapifault-baseten-401-unauthorized", + "call.in-progress.error-vapifault-baseten-403-model-access-denied", + "call.in-progress.error-vapifault-baseten-429-exceeded-quota", + "call.in-progress.error-providerfault-baseten-500-server-error", + "call.in-progress.error-providerfault-baseten-503-server-overloaded-error", "pipeline-error-mistral-400-bad-request-validation-failed", "pipeline-error-mistral-401-unauthorized", "pipeline-error-mistral-403-model-access-denied", @@ -47460,6 +75701,19 @@ "call.in-progress.error-vapifault-mistral-429-exceeded-quota", "call.in-progress.error-providerfault-mistral-500-server-error", "call.in-progress.error-providerfault-mistral-503-server-overloaded-error", + "pipeline-error-minimax-400-bad-request-validation-failed", + "pipeline-error-minimax-401-unauthorized", + "pipeline-error-minimax-403-model-access-denied", + "pipeline-error-minimax-429-exceeded-quota", + "pipeline-error-minimax-500-server-error", + "pipeline-error-minimax-503-server-overloaded-error", + "pipeline-error-minimax-llm-failed", + "call.in-progress.error-vapifault-minimax-400-bad-request-validation-failed", + "call.in-progress.error-vapifault-minimax-401-unauthorized", + "call.in-progress.error-vapifault-minimax-403-model-access-denied", + "call.in-progress.error-vapifault-minimax-429-exceeded-quota", + "call.in-progress.error-providerfault-minimax-500-server-error", + "call.in-progress.error-providerfault-minimax-503-server-overloaded-error", "pipeline-error-inflection-ai-400-bad-request-validation-failed", "pipeline-error-inflection-ai-401-unauthorized", "pipeline-error-inflection-ai-403-model-access-denied", @@ -47519,7 +75773,7 @@ "pipeline-error-anthropic-500-server-error", "pipeline-error-anthropic-503-server-overloaded-error", "pipeline-error-anthropic-llm-failed", - "call.in-progress.error-vapifault-anthropic-llm-failed", + "call.in-progress.error-providerfault-anthropic-llm-failed", "call.in-progress.error-vapifault-anthropic-400-bad-request-validation-failed", "call.in-progress.error-vapifault-anthropic-401-unauthorized", "call.in-progress.error-vapifault-anthropic-403-model-access-denied", @@ -47533,7 +75787,7 @@ "pipeline-error-anthropic-bedrock-500-server-error", "pipeline-error-anthropic-bedrock-503-server-overloaded-error", "pipeline-error-anthropic-bedrock-llm-failed", - "call.in-progress.error-vapifault-anthropic-bedrock-llm-failed", + "call.in-progress.error-providerfault-anthropic-bedrock-llm-failed", "call.in-progress.error-vapifault-anthropic-bedrock-400-bad-request-validation-failed", "call.in-progress.error-vapifault-anthropic-bedrock-401-unauthorized", "call.in-progress.error-vapifault-anthropic-bedrock-403-model-access-denied", @@ -47547,7 +75801,7 @@ "pipeline-error-anthropic-vertex-500-server-error", "pipeline-error-anthropic-vertex-503-server-overloaded-error", "pipeline-error-anthropic-vertex-llm-failed", - "call.in-progress.error-vapifault-anthropic-vertex-llm-failed", + "call.in-progress.error-providerfault-anthropic-vertex-llm-failed", "call.in-progress.error-vapifault-anthropic-vertex-400-bad-request-validation-failed", "call.in-progress.error-vapifault-anthropic-vertex-401-unauthorized", "call.in-progress.error-vapifault-anthropic-vertex-403-model-access-denied", @@ -47561,7 +75815,7 @@ "pipeline-error-together-ai-500-server-error", "pipeline-error-together-ai-503-server-overloaded-error", "pipeline-error-together-ai-llm-failed", - "call.in-progress.error-vapifault-together-ai-llm-failed", + "call.in-progress.error-providerfault-together-ai-llm-failed", "call.in-progress.error-vapifault-together-ai-400-bad-request-validation-failed", "call.in-progress.error-vapifault-together-ai-401-unauthorized", "call.in-progress.error-vapifault-together-ai-403-model-access-denied", @@ -47575,7 +75829,7 @@ "pipeline-error-anyscale-500-server-error", "pipeline-error-anyscale-503-server-overloaded-error", "pipeline-error-anyscale-llm-failed", - "call.in-progress.error-vapifault-anyscale-llm-failed", + "call.in-progress.error-providerfault-anyscale-llm-failed", "call.in-progress.error-vapifault-anyscale-400-bad-request-validation-failed", "call.in-progress.error-vapifault-anyscale-401-unauthorized", "call.in-progress.error-vapifault-anyscale-403-model-access-denied", @@ -47589,7 +75843,7 @@ "pipeline-error-openrouter-500-server-error", "pipeline-error-openrouter-503-server-overloaded-error", "pipeline-error-openrouter-llm-failed", - "call.in-progress.error-vapifault-openrouter-llm-failed", + "call.in-progress.error-providerfault-openrouter-llm-failed", "call.in-progress.error-vapifault-openrouter-400-bad-request-validation-failed", "call.in-progress.error-vapifault-openrouter-401-unauthorized", "call.in-progress.error-vapifault-openrouter-403-model-access-denied", @@ -47603,7 +75857,7 @@ "pipeline-error-perplexity-ai-500-server-error", "pipeline-error-perplexity-ai-503-server-overloaded-error", "pipeline-error-perplexity-ai-llm-failed", - "call.in-progress.error-vapifault-perplexity-ai-llm-failed", + "call.in-progress.error-providerfault-perplexity-ai-llm-failed", "call.in-progress.error-vapifault-perplexity-ai-400-bad-request-validation-failed", "call.in-progress.error-vapifault-perplexity-ai-401-unauthorized", "call.in-progress.error-vapifault-perplexity-ai-403-model-access-denied", @@ -47617,7 +75871,7 @@ "pipeline-error-deepinfra-500-server-error", "pipeline-error-deepinfra-503-server-overloaded-error", "pipeline-error-deepinfra-llm-failed", - "call.in-progress.error-vapifault-deepinfra-llm-failed", + "call.in-progress.error-providerfault-deepinfra-llm-failed", "call.in-progress.error-vapifault-deepinfra-400-bad-request-validation-failed", "call.in-progress.error-vapifault-deepinfra-401-unauthorized", "call.in-progress.error-vapifault-deepinfra-403-model-access-denied", @@ -47631,7 +75885,7 @@ "pipeline-error-runpod-500-server-error", "pipeline-error-runpod-503-server-overloaded-error", "pipeline-error-runpod-llm-failed", - "call.in-progress.error-vapifault-runpod-llm-failed", + "call.in-progress.error-providerfault-runpod-llm-failed", "call.in-progress.error-vapifault-runpod-400-bad-request-validation-failed", "call.in-progress.error-vapifault-runpod-401-unauthorized", "call.in-progress.error-vapifault-runpod-403-model-access-denied", @@ -47645,13 +75899,14 @@ "pipeline-error-custom-llm-500-server-error", "pipeline-error-custom-llm-503-server-overloaded-error", "pipeline-error-custom-llm-llm-failed", - "call.in-progress.error-vapifault-custom-llm-llm-failed", + "call.in-progress.error-providerfault-custom-llm-llm-failed", "call.in-progress.error-vapifault-custom-llm-400-bad-request-validation-failed", "call.in-progress.error-vapifault-custom-llm-401-unauthorized", "call.in-progress.error-vapifault-custom-llm-403-model-access-denied", "call.in-progress.error-vapifault-custom-llm-429-exceeded-quota", "call.in-progress.error-providerfault-custom-llm-500-server-error", "call.in-progress.error-providerfault-custom-llm-503-server-overloaded-error", + "call.in-progress.error-pipeline-ws-model-connection-failed", "pipeline-error-custom-voice-failed", "pipeline-error-cartesia-socket-hang-up", "pipeline-error-cartesia-requested-payment", @@ -47707,6 +75962,7 @@ "call.in-progress.error-vapifault-eleven-labs-voice-not-allowed-for-free-users", "call.in-progress.error-vapifault-eleven-labs-max-character-limit-exceeded", "call.in-progress.error-vapifault-eleven-labs-blocked-voice-potentially-against-terms-of-service-and-awaiting-verification", + "call.in-progress.error-providerfault-eleven-labs-system-busy-and-requested-upgrade", "call.in-progress.error-providerfault-eleven-labs-500-server-error", "call.in-progress.error-providerfault-eleven-labs-503-server-error", "pipeline-error-playht-request-timed-out", @@ -47756,12 +76012,32 @@ "call.in-progress.error-vapifault-google-transcriber-failed", "pipeline-error-openai-transcriber-failed", "call.in-progress.error-vapifault-openai-transcriber-failed", + "pipeline-error-soniox-transcriber-auth-failed", + "pipeline-error-soniox-transcriber-rate-limited", + "pipeline-error-soniox-transcriber-invalid-config", + "pipeline-error-soniox-transcriber-server-error", + "pipeline-error-soniox-transcriber-failed", + "call.in-progress.error-vapifault-soniox-transcriber-auth-failed", + "call.in-progress.error-vapifault-soniox-transcriber-rate-limited", + "call.in-progress.error-vapifault-soniox-transcriber-invalid-config", + "call.in-progress.error-vapifault-soniox-transcriber-server-error", + "call.in-progress.error-vapifault-soniox-transcriber-failed", + "pipeline-error-xai-transcriber-auth-failed", + "pipeline-error-xai-transcriber-rate-limited", + "pipeline-error-xai-transcriber-invalid-config", + "pipeline-error-xai-transcriber-server-error", + "pipeline-error-xai-transcriber-failed", + "call.in-progress.error-vapifault-xai-transcriber-auth-failed", + "call.in-progress.error-vapifault-xai-transcriber-rate-limited", + "call.in-progress.error-vapifault-xai-transcriber-invalid-config", + "call.in-progress.error-vapifault-xai-transcriber-server-error", + "call.in-progress.error-vapifault-xai-transcriber-failed", + "pipeline-error-cartesia-transcriber-failed", + "call.in-progress.error-vapifault-cartesia-transcriber-failed", "call.in-progress.error-warm-transfer-max-duration", "call.in-progress.error-warm-transfer-assistant-cancelled", "call.in-progress.error-warm-transfer-silence-timeout", "call.in-progress.error-warm-transfer-microphone-timeout", - "call.in-progress.error-warm-transfer-hang-timeout", - "call.in-progress.error-warm-transfer-idle-timeout", "assistant-ended-call", "assistant-said-end-call-phrase", "assistant-ended-call-with-hangup-task", @@ -47772,17 +76048,21 @@ "call.in-progress.error-transfer-failed", "customer-busy", "customer-ended-call", + "customer-ended-call-before-warm-transfer", "customer-ended-call-after-warm-transfer-attempt", + "customer-ended-call-during-transfer", "customer-did-not-answer", "customer-did-not-give-microphone-permission", "exceeded-max-duration", "manually-canceled", "phone-call-provider-closed-websocket", "call.forwarding.operator-busy", + "call.forwarding.no-answer", "silence-timed-out", "call.in-progress.error-sip-inbound-call-failed-to-connect", "call.in-progress.error-providerfault-outbound-sip-403-forbidden", "call.in-progress.error-providerfault-outbound-sip-407-proxy-authentication-required", + "call.in-progress.error-providerfault-outbound-sip-408-request-timeout", "call.in-progress.error-providerfault-outbound-sip-503-service-unavailable", "call.in-progress.error-providerfault-outbound-sip-480-temporarily-unavailable", "call.in-progress.error-sip-outbound-call-failed-to-connect", @@ -47795,7 +76075,8 @@ "twilio-failed-to-connect-call", "twilio-reported-customer-misdialed", "vonage-rejected", - "voicemail" + "voicemail", + "call-deleted" ] }, "cost": { @@ -47842,6 +76123,19 @@ ] } }, + "destination": { + "description": "This is the destination the call was transferred to, if the call was forwarded.\nThis can also be found at `call.destination` on GET /call/:id.", + "oneOf": [ + { + "$ref": "#/components/schemas/TransferDestinationNumber", + "title": "NumberTransferDestination" + }, + { + "$ref": "#/components/schemas/TransferDestinationSip", + "title": "SipTransferDestination" + } + ] + }, "timestamp": { "type": "number", "description": "This is the timestamp of the message." @@ -47903,6 +76197,14 @@ "format": "date-time", "type": "string", "description": "This is the ISO 8601 date-time string of when the call ended. This can also be found at `call.endedAt` on GET /call/:id." + }, + "compliance": { + "description": "This is the compliance result of the call. This can also be found at `call.compliance` on GET /call/:id.", + "allOf": [ + { + "$ref": "#/components/schemas/Compliance" + } + ] } }, "required": [ @@ -47912,6 +76214,100 @@ "analysis" ] }, + "ServerMessageHandoffDestinationRequest": { + "type": "object", + "properties": { + "phoneNumber": { + "description": "This is the phone number that the message is associated with.", + "oneOf": [ + { + "$ref": "#/components/schemas/CreateByoPhoneNumberDTO", + "title": "ByoPhoneNumber" + }, + { + "$ref": "#/components/schemas/CreateTwilioPhoneNumberDTO", + "title": "TwilioPhoneNumber" + }, + { + "$ref": "#/components/schemas/CreateVonagePhoneNumberDTO", + "title": "VonagePhoneNumber" + }, + { + "$ref": "#/components/schemas/CreateVapiPhoneNumberDTO", + "title": "VapiPhoneNumber" + }, + { + "$ref": "#/components/schemas/CreateTelnyxPhoneNumberDTO", + "title": "TelnyxPhoneNumber" + } + ] + }, + "assistantVersion": { + "type": "string", + "nullable": true, + "description": "This is the version label (e.g. `v3`) of the assistant the call was\nconfigured with. `null` for inline assistants, squad/workflow calls,\npre-resolution assistant-request messages, and orgs not on\nassistant versioning." + }, + "type": { + "type": "string", + "description": "This is the type of the message. \"handoff-destination-request\" is sent when the model is requesting handoff but destination is unknown.", + "enum": [ + "handoff-destination-request" + ] + }, + "timestamp": { + "type": "number", + "description": "This is the timestamp of the message." + }, + "artifact": { + "description": "This is a live version of the `call.artifact`.\n\nThis matches what is stored on `call.artifact` after the call.", + "allOf": [ + { + "$ref": "#/components/schemas/Artifact" + } + ] + }, + "assistant": { + "description": "This is the assistant that the message is associated with.", + "allOf": [ + { + "$ref": "#/components/schemas/CreateAssistantDTO" + } + ] + }, + "customer": { + "description": "This is the customer that the message is associated with.", + "allOf": [ + { + "$ref": "#/components/schemas/CreateCustomerDTO" + } + ] + }, + "call": { + "description": "This is the call that the message is associated with.", + "allOf": [ + { + "$ref": "#/components/schemas/Call" + } + ] + }, + "chat": { + "description": "This is the chat object.", + "allOf": [ + { + "$ref": "#/components/schemas/Chat" + } + ] + }, + "parameters": { + "type": "object", + "description": "This is the parameters of the handoff destination request." + } + }, + "required": [ + "type", + "parameters" + ] + }, "ServerMessageHang": { "type": "object", "properties": { @@ -47940,6 +76336,11 @@ } ] }, + "assistantVersion": { + "type": "string", + "nullable": true, + "description": "This is the version label (e.g. `v3`) of the assistant the call was\nconfigured with. `null` for inline assistants, squad/workflow calls,\npre-resolution assistant-request messages, and orgs not on\nassistant versioning." + }, "type": { "type": "string", "description": "This is the type of the message. \"hang\" is sent when the assistant is hanging due to a delay. The delay can be caused by many factors, such as:\n- the model is too slow to respond\n- the voice is too slow to respond\n- the tool call is still waiting for a response from your server\n- etc.", @@ -48024,6 +76425,11 @@ } ] }, + "assistantVersion": { + "type": "string", + "nullable": true, + "description": "This is the version label (e.g. `v3`) of the assistant the call was\nconfigured with. `null` for inline assistants, squad/workflow calls,\npre-resolution assistant-request messages, and orgs not on\nassistant versioning." + }, "type": { "type": "string", "description": "This is the type of the message. \"knowledge-base-request\" is sent to request knowledge base documents. To enable, use `assistant.knowledgeBase.provider=custom-knowledge-base`.", @@ -48144,6 +76550,11 @@ } ] }, + "assistantVersion": { + "type": "string", + "nullable": true, + "description": "This is the version label (e.g. `v3`) of the assistant the call was\nconfigured with. `null` for inline assistants, squad/workflow calls,\npre-resolution assistant-request messages, and orgs not on\nassistant versioning." + }, "type": { "type": "string", "description": "This is the type of the message. \"model-output\" is sent as the model outputs tokens.", @@ -48151,6 +76562,10 @@ "model-output" ] }, + "turnId": { + "type": "string", + "description": "This is the unique identifier for the current LLM turn. All tokens from the same\nLLM response share the same turnId. Use this to group tokens and discard on interruption." + }, "timestamp": { "type": "number", "description": "This is the timestamp of the message." @@ -48233,6 +76648,11 @@ } ] }, + "assistantVersion": { + "type": "string", + "nullable": true, + "description": "This is the version label (e.g. `v3`) of the assistant the call was\nconfigured with. `null` for inline assistants, squad/workflow calls,\npre-resolution assistant-request messages, and orgs not on\nassistant versioning." + }, "type": { "type": "string", "description": "This is the type of the message. \"phone-call-control\" is an advanced type of message.\n\nWhen it is requested in `assistant.serverMessages`, the hangup and forwarding responsibilities are delegated to your server. Vapi will no longer do the actual transfer and hangup.", @@ -48339,6 +76759,11 @@ } ] }, + "assistantVersion": { + "type": "string", + "nullable": true, + "description": "This is the version label (e.g. `v3`) of the assistant the call was\nconfigured with. `null` for inline assistants, squad/workflow calls,\npre-resolution assistant-request messages, and orgs not on\nassistant versioning." + }, "type": { "type": "string", "description": "This is the type of the message. \"speech-update\" is sent whenever assistant or user start or stop speaking.", @@ -48445,6 +76870,11 @@ } ] }, + "assistantVersion": { + "type": "string", + "nullable": true, + "description": "This is the version label (e.g. `v3`) of the assistant the call was\nconfigured with. `null` for inline assistants, squad/workflow calls,\npre-resolution assistant-request messages, and orgs not on\nassistant versioning." + }, "type": { "type": "string", "description": "This is the type of the message. \"status-update\" is sent whenever the `call.status` changes.", @@ -48461,7 +76891,9 @@ "ringing", "in-progress", "forwarding", - "ended" + "ended", + "not-found", + "deletion-failed" ] }, "endedReason": { @@ -48486,12 +76918,15 @@ "call.start.error-vapi-number-outbound-daily-limit", "call.start.error-get-transport", "call.start.error-subscription-wallet-does-not-exist", + "call.start.error-fraud-check-failed", "call.start.error-subscription-frozen", "call.start.error-subscription-insufficient-credits", "call.start.error-subscription-upgrade-failed", "call.start.error-subscription-concurrency-limit-reached", + "call.start.error-enterprise-feature-not-available-recording-consent", + "call.start.assistant-version-error-validation", "assistant-not-valid", - "database-error", + "call.start.error-vapifault-database-error", "assistant-not-found", "pipeline-error-openai-voice-failed", "pipeline-error-cartesia-voice-failed", @@ -48502,11 +76937,16 @@ "pipeline-error-azure-voice-failed", "pipeline-error-rime-ai-voice-failed", "pipeline-error-smallest-ai-voice-failed", + "pipeline-error-vapi-voice-failed", "pipeline-error-neuphonic-voice-failed", "pipeline-error-hume-voice-failed", "pipeline-error-sesame-voice-failed", "pipeline-error-inworld-voice-failed", "pipeline-error-minimax-voice-failed", + "pipeline-error-wellsaid-voice-failed", + "pipeline-error-xai-voice-failed", + "pipeline-error-microsoft-voice-failed", + "pipeline-error-microsoft-voice-request-canceled", "pipeline-error-tavus-video-failed", "call.in-progress.error-vapifault-openai-voice-failed", "call.in-progress.error-vapifault-cartesia-voice-failed", @@ -48517,11 +76957,15 @@ "call.in-progress.error-vapifault-azure-voice-failed", "call.in-progress.error-vapifault-rime-ai-voice-failed", "call.in-progress.error-vapifault-smallest-ai-voice-failed", + "call.in-progress.error-vapifault-vapi-voice-failed", "call.in-progress.error-vapifault-neuphonic-voice-failed", "call.in-progress.error-vapifault-hume-voice-failed", "call.in-progress.error-vapifault-sesame-voice-failed", "call.in-progress.error-vapifault-inworld-voice-failed", "call.in-progress.error-vapifault-minimax-voice-failed", + "call.in-progress.error-vapifault-wellsaid-voice-failed", + "call.in-progress.error-vapifault-xai-voice-failed", + "call.in-progress.error-vapifault-microsoft-voice-failed", "call.in-progress.error-vapifault-tavus-video-failed", "pipeline-error-vapi-llm-failed", "pipeline-error-vapi-400-bad-request-validation-failed", @@ -48530,6 +76974,7 @@ "pipeline-error-vapi-429-exceeded-quota", "pipeline-error-vapi-500-server-error", "pipeline-error-vapi-503-server-overloaded-error", + "call.in-progress.error-providerfault-vapi-llm-failed", "call.in-progress.error-vapifault-vapi-llm-failed", "call.in-progress.error-vapifault-vapi-400-bad-request-validation-failed", "call.in-progress.error-vapifault-vapi-401-unauthorized", @@ -48537,7 +76982,12 @@ "call.in-progress.error-vapifault-vapi-429-exceeded-quota", "call.in-progress.error-providerfault-vapi-500-server-error", "call.in-progress.error-providerfault-vapi-503-server-overloaded-error", + "pipeline-error-vapi-transcriber-failed", + "call.in-progress.error-vapifault-vapi-transcriber-failed", + "call.in-progress.error-providerfault-vapi-transcriber-failed", + "call.in-progress.error-providerfault-vapi-voice-failed", "pipeline-error-deepgram-transcriber-failed", + "pipeline-error-deepgram-transcriber-api-key-missing", "call.in-progress.error-vapifault-deepgram-transcriber-failed", "pipeline-error-gladia-transcriber-failed", "call.in-progress.error-vapifault-gladia-transcriber-failed", @@ -48559,6 +77009,34 @@ "call.in-progress.error-vapifault-talkscriber-transcriber-failed", "pipeline-error-azure-speech-transcriber-failed", "call.in-progress.error-vapifault-azure-speech-transcriber-failed", + "pipeline-error-eleven-labs-transcriber-failed", + "call.in-progress.error-vapifault-eleven-labs-transcriber-failed", + "pipeline-error-google-transcriber-failed", + "call.in-progress.error-vapifault-google-transcriber-failed", + "pipeline-error-openai-transcriber-failed", + "call.in-progress.error-vapifault-openai-transcriber-failed", + "pipeline-error-soniox-transcriber-auth-failed", + "pipeline-error-soniox-transcriber-rate-limited", + "pipeline-error-soniox-transcriber-invalid-config", + "pipeline-error-soniox-transcriber-server-error", + "pipeline-error-soniox-transcriber-failed", + "call.in-progress.error-vapifault-soniox-transcriber-auth-failed", + "call.in-progress.error-vapifault-soniox-transcriber-rate-limited", + "call.in-progress.error-vapifault-soniox-transcriber-invalid-config", + "call.in-progress.error-vapifault-soniox-transcriber-server-error", + "call.in-progress.error-vapifault-soniox-transcriber-failed", + "pipeline-error-xai-transcriber-auth-failed", + "pipeline-error-xai-transcriber-rate-limited", + "pipeline-error-xai-transcriber-invalid-config", + "pipeline-error-xai-transcriber-server-error", + "pipeline-error-xai-transcriber-failed", + "call.in-progress.error-vapifault-xai-transcriber-auth-failed", + "call.in-progress.error-vapifault-xai-transcriber-rate-limited", + "call.in-progress.error-vapifault-xai-transcriber-invalid-config", + "call.in-progress.error-vapifault-xai-transcriber-server-error", + "call.in-progress.error-vapifault-xai-transcriber-failed", + "pipeline-error-cartesia-transcriber-failed", + "call.in-progress.error-vapifault-cartesia-transcriber-failed", "call.in-progress.error-pipeline-no-available-llm-model", "worker-shutdown", "vonage-disconnected", @@ -48573,15 +77051,21 @@ "call.in-progress.error-vapifault-worker-died", "call.in-progress.twilio-completed-call", "call.in-progress.sip-completed-call", - "call.in-progress.error-vapifault-openai-llm-failed", - "call.in-progress.error-vapifault-azure-openai-llm-failed", - "call.in-progress.error-vapifault-groq-llm-failed", - "call.in-progress.error-vapifault-google-llm-failed", - "call.in-progress.error-vapifault-xai-llm-failed", - "call.in-progress.error-vapifault-mistral-llm-failed", - "call.in-progress.error-vapifault-inflection-ai-llm-failed", - "call.in-progress.error-vapifault-cerebras-llm-failed", - "call.in-progress.error-vapifault-deep-seek-llm-failed", + "call.in-progress.error-sip-inbound-call-failed-to-connect", + "call.in-progress.error-providerfault-outbound-sip-503-service-unavailable", + "call.in-progress.error-sip-outbound-call-failed-to-connect", + "call.ringing.error-sip-inbound-call-failed-to-connect", + "call.in-progress.error-providerfault-openai-llm-failed", + "call.in-progress.error-providerfault-azure-openai-llm-failed", + "call.in-progress.error-providerfault-groq-llm-failed", + "call.in-progress.error-providerfault-google-llm-failed", + "call.in-progress.error-providerfault-xai-llm-failed", + "call.in-progress.error-providerfault-mistral-llm-failed", + "call.in-progress.error-providerfault-minimax-llm-failed", + "call.in-progress.error-providerfault-inflection-ai-llm-failed", + "call.in-progress.error-providerfault-cerebras-llm-failed", + "call.in-progress.error-providerfault-deep-seek-llm-failed", + "call.in-progress.error-providerfault-baseten-llm-failed", "call.in-progress.error-vapifault-chat-pipeline-failed-to-start", "pipeline-error-openai-400-bad-request-validation-failed", "pipeline-error-openai-401-unauthorized", @@ -48641,6 +77125,19 @@ "call.in-progress.error-vapifault-xai-429-exceeded-quota", "call.in-progress.error-providerfault-xai-500-server-error", "call.in-progress.error-providerfault-xai-503-server-overloaded-error", + "pipeline-error-baseten-400-bad-request-validation-failed", + "pipeline-error-baseten-401-unauthorized", + "pipeline-error-baseten-403-model-access-denied", + "pipeline-error-baseten-429-exceeded-quota", + "pipeline-error-baseten-500-server-error", + "pipeline-error-baseten-503-server-overloaded-error", + "pipeline-error-baseten-llm-failed", + "call.in-progress.error-vapifault-baseten-400-bad-request-validation-failed", + "call.in-progress.error-vapifault-baseten-401-unauthorized", + "call.in-progress.error-vapifault-baseten-403-model-access-denied", + "call.in-progress.error-vapifault-baseten-429-exceeded-quota", + "call.in-progress.error-providerfault-baseten-500-server-error", + "call.in-progress.error-providerfault-baseten-503-server-overloaded-error", "pipeline-error-mistral-400-bad-request-validation-failed", "pipeline-error-mistral-401-unauthorized", "pipeline-error-mistral-403-model-access-denied", @@ -48654,6 +77151,19 @@ "call.in-progress.error-vapifault-mistral-429-exceeded-quota", "call.in-progress.error-providerfault-mistral-500-server-error", "call.in-progress.error-providerfault-mistral-503-server-overloaded-error", + "pipeline-error-minimax-400-bad-request-validation-failed", + "pipeline-error-minimax-401-unauthorized", + "pipeline-error-minimax-403-model-access-denied", + "pipeline-error-minimax-429-exceeded-quota", + "pipeline-error-minimax-500-server-error", + "pipeline-error-minimax-503-server-overloaded-error", + "pipeline-error-minimax-llm-failed", + "call.in-progress.error-vapifault-minimax-400-bad-request-validation-failed", + "call.in-progress.error-vapifault-minimax-401-unauthorized", + "call.in-progress.error-vapifault-minimax-403-model-access-denied", + "call.in-progress.error-vapifault-minimax-429-exceeded-quota", + "call.in-progress.error-providerfault-minimax-500-server-error", + "call.in-progress.error-providerfault-minimax-503-server-overloaded-error", "pipeline-error-inflection-ai-400-bad-request-validation-failed", "pipeline-error-inflection-ai-401-unauthorized", "pipeline-error-inflection-ai-403-model-access-denied", @@ -48713,7 +77223,7 @@ "pipeline-error-anthropic-500-server-error", "pipeline-error-anthropic-503-server-overloaded-error", "pipeline-error-anthropic-llm-failed", - "call.in-progress.error-vapifault-anthropic-llm-failed", + "call.in-progress.error-providerfault-anthropic-llm-failed", "call.in-progress.error-vapifault-anthropic-400-bad-request-validation-failed", "call.in-progress.error-vapifault-anthropic-401-unauthorized", "call.in-progress.error-vapifault-anthropic-403-model-access-denied", @@ -48727,7 +77237,7 @@ "pipeline-error-anthropic-bedrock-500-server-error", "pipeline-error-anthropic-bedrock-503-server-overloaded-error", "pipeline-error-anthropic-bedrock-llm-failed", - "call.in-progress.error-vapifault-anthropic-bedrock-llm-failed", + "call.in-progress.error-providerfault-anthropic-bedrock-llm-failed", "call.in-progress.error-vapifault-anthropic-bedrock-400-bad-request-validation-failed", "call.in-progress.error-vapifault-anthropic-bedrock-401-unauthorized", "call.in-progress.error-vapifault-anthropic-bedrock-403-model-access-denied", @@ -48741,7 +77251,7 @@ "pipeline-error-anthropic-vertex-500-server-error", "pipeline-error-anthropic-vertex-503-server-overloaded-error", "pipeline-error-anthropic-vertex-llm-failed", - "call.in-progress.error-vapifault-anthropic-vertex-llm-failed", + "call.in-progress.error-providerfault-anthropic-vertex-llm-failed", "call.in-progress.error-vapifault-anthropic-vertex-400-bad-request-validation-failed", "call.in-progress.error-vapifault-anthropic-vertex-401-unauthorized", "call.in-progress.error-vapifault-anthropic-vertex-403-model-access-denied", @@ -48755,7 +77265,7 @@ "pipeline-error-together-ai-500-server-error", "pipeline-error-together-ai-503-server-overloaded-error", "pipeline-error-together-ai-llm-failed", - "call.in-progress.error-vapifault-together-ai-llm-failed", + "call.in-progress.error-providerfault-together-ai-llm-failed", "call.in-progress.error-vapifault-together-ai-400-bad-request-validation-failed", "call.in-progress.error-vapifault-together-ai-401-unauthorized", "call.in-progress.error-vapifault-together-ai-403-model-access-denied", @@ -48769,7 +77279,7 @@ "pipeline-error-anyscale-500-server-error", "pipeline-error-anyscale-503-server-overloaded-error", "pipeline-error-anyscale-llm-failed", - "call.in-progress.error-vapifault-anyscale-llm-failed", + "call.in-progress.error-providerfault-anyscale-llm-failed", "call.in-progress.error-vapifault-anyscale-400-bad-request-validation-failed", "call.in-progress.error-vapifault-anyscale-401-unauthorized", "call.in-progress.error-vapifault-anyscale-403-model-access-denied", @@ -48783,7 +77293,7 @@ "pipeline-error-openrouter-500-server-error", "pipeline-error-openrouter-503-server-overloaded-error", "pipeline-error-openrouter-llm-failed", - "call.in-progress.error-vapifault-openrouter-llm-failed", + "call.in-progress.error-providerfault-openrouter-llm-failed", "call.in-progress.error-vapifault-openrouter-400-bad-request-validation-failed", "call.in-progress.error-vapifault-openrouter-401-unauthorized", "call.in-progress.error-vapifault-openrouter-403-model-access-denied", @@ -48797,7 +77307,7 @@ "pipeline-error-perplexity-ai-500-server-error", "pipeline-error-perplexity-ai-503-server-overloaded-error", "pipeline-error-perplexity-ai-llm-failed", - "call.in-progress.error-vapifault-perplexity-ai-llm-failed", + "call.in-progress.error-providerfault-perplexity-ai-llm-failed", "call.in-progress.error-vapifault-perplexity-ai-400-bad-request-validation-failed", "call.in-progress.error-vapifault-perplexity-ai-401-unauthorized", "call.in-progress.error-vapifault-perplexity-ai-403-model-access-denied", @@ -48811,7 +77321,7 @@ "pipeline-error-deepinfra-500-server-error", "pipeline-error-deepinfra-503-server-overloaded-error", "pipeline-error-deepinfra-llm-failed", - "call.in-progress.error-vapifault-deepinfra-llm-failed", + "call.in-progress.error-providerfault-deepinfra-llm-failed", "call.in-progress.error-vapifault-deepinfra-400-bad-request-validation-failed", "call.in-progress.error-vapifault-deepinfra-401-unauthorized", "call.in-progress.error-vapifault-deepinfra-403-model-access-denied", @@ -48825,7 +77335,7 @@ "pipeline-error-runpod-500-server-error", "pipeline-error-runpod-503-server-overloaded-error", "pipeline-error-runpod-llm-failed", - "call.in-progress.error-vapifault-runpod-llm-failed", + "call.in-progress.error-providerfault-runpod-llm-failed", "call.in-progress.error-vapifault-runpod-400-bad-request-validation-failed", "call.in-progress.error-vapifault-runpod-401-unauthorized", "call.in-progress.error-vapifault-runpod-403-model-access-denied", @@ -48839,13 +77349,14 @@ "pipeline-error-custom-llm-500-server-error", "pipeline-error-custom-llm-503-server-overloaded-error", "pipeline-error-custom-llm-llm-failed", - "call.in-progress.error-vapifault-custom-llm-llm-failed", + "call.in-progress.error-providerfault-custom-llm-llm-failed", "call.in-progress.error-vapifault-custom-llm-400-bad-request-validation-failed", "call.in-progress.error-vapifault-custom-llm-401-unauthorized", "call.in-progress.error-vapifault-custom-llm-403-model-access-denied", "call.in-progress.error-vapifault-custom-llm-429-exceeded-quota", "call.in-progress.error-providerfault-custom-llm-500-server-error", "call.in-progress.error-providerfault-custom-llm-503-server-overloaded-error", + "call.in-progress.error-pipeline-ws-model-connection-failed", "pipeline-error-custom-voice-failed", "pipeline-error-cartesia-socket-hang-up", "pipeline-error-cartesia-requested-payment", @@ -48901,6 +77412,7 @@ "call.in-progress.error-vapifault-eleven-labs-voice-not-allowed-for-free-users", "call.in-progress.error-vapifault-eleven-labs-max-character-limit-exceeded", "call.in-progress.error-vapifault-eleven-labs-blocked-voice-potentially-against-terms-of-service-and-awaiting-verification", + "call.in-progress.error-providerfault-eleven-labs-system-busy-and-requested-upgrade", "call.in-progress.error-providerfault-eleven-labs-500-server-error", "call.in-progress.error-providerfault-eleven-labs-503-server-error", "pipeline-error-playht-request-timed-out", @@ -48950,12 +77462,32 @@ "call.in-progress.error-vapifault-google-transcriber-failed", "pipeline-error-openai-transcriber-failed", "call.in-progress.error-vapifault-openai-transcriber-failed", + "pipeline-error-soniox-transcriber-auth-failed", + "pipeline-error-soniox-transcriber-rate-limited", + "pipeline-error-soniox-transcriber-invalid-config", + "pipeline-error-soniox-transcriber-server-error", + "pipeline-error-soniox-transcriber-failed", + "call.in-progress.error-vapifault-soniox-transcriber-auth-failed", + "call.in-progress.error-vapifault-soniox-transcriber-rate-limited", + "call.in-progress.error-vapifault-soniox-transcriber-invalid-config", + "call.in-progress.error-vapifault-soniox-transcriber-server-error", + "call.in-progress.error-vapifault-soniox-transcriber-failed", + "pipeline-error-xai-transcriber-auth-failed", + "pipeline-error-xai-transcriber-rate-limited", + "pipeline-error-xai-transcriber-invalid-config", + "pipeline-error-xai-transcriber-server-error", + "pipeline-error-xai-transcriber-failed", + "call.in-progress.error-vapifault-xai-transcriber-auth-failed", + "call.in-progress.error-vapifault-xai-transcriber-rate-limited", + "call.in-progress.error-vapifault-xai-transcriber-invalid-config", + "call.in-progress.error-vapifault-xai-transcriber-server-error", + "call.in-progress.error-vapifault-xai-transcriber-failed", + "pipeline-error-cartesia-transcriber-failed", + "call.in-progress.error-vapifault-cartesia-transcriber-failed", "call.in-progress.error-warm-transfer-max-duration", "call.in-progress.error-warm-transfer-assistant-cancelled", "call.in-progress.error-warm-transfer-silence-timeout", "call.in-progress.error-warm-transfer-microphone-timeout", - "call.in-progress.error-warm-transfer-hang-timeout", - "call.in-progress.error-warm-transfer-idle-timeout", "assistant-ended-call", "assistant-said-end-call-phrase", "assistant-ended-call-with-hangup-task", @@ -48966,17 +77498,21 @@ "call.in-progress.error-transfer-failed", "customer-busy", "customer-ended-call", + "customer-ended-call-before-warm-transfer", "customer-ended-call-after-warm-transfer-attempt", + "customer-ended-call-during-transfer", "customer-did-not-answer", "customer-did-not-give-microphone-permission", "exceeded-max-duration", "manually-canceled", "phone-call-provider-closed-websocket", "call.forwarding.operator-busy", + "call.forwarding.no-answer", "silence-timed-out", "call.in-progress.error-sip-inbound-call-failed-to-connect", "call.in-progress.error-providerfault-outbound-sip-403-forbidden", "call.in-progress.error-providerfault-outbound-sip-407-proxy-authentication-required", + "call.in-progress.error-providerfault-outbound-sip-408-request-timeout", "call.in-progress.error-providerfault-outbound-sip-503-service-unavailable", "call.in-progress.error-providerfault-outbound-sip-480-temporarily-unavailable", "call.in-progress.error-sip-outbound-call-failed-to-connect", @@ -48989,57 +77525,741 @@ "twilio-failed-to-connect-call", "twilio-reported-customer-misdialed", "vonage-rejected", - "voicemail" + "voicemail", + "call-deleted" + ] + }, + "messages": { + "type": "array", + "description": "These are the conversation messages of the call. This is only sent if the status is \"forwarding\".", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/UserMessage", + "title": "UserMessage" + }, + { + "$ref": "#/components/schemas/SystemMessage", + "title": "SystemMessage" + }, + { + "$ref": "#/components/schemas/BotMessage", + "title": "BotMessage" + }, + { + "$ref": "#/components/schemas/ToolCallMessage", + "title": "ToolCallMessage" + }, + { + "$ref": "#/components/schemas/ToolCallResultMessage", + "title": "ToolCallResultMessage" + } + ] + } + }, + "messagesOpenAIFormatted": { + "description": "These are the conversation messages of the call. This is only sent if the status is \"forwarding\".", + "type": "array", + "items": { + "$ref": "#/components/schemas/OpenAIMessage" + } + }, + "destination": { + "description": "This is the destination the call is being transferred to. This is only sent if the status is \"forwarding\".", + "oneOf": [ + { + "$ref": "#/components/schemas/TransferDestinationNumber", + "title": "NumberTransferDestination" + }, + { + "$ref": "#/components/schemas/TransferDestinationSip", + "title": "SipTransferDestination" + } + ] + }, + "timestamp": { + "type": "number", + "description": "This is the timestamp of the message." + }, + "artifact": { + "description": "This is a live version of the `call.artifact`.\n\nThis matches what is stored on `call.artifact` after the call.", + "allOf": [ + { + "$ref": "#/components/schemas/Artifact" + } + ] + }, + "assistant": { + "description": "This is the assistant that the message is associated with.", + "allOf": [ + { + "$ref": "#/components/schemas/CreateAssistantDTO" + } + ] + }, + "customer": { + "description": "This is the customer that the message is associated with.", + "allOf": [ + { + "$ref": "#/components/schemas/CreateCustomerDTO" + } + ] + }, + "call": { + "description": "This is the call that the message is associated with.", + "allOf": [ + { + "$ref": "#/components/schemas/Call" + } + ] + }, + "chat": { + "description": "This is the chat object.", + "allOf": [ + { + "$ref": "#/components/schemas/Chat" + } + ] + }, + "transcript": { + "type": "string", + "description": "This is the transcript of the call. This is only sent if the status is \"forwarding\"." + }, + "summary": { + "type": "string", + "description": "This is the summary of the call. This is only sent if the status is \"forwarding\"." + }, + "inboundPhoneCallDebuggingArtifacts": { + "type": "object", + "description": "This is the inbound phone call debugging artifacts. This is only sent if the status is \"ended\" and there was an error accepting the inbound phone call.\n\nThis will include any errors related to the \"assistant-request\" if one was made." + } + }, + "required": [ + "type", + "status" + ] + }, + "ServerMessageToolCalls": { + "type": "object", + "properties": { + "phoneNumber": { + "description": "This is the phone number that the message is associated with.", + "oneOf": [ + { + "$ref": "#/components/schemas/CreateByoPhoneNumberDTO", + "title": "ByoPhoneNumber" + }, + { + "$ref": "#/components/schemas/CreateTwilioPhoneNumberDTO", + "title": "TwilioPhoneNumber" + }, + { + "$ref": "#/components/schemas/CreateVonagePhoneNumberDTO", + "title": "VonagePhoneNumber" + }, + { + "$ref": "#/components/schemas/CreateVapiPhoneNumberDTO", + "title": "VapiPhoneNumber" + }, + { + "$ref": "#/components/schemas/CreateTelnyxPhoneNumberDTO", + "title": "TelnyxPhoneNumber" + } + ] + }, + "assistantVersion": { + "type": "string", + "nullable": true, + "description": "This is the version label (e.g. `v3`) of the assistant the call was\nconfigured with. `null` for inline assistants, squad/workflow calls,\npre-resolution assistant-request messages, and orgs not on\nassistant versioning." + }, + "type": { + "type": "string", + "description": "This is the type of the message. \"tool-calls\" is sent to call a tool.", + "enum": [ + "tool-calls" + ] + }, + "toolWithToolCallList": { + "type": "array", + "description": "This is the list of tools calls that the model is requesting along with the original tool configuration.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/FunctionToolWithToolCall", + "title": "FunctionToolWithToolCall" + }, + { + "$ref": "#/components/schemas/GhlToolWithToolCall", + "title": "GhlToolWithToolCall" + }, + { + "$ref": "#/components/schemas/MakeToolWithToolCall", + "title": "MakeToolWithToolCall" + }, + { + "$ref": "#/components/schemas/BashToolWithToolCall", + "title": "BashToolWithToolCall" + }, + { + "$ref": "#/components/schemas/ComputerToolWithToolCall", + "title": "ComputerToolWithToolCall" + }, + { + "$ref": "#/components/schemas/TextEditorToolWithToolCall", + "title": "TextEditorToolWithToolCall" + }, + { + "$ref": "#/components/schemas/GoogleCalendarCreateEventToolWithToolCall", + "title": "GoogleCalendarCreateEventToolWithToolCall" + } + ] + } + }, + "timestamp": { + "type": "number", + "description": "This is the timestamp of the message." + }, + "artifact": { + "description": "This is a live version of the `call.artifact`.\n\nThis matches what is stored on `call.artifact` after the call.", + "allOf": [ + { + "$ref": "#/components/schemas/Artifact" + } + ] + }, + "assistant": { + "description": "This is the assistant that the message is associated with.", + "allOf": [ + { + "$ref": "#/components/schemas/CreateAssistantDTO" + } + ] + }, + "customer": { + "description": "This is the customer that the message is associated with.", + "allOf": [ + { + "$ref": "#/components/schemas/CreateCustomerDTO" + } + ] + }, + "call": { + "description": "This is the call that the message is associated with.", + "allOf": [ + { + "$ref": "#/components/schemas/Call" + } + ] + }, + "chat": { + "description": "This is the chat object.", + "allOf": [ + { + "$ref": "#/components/schemas/Chat" + } + ] + }, + "toolCallList": { + "description": "This is the list of tool calls that the model is requesting.", + "type": "array", + "items": { + "$ref": "#/components/schemas/ToolCall" + } + } + }, + "required": [ + "toolWithToolCallList", + "toolCallList" + ] + }, + "ServerMessageTransferDestinationRequest": { + "type": "object", + "properties": { + "phoneNumber": { + "description": "This is the phone number that the message is associated with.", + "oneOf": [ + { + "$ref": "#/components/schemas/CreateByoPhoneNumberDTO", + "title": "ByoPhoneNumber" + }, + { + "$ref": "#/components/schemas/CreateTwilioPhoneNumberDTO", + "title": "TwilioPhoneNumber" + }, + { + "$ref": "#/components/schemas/CreateVonagePhoneNumberDTO", + "title": "VonagePhoneNumber" + }, + { + "$ref": "#/components/schemas/CreateVapiPhoneNumberDTO", + "title": "VapiPhoneNumber" + }, + { + "$ref": "#/components/schemas/CreateTelnyxPhoneNumberDTO", + "title": "TelnyxPhoneNumber" + } + ] + }, + "assistantVersion": { + "type": "string", + "nullable": true, + "description": "This is the version label (e.g. `v3`) of the assistant the call was\nconfigured with. `null` for inline assistants, squad/workflow calls,\npre-resolution assistant-request messages, and orgs not on\nassistant versioning." + }, + "type": { + "type": "string", + "description": "This is the type of the message. \"transfer-destination-request\" is sent when the model is requesting transfer but destination is unknown.", + "enum": [ + "transfer-destination-request" + ] + }, + "timestamp": { + "type": "number", + "description": "This is the timestamp of the message." + }, + "artifact": { + "description": "This is a live version of the `call.artifact`.\n\nThis matches what is stored on `call.artifact` after the call.", + "allOf": [ + { + "$ref": "#/components/schemas/Artifact" + } + ] + }, + "assistant": { + "description": "This is the assistant that the message is associated with.", + "allOf": [ + { + "$ref": "#/components/schemas/CreateAssistantDTO" + } + ] + }, + "customer": { + "description": "This is the customer that the message is associated with.", + "allOf": [ + { + "$ref": "#/components/schemas/CreateCustomerDTO" + } + ] + }, + "call": { + "description": "This is the call that the message is associated with.", + "allOf": [ + { + "$ref": "#/components/schemas/Call" + } + ] + }, + "chat": { + "description": "This is the chat object.", + "allOf": [ + { + "$ref": "#/components/schemas/Chat" + } + ] + } + }, + "required": [ + "type" + ] + }, + "ServerMessageTransferUpdate": { + "type": "object", + "properties": { + "phoneNumber": { + "description": "This is the phone number that the message is associated with.", + "oneOf": [ + { + "$ref": "#/components/schemas/CreateByoPhoneNumberDTO", + "title": "ByoPhoneNumber" + }, + { + "$ref": "#/components/schemas/CreateTwilioPhoneNumberDTO", + "title": "TwilioPhoneNumber" + }, + { + "$ref": "#/components/schemas/CreateVonagePhoneNumberDTO", + "title": "VonagePhoneNumber" + }, + { + "$ref": "#/components/schemas/CreateVapiPhoneNumberDTO", + "title": "VapiPhoneNumber" + }, + { + "$ref": "#/components/schemas/CreateTelnyxPhoneNumberDTO", + "title": "TelnyxPhoneNumber" + } + ] + }, + "assistantVersion": { + "type": "string", + "nullable": true, + "description": "This is the version label (e.g. `v3`) of the assistant the call was\nconfigured with. `null` for inline assistants, squad/workflow calls,\npre-resolution assistant-request messages, and orgs not on\nassistant versioning." + }, + "type": { + "type": "string", + "description": "This is the type of the message. \"transfer-update\" is sent whenever a transfer happens.", + "enum": [ + "transfer-update" + ] + }, + "destination": { + "description": "This is the destination of the transfer.", + "oneOf": [ + { + "$ref": "#/components/schemas/TransferDestinationAssistant", + "title": "Assistant" + }, + { + "$ref": "#/components/schemas/TransferDestinationNumber", + "title": "Number" + }, + { + "$ref": "#/components/schemas/TransferDestinationSip", + "title": "Sip" + } + ] + }, + "timestamp": { + "type": "number", + "description": "This is the timestamp of the message." + }, + "artifact": { + "description": "This is a live version of the `call.artifact`.\n\nThis matches what is stored on `call.artifact` after the call.", + "allOf": [ + { + "$ref": "#/components/schemas/Artifact" + } + ] + }, + "assistant": { + "description": "This is the assistant that the message is associated with.", + "allOf": [ + { + "$ref": "#/components/schemas/CreateAssistantDTO" + } + ] + }, + "customer": { + "description": "This is the customer that the message is associated with.", + "allOf": [ + { + "$ref": "#/components/schemas/CreateCustomerDTO" + } + ] + }, + "call": { + "description": "This is the call that the message is associated with.", + "allOf": [ + { + "$ref": "#/components/schemas/Call" + } ] }, - "messages": { - "type": "array", - "description": "These are the conversation messages of the call. This is only sent if the status is \"forwarding\".", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/UserMessage", - "title": "UserMessage" - }, - { - "$ref": "#/components/schemas/SystemMessage", - "title": "SystemMessage" - }, - { - "$ref": "#/components/schemas/BotMessage", - "title": "BotMessage" - }, - { - "$ref": "#/components/schemas/ToolCallMessage", - "title": "ToolCallMessage" - }, - { - "$ref": "#/components/schemas/ToolCallResultMessage", - "title": "ToolCallResultMessage" - } - ] - } + "chat": { + "description": "This is the chat object.", + "allOf": [ + { + "$ref": "#/components/schemas/Chat" + } + ] }, - "messagesOpenAIFormatted": { - "description": "These are the conversation messages of the call. This is only sent if the status is \"forwarding\".", + "toAssistant": { + "description": "This is the assistant that the call is being transferred to. This is only sent if `destination.type` is \"assistant\".", + "allOf": [ + { + "$ref": "#/components/schemas/CreateAssistantDTO" + } + ] + }, + "fromAssistant": { + "description": "This is the assistant that the call is being transferred from. This is only sent if `destination.type` is \"assistant\".", + "allOf": [ + { + "$ref": "#/components/schemas/CreateAssistantDTO" + } + ] + }, + "toStepRecord": { + "type": "object", + "description": "This is the step that the conversation moved to." + }, + "fromStepRecord": { + "type": "object", + "description": "This is the step that the conversation moved from. =" + } + }, + "required": [ + "type" + ] + }, + "ServerMessageTranscript": { + "type": "object", + "properties": { + "phoneNumber": { + "description": "This is the phone number that the message is associated with.", + "oneOf": [ + { + "$ref": "#/components/schemas/CreateByoPhoneNumberDTO", + "title": "ByoPhoneNumber" + }, + { + "$ref": "#/components/schemas/CreateTwilioPhoneNumberDTO", + "title": "TwilioPhoneNumber" + }, + { + "$ref": "#/components/schemas/CreateVonagePhoneNumberDTO", + "title": "VonagePhoneNumber" + }, + { + "$ref": "#/components/schemas/CreateVapiPhoneNumberDTO", + "title": "VapiPhoneNumber" + }, + { + "$ref": "#/components/schemas/CreateTelnyxPhoneNumberDTO", + "title": "TelnyxPhoneNumber" + } + ] + }, + "assistantVersion": { + "type": "string", + "nullable": true, + "description": "This is the version label (e.g. `v3`) of the assistant the call was\nconfigured with. `null` for inline assistants, squad/workflow calls,\npre-resolution assistant-request messages, and orgs not on\nassistant versioning." + }, + "type": { + "type": "string", + "description": "This is the type of the message. \"transcript\" is sent as transcriber outputs partial or final transcript.", + "enum": [ + "transcript", + "transcript[transcriptType=\"final\"]" + ] + }, + "timestamp": { + "type": "number", + "description": "This is the timestamp of the message." + }, + "artifact": { + "description": "This is a live version of the `call.artifact`.\n\nThis matches what is stored on `call.artifact` after the call.", + "allOf": [ + { + "$ref": "#/components/schemas/Artifact" + } + ] + }, + "assistant": { + "description": "This is the assistant that the message is associated with.", + "allOf": [ + { + "$ref": "#/components/schemas/CreateAssistantDTO" + } + ] + }, + "customer": { + "description": "This is the customer that the message is associated with.", + "allOf": [ + { + "$ref": "#/components/schemas/CreateCustomerDTO" + } + ] + }, + "call": { + "description": "This is the call that the message is associated with.", + "allOf": [ + { + "$ref": "#/components/schemas/Call" + } + ] + }, + "chat": { + "description": "This is the chat object.", + "allOf": [ + { + "$ref": "#/components/schemas/Chat" + } + ] + }, + "role": { + "type": "string", + "description": "This is the role for which the transcript is for.", + "enum": [ + "assistant", + "user" + ] + }, + "transcriptType": { + "type": "string", + "description": "This is the type of the transcript.", + "enum": [ + "partial", + "final" + ] + }, + "transcript": { + "type": "string", + "description": "This is the transcript content." + }, + "assistantId": { + "type": "string", + "description": "The ID of the assistant that produced this transcript. Present on\nassistant-role events when an active assistant ID is available." + }, + "assistantName": { + "type": "string", + "description": "The name of the assistant that produced this transcript. Present on\nassistant-role events when an active assistant name is available." + }, + "isFiltered": { + "type": "boolean", + "description": "Indicates if the transcript was filtered for security reasons." + }, + "detectedThreats": { + "description": "List of detected security threats if the transcript was filtered.", "type": "array", "items": { - "$ref": "#/components/schemas/OpenAIMessage" + "type": "string" } }, - "destination": { - "description": "This is the destination the call is being transferred to. This is only sent if the status is \"forwarding\".", + "originalTranscript": { + "type": "string", + "description": "The original transcript before filtering (only included if content was filtered)." + } + }, + "required": [ + "type", + "role", + "transcriptType", + "transcript" + ] + }, + "ServerMessageUserInterrupted": { + "type": "object", + "properties": { + "phoneNumber": { + "description": "This is the phone number that the message is associated with.", "oneOf": [ { - "$ref": "#/components/schemas/TransferDestinationNumber", - "title": "NumberTransferDestination" + "$ref": "#/components/schemas/CreateByoPhoneNumberDTO", + "title": "ByoPhoneNumber" }, { - "$ref": "#/components/schemas/TransferDestinationSip", - "title": "SipTransferDestination" + "$ref": "#/components/schemas/CreateTwilioPhoneNumberDTO", + "title": "TwilioPhoneNumber" + }, + { + "$ref": "#/components/schemas/CreateVonagePhoneNumberDTO", + "title": "VonagePhoneNumber" + }, + { + "$ref": "#/components/schemas/CreateVapiPhoneNumberDTO", + "title": "VapiPhoneNumber" + }, + { + "$ref": "#/components/schemas/CreateTelnyxPhoneNumberDTO", + "title": "TelnyxPhoneNumber" + } + ] + }, + "assistantVersion": { + "type": "string", + "nullable": true, + "description": "This is the version label (e.g. `v3`) of the assistant the call was\nconfigured with. `null` for inline assistants, squad/workflow calls,\npre-resolution assistant-request messages, and orgs not on\nassistant versioning." + }, + "type": { + "type": "string", + "description": "This is the type of the message. \"user-interrupted\" is sent when the user interrupts the assistant.", + "enum": [ + "user-interrupted" + ] + }, + "turnId": { + "type": "string", + "description": "This is the turnId of the LLM response that was interrupted. Matches the turnId\non model-output messages so clients can discard the interrupted turn's tokens." + }, + "timestamp": { + "type": "number", + "description": "This is the timestamp of the message." + }, + "artifact": { + "description": "This is a live version of the `call.artifact`.\n\nThis matches what is stored on `call.artifact` after the call.", + "allOf": [ + { + "$ref": "#/components/schemas/Artifact" + } + ] + }, + "assistant": { + "description": "This is the assistant that the message is associated with.", + "allOf": [ + { + "$ref": "#/components/schemas/CreateAssistantDTO" + } + ] + }, + "customer": { + "description": "This is the customer that the message is associated with.", + "allOf": [ + { + "$ref": "#/components/schemas/CreateCustomerDTO" + } + ] + }, + "call": { + "description": "This is the call that the message is associated with.", + "allOf": [ + { + "$ref": "#/components/schemas/Call" + } + ] + }, + "chat": { + "description": "This is the chat object.", + "allOf": [ + { + "$ref": "#/components/schemas/Chat" + } + ] + } + }, + "required": [ + "type" + ] + }, + "ServerMessageLanguageChangeDetected": { + "type": "object", + "properties": { + "phoneNumber": { + "description": "This is the phone number that the message is associated with.", + "oneOf": [ + { + "$ref": "#/components/schemas/CreateByoPhoneNumberDTO", + "title": "ByoPhoneNumber" + }, + { + "$ref": "#/components/schemas/CreateTwilioPhoneNumberDTO", + "title": "TwilioPhoneNumber" + }, + { + "$ref": "#/components/schemas/CreateVonagePhoneNumberDTO", + "title": "VonagePhoneNumber" + }, + { + "$ref": "#/components/schemas/CreateVapiPhoneNumberDTO", + "title": "VapiPhoneNumber" + }, + { + "$ref": "#/components/schemas/CreateTelnyxPhoneNumberDTO", + "title": "TelnyxPhoneNumber" } ] }, + "assistantVersion": { + "type": "string", + "nullable": true, + "description": "This is the version label (e.g. `v3`) of the assistant the call was\nconfigured with. `null` for inline assistants, squad/workflow calls,\npre-resolution assistant-request messages, and orgs not on\nassistant versioning." + }, + "type": { + "type": "string", + "description": "This is the type of the message. \"language-change-detected\" is sent when the transcriber is automatically switched based on the detected language.", + "enum": [ + "language-change-detected" + ] + }, "timestamp": { "type": "number", "description": "This is the timestamp of the message." @@ -49084,25 +78304,111 @@ } ] }, - "transcript": { + "language": { "type": "string", - "description": "This is the transcript of the call. This is only sent if the status is \"forwarding\"." + "description": "This is the language the transcriber is switched to." + } + }, + "required": [ + "type", + "language" + ] + }, + "ServerMessageVoiceInput": { + "type": "object", + "properties": { + "phoneNumber": { + "description": "This is the phone number that the message is associated with.", + "oneOf": [ + { + "$ref": "#/components/schemas/CreateByoPhoneNumberDTO", + "title": "ByoPhoneNumber" + }, + { + "$ref": "#/components/schemas/CreateTwilioPhoneNumberDTO", + "title": "TwilioPhoneNumber" + }, + { + "$ref": "#/components/schemas/CreateVonagePhoneNumberDTO", + "title": "VonagePhoneNumber" + }, + { + "$ref": "#/components/schemas/CreateVapiPhoneNumberDTO", + "title": "VapiPhoneNumber" + }, + { + "$ref": "#/components/schemas/CreateTelnyxPhoneNumberDTO", + "title": "TelnyxPhoneNumber" + } + ] }, - "summary": { + "assistantVersion": { "type": "string", - "description": "This is the summary of the call. This is only sent if the status is \"forwarding\"." + "nullable": true, + "description": "This is the version label (e.g. `v3`) of the assistant the call was\nconfigured with. `null` for inline assistants, squad/workflow calls,\npre-resolution assistant-request messages, and orgs not on\nassistant versioning." }, - "inboundPhoneCallDebuggingArtifacts": { - "type": "object", - "description": "This is the inbound phone call debugging artifacts. This is only sent if the status is \"ended\" and there was an error accepting the inbound phone call.\n\nThis will include any errors related to the \"assistant-request\" if one was made." + "type": { + "type": "string", + "description": "This is the type of the message. \"voice-input\" is sent when a generation is requested from voice provider.", + "enum": [ + "voice-input" + ] + }, + "timestamp": { + "type": "number", + "description": "This is the timestamp of the message." + }, + "artifact": { + "description": "This is a live version of the `call.artifact`.\n\nThis matches what is stored on `call.artifact` after the call.", + "allOf": [ + { + "$ref": "#/components/schemas/Artifact" + } + ] + }, + "assistant": { + "description": "This is the assistant that the message is associated with.", + "allOf": [ + { + "$ref": "#/components/schemas/CreateAssistantDTO" + } + ] + }, + "customer": { + "description": "This is the customer that the message is associated with.", + "allOf": [ + { + "$ref": "#/components/schemas/CreateCustomerDTO" + } + ] + }, + "call": { + "description": "This is the call that the message is associated with.", + "allOf": [ + { + "$ref": "#/components/schemas/Call" + } + ] + }, + "chat": { + "description": "This is the chat object.", + "allOf": [ + { + "$ref": "#/components/schemas/Chat" + } + ] + }, + "input": { + "type": "string", + "description": "This is the voice input content" } }, "required": [ "type", - "status" + "input" ] }, - "ServerMessageToolCalls": { + "ServerMessageAssistantSpeech": { "type": "object", "properties": { "phoneNumber": { @@ -49130,47 +78436,49 @@ } ] }, + "assistantVersion": { + "type": "string", + "nullable": true, + "description": "This is the version label (e.g. `v3`) of the assistant the call was\nconfigured with. `null` for inline assistants, squad/workflow calls,\npre-resolution assistant-request messages, and orgs not on\nassistant versioning." + }, "type": { "type": "string", - "description": "This is the type of the message. \"tool-calls\" is sent to call a tool.", + "description": "This is the type of the message. \"assistant-speech\" is sent as assistant audio is being played.", "enum": [ - "tool-calls" + "assistant.speechStarted" ] }, - "toolWithToolCallList": { - "type": "array", - "description": "This is the list of tools calls that the model is requesting along with the original tool configuration.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/FunctionToolWithToolCall", - "title": "FunctionToolWithToolCall" - }, - { - "$ref": "#/components/schemas/GhlToolWithToolCall", - "title": "GhlToolWithToolCall" - }, - { - "$ref": "#/components/schemas/MakeToolWithToolCall", - "title": "MakeToolWithToolCall" - }, - { - "$ref": "#/components/schemas/BashToolWithToolCall", - "title": "BashToolWithToolCall" - }, - { - "$ref": "#/components/schemas/ComputerToolWithToolCall", - "title": "ComputerToolWithToolCall" - }, - { - "$ref": "#/components/schemas/TextEditorToolWithToolCall", - "title": "TextEditorToolWithToolCall" - }, - { - "$ref": "#/components/schemas/GoogleCalendarCreateEventToolWithToolCall", - "title": "GoogleCalendarCreateEventToolWithToolCall" - } - ] + "text": { + "type": "string", + "description": "The full assistant text for the current turn. This is the complete text,\nnot an incremental delta — consumers should use `timing` metadata (e.g.\n`wordsSpoken`) to determine which portion has been spoken so far." + }, + "turn": { + "type": "number", + "description": "This is the turn number of the assistant speech event (0-indexed)." + }, + "source": { + "type": "string", + "description": "Indicates how the text was sourced.", + "enum": [ + "model", + "force-say", + "custom-voice" + ] + }, + "timing": { + "description": "Optional timing metadata. Shape depends on `timing.type`:\n\n- `word-alignment` (ElevenLabs): per-character timing at playback\n cadence. words[] includes space entries. Best consumed by tracking\n a running character count: join timing.words, add to a char cursor,\n and highlight text up to that position. No interpolation needed.\n\n- `word-progress` (Minimax with voice.subtitleType: 'word'): cursor-\n based word count per TTS segment. Use wordsSpoken as the anchor,\n interpolate forward using segmentDurationMs or timing.words until\n the next event arrives.\n\nWhen absent, the event is a text-only fallback for providers without\nword-level timing (e.g. Cartesia, Deepgram, Azure). Text emits once\nper TTS chunk when audio is playing. Optionally interpolate a word\ncursor at ~3.5 words/sec between events for approximate tracking.", + "oneOf": [ + { + "$ref": "#/components/schemas/AssistantSpeechWordAlignmentTiming", + "title": "WordAlignmentTiming" + }, + { + "$ref": "#/components/schemas/AssistantSpeechWordProgressTiming", + "title": "WordProgressTiming" + } + ], + "discriminator": { + "propertyName": "type" } }, "timestamp": { @@ -49216,21 +78524,14 @@ "$ref": "#/components/schemas/Chat" } ] - }, - "toolCallList": { - "description": "This is the list of tool calls that the model is requesting.", - "type": "array", - "items": { - "$ref": "#/components/schemas/ToolCall" - } } }, "required": [ - "toolWithToolCallList", - "toolCallList" + "type", + "text" ] }, - "ServerMessageTransferDestinationRequest": { + "ServerMessageVoiceRequest": { "type": "object", "properties": { "phoneNumber": { @@ -49258,11 +78559,16 @@ } ] }, + "assistantVersion": { + "type": "string", + "nullable": true, + "description": "This is the version label (e.g. `v3`) of the assistant the call was\nconfigured with. `null` for inline assistants, squad/workflow calls,\npre-resolution assistant-request messages, and orgs not on\nassistant versioning." + }, "type": { "type": "string", - "description": "This is the type of the message. \"transfer-destination-request\" is sent when the model is requesting transfer but destination is unknown.", + "description": "This is the type of the message. \"voice-request\" is sent when using `assistant.voice={ \"type\": \"custom-voice\" }`.\n\nHere is what the request will look like:\n\nPOST https://{assistant.voice.server.url}\nContent-Type: application/json\n\n{\n \"messsage\": {\n \"type\": \"voice-request\",\n \"text\": \"Hello, world!\",\n \"sampleRate\": 24000,\n ...other metadata about the call...\n }\n}\n\nThe expected response is 1-channel 16-bit raw PCM audio at the sample rate specified in the request. Here is how the response will be piped to the transport:\n```\nresponse.on('data', (chunk: Buffer) => {\n outputStream.write(chunk);\n});\n```", "enum": [ - "transfer-destination-request" + "voice-request" ] }, "timestamp": { @@ -49308,13 +78614,23 @@ "$ref": "#/components/schemas/Chat" } ] + }, + "text": { + "type": "string", + "description": "This is the text to be synthesized." + }, + "sampleRate": { + "type": "number", + "description": "This is the sample rate to be synthesized." } }, "required": [ - "type" + "type", + "text", + "sampleRate" ] }, - "ServerMessageTransferUpdate": { + "ServerMessageCallEndpointingRequest": { "type": "object", "properties": { "phoneNumber": { @@ -49342,29 +78658,52 @@ } ] }, + "assistantVersion": { + "type": "string", + "nullable": true, + "description": "This is the version label (e.g. `v3`) of the assistant the call was\nconfigured with. `null` for inline assistants, squad/workflow calls,\npre-resolution assistant-request messages, and orgs not on\nassistant versioning." + }, "type": { "type": "string", - "description": "This is the type of the message. \"transfer-update\" is sent whenever a transfer happens.", + "description": "This is the type of the message. \"call.endpointing.request\" is sent when using `assistant.startSpeakingPlan.smartEndpointingPlan={ \"provider\": \"custom-endpointing-model\" }`.\n\nHere is what the request will look like:\n\nPOST https://{assistant.startSpeakingPlan.smartEndpointingPlan.server.url}\nContent-Type: application/json\n\n{\n \"message\": {\n \"type\": \"call.endpointing.request\",\n \"messages\": [\n {\n \"role\": \"user\",\n \"message\": \"Hello, how are you?\",\n \"time\": 1234567890,\n \"secondsFromStart\": 0\n }\n ],\n ...other metadata about the call...\n }\n}\n\nThe expected response:\n{\n \"timeoutSeconds\": 0.5\n}", "enum": [ - "transfer-update" + "call.endpointing.request" ] }, - "destination": { - "description": "This is the destination of the transfer.", - "oneOf": [ - { - "$ref": "#/components/schemas/TransferDestinationAssistant", - "title": "Assistant" - }, - { - "$ref": "#/components/schemas/TransferDestinationNumber", - "title": "Number" - }, - { - "$ref": "#/components/schemas/TransferDestinationSip", - "title": "Sip" - } - ] + "messages": { + "type": "array", + "description": "This is the conversation history at the time of the endpointing request.", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/UserMessage", + "title": "UserMessage" + }, + { + "$ref": "#/components/schemas/SystemMessage", + "title": "SystemMessage" + }, + { + "$ref": "#/components/schemas/BotMessage", + "title": "BotMessage" + }, + { + "$ref": "#/components/schemas/ToolCallMessage", + "title": "ToolCallMessage" + }, + { + "$ref": "#/components/schemas/ToolCallResultMessage", + "title": "ToolCallResultMessage" + } + ] + } + }, + "messagesOpenAIFormatted": { + "description": "This is just `messages` formatted for OpenAI.", + "type": "array", + "items": { + "$ref": "#/components/schemas/OpenAIMessage" + } }, "timestamp": { "type": "number", @@ -49409,37 +78748,14 @@ "$ref": "#/components/schemas/Chat" } ] - }, - "toAssistant": { - "description": "This is the assistant that the call is being transferred to. This is only sent if `destination.type` is \"assistant\".", - "allOf": [ - { - "$ref": "#/components/schemas/CreateAssistantDTO" - } - ] - }, - "fromAssistant": { - "description": "This is the assistant that the call is being transferred from. This is only sent if `destination.type` is \"assistant\".", - "allOf": [ - { - "$ref": "#/components/schemas/CreateAssistantDTO" - } - ] - }, - "toStepRecord": { - "type": "object", - "description": "This is the step that the conversation moved to." - }, - "fromStepRecord": { - "type": "object", - "description": "This is the step that the conversation moved from. =" } }, "required": [ - "type" + "type", + "messagesOpenAIFormatted" ] }, - "ServerMessageTranscript": { + "ServerMessageChatCreated": { "type": "object", "properties": { "phoneNumber": { @@ -49467,12 +78783,16 @@ } ] }, + "assistantVersion": { + "type": "string", + "nullable": true, + "description": "This is the version label (e.g. `v3`) of the assistant the call was\nconfigured with. `null` for inline assistants, squad/workflow calls,\npre-resolution assistant-request messages, and orgs not on\nassistant versioning." + }, "type": { "type": "string", - "description": "This is the type of the message. \"transcript\" is sent as transcriber outputs partial or final transcript.", + "description": "This is the type of the message. \"chat.created\" is sent when a new chat is created.", "enum": [ - "transcript", - "transcript[transcriptType=\"final\"]" + "chat.created" ] }, "timestamp": { @@ -49512,57 +78832,20 @@ ] }, "chat": { - "description": "This is the chat object.", + "description": "This is the chat that was created.", "allOf": [ { "$ref": "#/components/schemas/Chat" } ] - }, - "role": { - "type": "string", - "description": "This is the role for which the transcript is for.", - "enum": [ - "assistant", - "user" - ] - }, - "transcriptType": { - "type": "string", - "description": "This is the type of the transcript.", - "enum": [ - "partial", - "final" - ] - }, - "transcript": { - "type": "string", - "description": "This is the transcript content." - }, - "isFiltered": { - "type": "boolean", - "description": "Indicates if the transcript was filtered for security reasons." - }, - "detectedThreats": { - "description": "List of detected security threats if the transcript was filtered.", - "type": "array", - "items": { - "type": "string" - } - }, - "originalTranscript": { - "type": "string", - "description": "The original transcript before filtering (only included if content was filtered)." } }, "required": [ "type", - "role", - "transcriptType", - "transcript" + "chat" ] }, - "ServerMessageUserInterrupted": { + "ServerMessageChatDeleted": { "type": "object", "properties": { "phoneNumber": { @@ -49590,11 +78873,16 @@ } ] }, + "assistantVersion": { + "type": "string", + "nullable": true, + "description": "This is the version label (e.g. `v3`) of the assistant the call was\nconfigured with. `null` for inline assistants, squad/workflow calls,\npre-resolution assistant-request messages, and orgs not on\nassistant versioning." + }, "type": { "type": "string", - "description": "This is the type of the message. \"user-interrupted\" is sent when the user interrupts the assistant.", + "description": "This is the type of the message. \"chat.deleted\" is sent when a chat is deleted.", "enum": [ - "user-interrupted" + "chat.deleted" ] }, "timestamp": { @@ -49634,7 +78922,7 @@ ] }, "chat": { - "description": "This is the chat object.", + "description": "This is the chat that was deleted.", "allOf": [ { "$ref": "#/components/schemas/Chat" @@ -49643,10 +78931,11 @@ } }, "required": [ - "type" + "type", + "chat" ] }, - "ServerMessageLanguageChangeDetected": { + "ServerMessageSessionCreated": { "type": "object", "properties": { "phoneNumber": { @@ -49674,11 +78963,16 @@ } ] }, + "assistantVersion": { + "type": "string", + "nullable": true, + "description": "This is the version label (e.g. `v3`) of the assistant the call was\nconfigured with. `null` for inline assistants, squad/workflow calls,\npre-resolution assistant-request messages, and orgs not on\nassistant versioning." + }, "type": { "type": "string", - "description": "This is the type of the message. \"language-change-detected\" is sent when the transcriber is automatically switched based on the detected language.", + "description": "This is the type of the message. \"session.created\" is sent when a new session is created.", "enum": [ - "language-change-detected" + "session.created" ] }, "timestamp": { @@ -49725,17 +79019,21 @@ } ] }, - "language": { - "type": "string", - "description": "This is the language the transcriber is switched to." + "session": { + "description": "This is the session that was created.", + "allOf": [ + { + "$ref": "#/components/schemas/Session" + } + ] } }, "required": [ "type", - "language" + "session" ] }, - "ServerMessageVoiceInput": { + "ServerMessageSessionUpdated": { "type": "object", "properties": { "phoneNumber": { @@ -49763,11 +79061,16 @@ } ] }, + "assistantVersion": { + "type": "string", + "nullable": true, + "description": "This is the version label (e.g. `v3`) of the assistant the call was\nconfigured with. `null` for inline assistants, squad/workflow calls,\npre-resolution assistant-request messages, and orgs not on\nassistant versioning." + }, "type": { "type": "string", - "description": "This is the type of the message. \"voice-input\" is sent when a generation is requested from voice provider.", + "description": "This is the type of the message. \"session.updated\" is sent when a session is updated.", "enum": [ - "voice-input" + "session.updated" ] }, "timestamp": { @@ -49814,17 +79117,21 @@ } ] }, - "input": { - "type": "string", - "description": "This is the voice input content" + "session": { + "description": "This is the session that was updated.", + "allOf": [ + { + "$ref": "#/components/schemas/Session" + } + ] } }, "required": [ "type", - "input" + "session" ] }, - "ServerMessageVoiceRequest": { + "ServerMessageSessionDeleted": { "type": "object", "properties": { "phoneNumber": { @@ -49852,11 +79159,16 @@ } ] }, + "assistantVersion": { + "type": "string", + "nullable": true, + "description": "This is the version label (e.g. `v3`) of the assistant the call was\nconfigured with. `null` for inline assistants, squad/workflow calls,\npre-resolution assistant-request messages, and orgs not on\nassistant versioning." + }, "type": { "type": "string", - "description": "This is the type of the message. \"voice-request\" is sent when using `assistant.voice={ \"type\": \"custom-voice\" }`.\n\nHere is what the request will look like:\n\nPOST https://{assistant.voice.server.url}\nContent-Type: application/json\n\n{\n \"messsage\": {\n \"type\": \"voice-request\",\n \"text\": \"Hello, world!\",\n \"sampleRate\": 24000,\n ...other metadata about the call...\n }\n}\n\nThe expected response is 1-channel 16-bit raw PCM audio at the sample rate specified in the request. Here is how the response will be piped to the transport:\n```\nresponse.on('data', (chunk: Buffer) => {\n outputStream.write(chunk);\n});\n```", + "description": "This is the type of the message. \"session.deleted\" is sent when a session is deleted.", "enum": [ - "voice-request" + "session.deleted" ] }, "timestamp": { @@ -49903,22 +79215,21 @@ } ] }, - "text": { - "type": "string", - "description": "This is the text to be synthesized." - }, - "sampleRate": { - "type": "number", - "description": "This is the sample rate to be synthesized." + "session": { + "description": "This is the session that was deleted.", + "allOf": [ + { + "$ref": "#/components/schemas/Session" + } + ] } }, "required": [ "type", - "text", - "sampleRate" + "session" ] }, - "ServerMessageCallEndpointingRequest": { + "ServerMessageCallDeleted": { "type": "object", "properties": { "phoneNumber": { @@ -49946,48 +79257,18 @@ } ] }, + "assistantVersion": { + "type": "string", + "nullable": true, + "description": "This is the version label (e.g. `v3`) of the assistant the call was\nconfigured with. `null` for inline assistants, squad/workflow calls,\npre-resolution assistant-request messages, and orgs not on\nassistant versioning." + }, "type": { "type": "string", - "description": "This is the type of the message. \"call.endpointing.request\" is sent when using `assistant.startSpeakingPlan.smartEndpointingPlan={ \"provider\": \"custom-endpointing-model\" }`.\n\nHere is what the request will look like:\n\nPOST https://{assistant.startSpeakingPlan.smartEndpointingPlan.server.url}\nContent-Type: application/json\n\n{\n \"message\": {\n \"type\": \"call.endpointing.request\",\n \"messages\": [\n {\n \"role\": \"user\",\n \"message\": \"Hello, how are you?\",\n \"time\": 1234567890,\n \"secondsFromStart\": 0\n }\n ],\n ...other metadata about the call...\n }\n}\n\nThe expected response:\n{\n \"timeoutSeconds\": 0.5\n}", + "description": "This is the type of the message. \"call.deleted\" is sent when a call is deleted.", "enum": [ - "call.endpointing.request" + "call.deleted" ] }, - "messages": { - "type": "array", - "description": "This is the conversation history at the time of the endpointing request.", - "items": { - "oneOf": [ - { - "$ref": "#/components/schemas/UserMessage", - "title": "UserMessage" - }, - { - "$ref": "#/components/schemas/SystemMessage", - "title": "SystemMessage" - }, - { - "$ref": "#/components/schemas/BotMessage", - "title": "BotMessage" - }, - { - "$ref": "#/components/schemas/ToolCallMessage", - "title": "ToolCallMessage" - }, - { - "$ref": "#/components/schemas/ToolCallResultMessage", - "title": "ToolCallResultMessage" - } - ] - } - }, - "messagesOpenAIFormatted": { - "description": "This is just `messages` formatted for OpenAI.", - "type": "array", - "items": { - "$ref": "#/components/schemas/OpenAIMessage" - } - }, "timestamp": { "type": "number", "description": "This is the timestamp of the message." @@ -50034,11 +79315,10 @@ } }, "required": [ - "type", - "messagesOpenAIFormatted" + "type" ] }, - "ServerMessageChatCreated": { + "ServerMessageCallDeleteFailed": { "type": "object", "properties": { "phoneNumber": { @@ -50066,11 +79346,16 @@ } ] }, + "assistantVersion": { + "type": "string", + "nullable": true, + "description": "This is the version label (e.g. `v3`) of the assistant the call was\nconfigured with. `null` for inline assistants, squad/workflow calls,\npre-resolution assistant-request messages, and orgs not on\nassistant versioning." + }, "type": { "type": "string", - "description": "This is the type of the message. \"chat.created\" is sent when a new chat is created.", + "description": "This is the type of the message. \"call.deleted\" is sent when a call is deleted.", "enum": [ - "chat.created" + "call.delete.failed" ] }, "timestamp": { @@ -50110,7 +79395,7 @@ ] }, "chat": { - "description": "This is the chat that was created.", + "description": "This is the chat object.", "allOf": [ { "$ref": "#/components/schemas/Chat" @@ -50119,96 +79404,36 @@ } }, "required": [ - "type", - "chat" + "type" ] }, - "ServerMessageChatDeleted": { + "CallArtifactUploadItem": { "type": "object", "properties": { - "phoneNumber": { - "description": "This is the phone number that the message is associated with.", - "oneOf": [ - { - "$ref": "#/components/schemas/CreateByoPhoneNumberDTO", - "title": "ByoPhoneNumber" - }, - { - "$ref": "#/components/schemas/CreateTwilioPhoneNumberDTO", - "title": "TwilioPhoneNumber" - }, - { - "$ref": "#/components/schemas/CreateVonagePhoneNumberDTO", - "title": "VonagePhoneNumber" - }, - { - "$ref": "#/components/schemas/CreateVapiPhoneNumberDTO", - "title": "VapiPhoneNumber" - }, - { - "$ref": "#/components/schemas/CreateTelnyxPhoneNumberDTO", - "title": "TelnyxPhoneNumber" - } - ] - }, "type": { "type": "string", - "description": "This is the type of the message. \"chat.deleted\" is sent when a chat is deleted.", + "description": "The artifact this result refers to.", "enum": [ - "chat.deleted" - ] - }, - "timestamp": { - "type": "number", - "description": "This is the timestamp of the message." - }, - "artifact": { - "description": "This is a live version of the `call.artifact`.\n\nThis matches what is stored on `call.artifact` after the call.", - "allOf": [ - { - "$ref": "#/components/schemas/Artifact" - } - ] - }, - "assistant": { - "description": "This is the assistant that the message is associated with.", - "allOf": [ - { - "$ref": "#/components/schemas/CreateAssistantDTO" - } - ] - }, - "customer": { - "description": "This is the customer that the message is associated with.", - "allOf": [ - { - "$ref": "#/components/schemas/CreateCustomerDTO" - } - ] - }, - "call": { - "description": "This is the call that the message is associated with.", - "allOf": [ - { - "$ref": "#/components/schemas/Call" - } + "end-of-call-report", + "recording-mono", + "recording-stereo", + "recording-assistant", + "recording-customer", + "log", + "pcap" ] }, - "chat": { - "description": "This is the chat that was deleted.", - "allOf": [ - { - "$ref": "#/components/schemas/Chat" - } - ] + "success": { + "type": "boolean", + "description": "Whether this artifact was stored successfully in your own configured storage." } }, "required": [ "type", - "chat" + "success" ] }, - "ServerMessageSessionCreated": { + "ServerMessageCallArtifactUpload": { "type": "object", "properties": { "phoneNumber": { @@ -50236,13 +79461,25 @@ } ] }, + "assistantVersion": { + "type": "string", + "nullable": true, + "description": "This is the version label (e.g. `v3`) of the assistant the call was\nconfigured with. `null` for inline assistants, squad/workflow calls,\npre-resolution assistant-request messages, and orgs not on\nassistant versioning." + }, "type": { "type": "string", - "description": "This is the type of the message. \"session.created\" is sent when a new session is created.", + "description": "This is the type of the message. \"call.artifact.upload\" is sent after a call\nto report whether each artifact was stored in your own configured storage.", "enum": [ - "session.created" + "call.artifact.upload" ] }, + "artifacts": { + "description": "One entry per artifact whose write targeted your own configured storage,\neach reporting whether that artifact was stored successfully. Artifacts that\nwere not destined for your own storage (Vapi default storage, or no storage\ncredential configured) are omitted, and this message is sent only when at\nleast one artifact targeted your own storage.", + "type": "array", + "items": { + "$ref": "#/components/schemas/CallArtifactUploadItem" + } + }, "timestamp": { "type": "number", "description": "This is the timestamp of the message." @@ -50286,115 +79523,62 @@ "$ref": "#/components/schemas/Chat" } ] - }, - "session": { - "description": "This is the session that was created.", - "allOf": [ - { - "$ref": "#/components/schemas/Session" - } - ] } }, "required": [ "type", - "session" + "artifacts" ] }, - "ServerMessageSessionUpdated": { + "CampaignContact": { "type": "object", "properties": { - "phoneNumber": { - "description": "This is the phone number that the message is associated with.", - "oneOf": [ - { - "$ref": "#/components/schemas/CreateByoPhoneNumberDTO", - "title": "ByoPhoneNumber" - }, - { - "$ref": "#/components/schemas/CreateTwilioPhoneNumberDTO", - "title": "TwilioPhoneNumber" - }, - { - "$ref": "#/components/schemas/CreateVonagePhoneNumberDTO", - "title": "VonagePhoneNumber" - }, - { - "$ref": "#/components/schemas/CreateVapiPhoneNumberDTO", - "title": "VapiPhoneNumber" - }, - { - "$ref": "#/components/schemas/CreateTelnyxPhoneNumberDTO", - "title": "TelnyxPhoneNumber" - } - ] + "id": { + "type": "string" }, - "type": { - "type": "string", - "description": "This is the type of the message. \"session.updated\" is sent when a session is updated.", - "enum": [ - "session.updated" - ] + "campaignId": { + "type": "string" }, - "timestamp": { - "type": "number", - "description": "This is the timestamp of the message." + "orgId": { + "type": "string" }, - "artifact": { - "description": "This is a live version of the `call.artifact`.\n\nThis matches what is stored on `call.artifact` after the call.", - "allOf": [ - { - "$ref": "#/components/schemas/Artifact" - } - ] + "customerId": { + "type": "string" }, - "assistant": { - "description": "This is the assistant that the message is associated with.", - "allOf": [ - { - "$ref": "#/components/schemas/CreateAssistantDTO" - } - ] + "number": { + "type": "string", + "minLength": 3, + "maxLength": 40 }, - "customer": { - "description": "This is the customer that the message is associated with.", - "allOf": [ - { - "$ref": "#/components/schemas/CreateCustomerDTO" - } - ] + "name": { + "type": "string", + "maxLength": 40 }, - "call": { - "description": "This is the call that the message is associated with.", - "allOf": [ - { - "$ref": "#/components/schemas/Call" - } - ] + "assistantOverrides": { + "$ref": "#/components/schemas/AssistantOverrides" }, - "chat": { - "description": "This is the chat object.", + "squadOverrides": { + "description": "Use this when the campaign targets a `squadId`. Mirrors the call-level `squadOverrides` field. Merged with the campaign-level squadOverrides at dispatch time.", "allOf": [ { - "$ref": "#/components/schemas/Chat" + "$ref": "#/components/schemas/AssistantOverrides" } ] }, - "session": { - "description": "This is the session that was updated.", - "allOf": [ - { - "$ref": "#/components/schemas/Session" - } - ] + "createdAt": { + "format": "date-time", + "type": "string" } }, "required": [ - "type", - "session" + "id", + "campaignId", + "orgId", + "number", + "createdAt" ] }, - "ServerMessageSessionDeleted": { + "ServerMessageCampaignPredial": { "type": "object", "properties": { "phoneNumber": { @@ -50422,11 +79606,28 @@ } ] }, + "assistantVersion": { + "type": "string", + "nullable": true, + "description": "This is the version label (e.g. `v3`) of the assistant the call was\nconfigured with. `null` for inline assistants, squad/workflow calls,\npre-resolution assistant-request messages, and orgs not on\nassistant versioning." + }, "type": { "type": "string", - "description": "This is the type of the message. \"session.deleted\" is sent when a session is deleted.", + "description": "This is the type of the message. \"campaign.predial\" is sent to the campaign's server before each contact is dialed, so the server can decide whether the contact is eligible to be called. It is only sent when the campaign's `predialPlan` is set (and not disabled).", "enum": [ - "session.deleted" + "campaign.predial" + ] + }, + "campaignId": { + "type": "string", + "description": "This is the ID of the campaign the contact belongs to." + }, + "contact": { + "description": "This is the contact that is about to be dialed.", + "allOf": [ + { + "$ref": "#/components/schemas/CampaignContact" + } ] }, "timestamp": { @@ -50472,19 +79673,12 @@ "$ref": "#/components/schemas/Chat" } ] - }, - "session": { - "description": "This is the session that was deleted.", - "allOf": [ - { - "$ref": "#/components/schemas/Session" - } - ] } }, "required": [ "type", - "session" + "campaignId", + "contact" ] }, "ServerMessage": { @@ -50505,6 +79699,10 @@ "$ref": "#/components/schemas/ServerMessageEndOfCallReport", "title": "EndOfCallReport" }, + { + "$ref": "#/components/schemas/ServerMessageHandoffDestinationRequest", + "title": "HandoffDestinationRequest" + }, { "$ref": "#/components/schemas/ServerMessageHang", "title": "Hang" @@ -50557,6 +79755,10 @@ "$ref": "#/components/schemas/ServerMessageVoiceInput", "title": "VoiceInput" }, + { + "$ref": "#/components/schemas/ServerMessageAssistantSpeech", + "title": "AssistantSpeech" + }, { "$ref": "#/components/schemas/ServerMessageVoiceRequest", "title": "VoiceRequest" @@ -50584,6 +79786,22 @@ { "$ref": "#/components/schemas/ServerMessageSessionDeleted", "title": "SessionDeleted" + }, + { + "$ref": "#/components/schemas/ServerMessageCallDeleted", + "title": "CallDeleted" + }, + { + "$ref": "#/components/schemas/ServerMessageCallDeleteFailed", + "title": "CallDeleteFailed" + }, + { + "$ref": "#/components/schemas/ServerMessageCallArtifactUpload", + "title": "CallArtifactUpload" + }, + { + "$ref": "#/components/schemas/ServerMessageCampaignPredial", + "title": "CampaignPredial" } ] } @@ -50640,6 +79858,14 @@ } ] }, + "squadOverrides": { + "description": "These are the overrides for the `squad` or `squadId`'s member settings and template variables.\nThis will apply to all members of the squad.", + "allOf": [ + { + "$ref": "#/components/schemas/AssistantOverrides" + } + ] + }, "workflowId": { "type": "string", "description": "This is the workflow that will be used for the call. To use a transient workflow, use `workflow` instead.\n\nTo start a call with:\n- Assistant, use `assistant` or `assistantId`\n- Squad, use `squad` or `squadId`\n- Workflow, use `workflow` or `workflowId`" @@ -50669,13 +79895,17 @@ "ServerMessageResponseHandoffDestinationRequest": { "type": "object", "properties": { + "result": { + "type": "string", + "description": "This is the local tool result message returned for the handoff tool call." + }, "destination": { - "description": "This is the destination you'd like the call to be transferred to.", - "allOf": [ - { - "$ref": "#/components/schemas/HandoffDestinationAssistant" - } - ] + "type": "object", + "description": "This is the destination you'd like the call to be transferred to." + }, + "error": { + "type": "string", + "description": "This is the error message if the handoff should not be made." } }, "required": [ @@ -50854,6 +80084,18 @@ "timeoutSeconds" ] }, + "ServerMessageResponseCampaignPredial": { + "type": "object", + "properties": { + "eligible": { + "type": "boolean", + "description": "This is whether the contact is eligible to be dialed. `true` places the call; `false` skips the contact. Any other response — a missing or non-boolean `eligible`, an unreachable server, an error, or a timeout — records a pre-dial failure for the contact and the call is not placed." + } + }, + "required": [ + "eligible" + ] + }, "ServerMessageResponse": { "type": "object", "properties": { @@ -50887,6 +80129,10 @@ { "$ref": "#/components/schemas/ServerMessageResponseCallEndpointingRequest", "title": "CallEndpointingRequest" + }, + { + "$ref": "#/components/schemas/ServerMessageResponseCampaignPredial", + "title": "CampaignPredial" } ] } @@ -50929,7 +80175,7 @@ "properties": { "type": { "type": "string", - "description": "This is the type of the message. Send \"control\" message to control the assistant. `control` options are:\n- \"mute-assistant\" - mute the assistant\n- \"unmute-assistant\" - unmute the assistant\n- \"say-first-message\" - say the first message (this is used when video recording is enabled and the conversation is only started once the client side kicks off the recording)", + "description": "This is the type of the message. Send \"control\" message to control the assistant. `control` options are:\n- \"mute-assistant\" - mute the assistant\n- \"unmute-assistant\" - unmute the assistant\n- \"mute-customer\" - mute the user\n- \"unmute-customer\" - unmute the user\n- \"say-first-message\" - say the first message (this is used when video recording is enabled and the conversation is only started once the client side kicks off the recording)", "enum": [ "control" ] @@ -50940,6 +80186,8 @@ "enum": [ "mute-assistant", "unmute-assistant", + "mute-customer", + "unmute-customer", "say-first-message" ] } @@ -51025,6 +80273,35 @@ "type" ] }, + "ClientInboundMessageSendTransportMessage": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "This is the type of the message. Send \"send-transport-message\" to send a transport-specific message during the call.", + "enum": [ + "send-transport-message" + ] + }, + "message": { + "description": "This is the transport-specific message to send.", + "oneOf": [ + { + "$ref": "#/components/schemas/VapiSipTransportMessage", + "title": "VapiSipTransportMessage" + }, + { + "$ref": "#/components/schemas/TwilioTransportMessage", + "title": "TwilioTransportMessage" + } + ] + } + }, + "required": [ + "type", + "message" + ] + }, "ClientInboundMessage": { "type": "object", "properties": { @@ -51050,6 +80327,10 @@ { "$ref": "#/components/schemas/ClientInboundMessageTransfer", "title": "Transfer" + }, + { + "$ref": "#/components/schemas/ClientInboundMessageSendTransportMessage", + "title": "SendTransportMessage" } ] } @@ -51058,386 +80339,6 @@ "message" ] }, - "BotMessage": { - "type": "object", - "properties": { - "role": { - "type": "string", - "description": "The role of the bot in the conversation." - }, - "message": { - "type": "string", - "description": "The message content from the bot." - }, - "time": { - "type": "number", - "description": "The timestamp when the message was sent." - }, - "endTime": { - "type": "number", - "description": "The timestamp when the message ended." - }, - "secondsFromStart": { - "type": "number", - "description": "The number of seconds from the start of the conversation." - }, - "source": { - "type": "string", - "description": "The source of the message." - }, - "duration": { - "type": "number", - "description": "The duration of the message in seconds." - } - }, - "required": [ - "role", - "message", - "time", - "endTime", - "secondsFromStart" - ] - }, - "ToolCallMessage": { - "type": "object", - "properties": { - "role": { - "type": "string", - "description": "The role of the tool call in the conversation." - }, - "toolCalls": { - "description": "The list of tool calls made during the conversation.", - "type": "array", - "items": { - "type": "object" - } - }, - "message": { - "type": "string", - "description": "The message content for the tool call." - }, - "time": { - "type": "number", - "description": "The timestamp when the message was sent." - }, - "secondsFromStart": { - "type": "number", - "description": "The number of seconds from the start of the conversation." - } - }, - "required": [ - "role", - "toolCalls", - "message", - "time", - "secondsFromStart" - ] - }, - "ToolCallResultMessage": { - "type": "object", - "properties": { - "role": { - "type": "string", - "description": "The role of the tool call result in the conversation." - }, - "toolCallId": { - "type": "string", - "description": "The ID of the tool call." - }, - "name": { - "type": "string", - "description": "The name of the tool that returned the result." - }, - "result": { - "type": "string", - "description": "The result of the tool call in JSON format." - }, - "time": { - "type": "number", - "description": "The timestamp when the message was sent." - }, - "secondsFromStart": { - "type": "number", - "description": "The number of seconds from the start of the conversation." - }, - "metadata": { - "type": "object", - "description": "The metadata for the tool call result." - } - }, - "required": [ - "role", - "toolCallId", - "name", - "result", - "time", - "secondsFromStart" - ] - }, - "TransportCost": { - "type": "object", - "properties": { - "type": { - "type": "string", - "description": "This is the type of cost, always 'transport' for this class.", - "enum": [ - "transport" - ] - }, - "provider": { - "type": "string", - "enum": [ - "twilio", - "vonage", - "vapi" - ] - }, - "minutes": { - "type": "number", - "description": "This is the minutes of `transport` usage. This should match `call.endedAt` - `call.startedAt`." - }, - "cost": { - "type": "number", - "description": "This is the cost of the component in USD." - } - }, - "required": [ - "type", - "minutes", - "cost" - ] - }, - "TranscriberCost": { - "type": "object", - "properties": { - "type": { - "type": "string", - "description": "This is the type of cost, always 'transcriber' for this class.", - "enum": [ - "transcriber" - ] - }, - "transcriber": { - "type": "object", - "description": "This is the transcriber that was used during the call.\n\nThis matches one of the below:\n- `call.assistant.transcriber`,\n- `call.assistantId->transcriber`,\n- `call.squad[n].assistant.transcriber`,\n- `call.squad[n].assistantId->transcriber`,\n- `call.squadId->[n].assistant.transcriber`,\n- `call.squadId->[n].assistantId->transcriber`." - }, - "minutes": { - "type": "number", - "description": "This is the minutes of `transcriber` usage. This should match `call.endedAt` - `call.startedAt` for single assistant calls, while squad calls will have multiple transcriber costs one for each assistant that was used." - }, - "cost": { - "type": "number", - "description": "This is the cost of the component in USD." - } - }, - "required": [ - "type", - "transcriber", - "minutes", - "cost" - ] - }, - "ModelCost": { - "type": "object", - "properties": { - "type": { - "type": "string", - "description": "This is the type of cost, always 'model' for this class.", - "enum": [ - "model" - ] - }, - "model": { - "type": "object", - "description": "This is the model that was used during the call.\n\nThis matches one of the following:\n- `call.assistant.model`,\n- `call.assistantId->model`,\n- `call.squad[n].assistant.model`,\n- `call.squad[n].assistantId->model`,\n- `call.squadId->[n].assistant.model`,\n- `call.squadId->[n].assistantId->model`." - }, - "promptTokens": { - "type": "number", - "description": "This is the number of prompt tokens used in the call. These should be total prompt tokens used in the call for single assistant calls, while squad calls will have multiple model costs one for each assistant that was used." - }, - "completionTokens": { - "type": "number", - "description": "This is the number of completion tokens generated in the call. These should be total completion tokens used in the call for single assistant calls, while squad calls will have multiple model costs one for each assistant that was used." - }, - "cost": { - "type": "number", - "description": "This is the cost of the component in USD." - } - }, - "required": [ - "type", - "model", - "promptTokens", - "completionTokens", - "cost" - ] - }, - "VoiceCost": { - "type": "object", - "properties": { - "type": { - "type": "string", - "description": "This is the type of cost, always 'voice' for this class.", - "enum": [ - "voice" - ] - }, - "voice": { - "type": "object", - "description": "This is the voice that was used during the call.\n\nThis matches one of the following:\n- `call.assistant.voice`,\n- `call.assistantId->voice`,\n- `call.squad[n].assistant.voice`,\n- `call.squad[n].assistantId->voice`,\n- `call.squadId->[n].assistant.voice`,\n- `call.squadId->[n].assistantId->voice`." - }, - "characters": { - "type": "number", - "description": "This is the number of characters that were generated during the call. These should be total characters used in the call for single assistant calls, while squad calls will have multiple voice costs one for each assistant that was used." - }, - "cost": { - "type": "number", - "description": "This is the cost of the component in USD." - } - }, - "required": [ - "type", - "voice", - "characters", - "cost" - ] - }, - "VapiCost": { - "type": "object", - "properties": { - "type": { - "type": "string", - "description": "This is the type of cost, always 'vapi' for this class.", - "enum": [ - "vapi" - ] - }, - "subType": { - "type": "string", - "description": "This is the sub type of the cost.", - "enum": [ - "normal", - "overage" - ] - }, - "minutes": { - "type": "number", - "description": "This is the minutes of Vapi usage. This should match `call.endedAt` - `call.startedAt`." - }, - "cost": { - "type": "number", - "description": "This is the cost of the component in USD." - } - }, - "required": [ - "type", - "subType", - "minutes", - "cost" - ] - }, - "AnalysisCost": { - "type": "object", - "properties": { - "type": { - "type": "string", - "description": "This is the type of cost, always 'analysis' for this class.", - "enum": [ - "analysis" - ] - }, - "analysisType": { - "type": "string", - "description": "This is the type of analysis performed.", - "enum": [ - "summary", - "structuredData", - "successEvaluation", - "structuredOutput" - ] - }, - "model": { - "type": "object", - "description": "This is the model that was used to perform the analysis." - }, - "promptTokens": { - "type": "number", - "description": "This is the number of prompt tokens used in the analysis." - }, - "completionTokens": { - "type": "number", - "description": "This is the number of completion tokens generated in the analysis." - }, - "cost": { - "type": "number", - "description": "This is the cost of the component in USD." - } - }, - "required": [ - "type", - "analysisType", - "model", - "promptTokens", - "completionTokens", - "cost" - ] - }, - "VoicemailDetectionCost": { - "type": "object", - "properties": { - "type": { - "type": "string", - "description": "This is the type of cost, always 'voicemail-detection' for this class.", - "enum": [ - "voicemail-detection" - ] - }, - "model": { - "type": "object", - "description": "This is the model that was used to perform the analysis." - }, - "provider": { - "type": "string", - "description": "This is the provider that was used to detect the voicemail.", - "enum": [ - "twilio", - "google", - "openai", - "vapi" - ] - }, - "promptTextTokens": { - "type": "number", - "description": "This is the number of prompt text tokens used in the voicemail detection." - }, - "promptAudioTokens": { - "type": "number", - "description": "This is the number of prompt audio tokens used in the voicemail detection." - }, - "completionTextTokens": { - "type": "number", - "description": "This is the number of completion text tokens used in the voicemail detection." - }, - "completionAudioTokens": { - "type": "number", - "description": "This is the number of completion audio tokens used in the voicemail detection." - }, - "cost": { - "type": "number", - "description": "This is the cost of the component in USD." - } - }, - "required": [ - "type", - "model", - "provider", - "promptTextTokens", - "promptAudioTokens", - "completionTextTokens", - "completionAudioTokens", - "cost" - ] - }, "KnowledgeBaseCost": { "type": "object", "properties": { @@ -51473,14 +80374,14 @@ "cost" ] }, - "ChatCost": { + "SessionCost": { "type": "object", "properties": { "type": { "type": "string", - "description": "This is the type of cost, always 'chat' for this class.", + "description": "This is the type of cost, always 'session' for this class.", "enum": [ - "chat" + "session" ] }, "cost": { @@ -51498,7 +80399,7 @@ "properties": { "messages": { "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", "items": { "oneOf": [ { @@ -51540,6 +80441,21 @@ } ] }, + "variableExtractionPlan": { + "description": "Plan to extract variables from the tool response", + "allOf": [ + { + "$ref": "#/components/schemas/VariableExtractionPlan" + } + ] + }, + "parameters": { + "description": "Static key-value pairs merged into the request body. Values support Liquid templates.", + "type": "array", + "items": { + "$ref": "#/components/schemas/ToolParameter" + } + }, "toolCall": { "$ref": "#/components/schemas/ToolCall" }, @@ -51570,7 +80486,7 @@ "properties": { "messages": { "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", "items": { "oneOf": [ { @@ -51625,7 +80541,7 @@ "properties": { "messages": { "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", "items": { "oneOf": [ { @@ -51680,7 +80596,7 @@ "properties": { "messages": { "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", "items": { "oneOf": [ { @@ -51756,7 +80672,7 @@ "properties": { "messages": { "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", "items": { "oneOf": [ { @@ -51846,7 +80762,7 @@ "properties": { "messages": { "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", "items": { "oneOf": [ { @@ -51922,7 +80838,7 @@ "properties": { "messages": { "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", "items": { "oneOf": [ { @@ -51973,7 +80889,7 @@ "properties": { "messages": { "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", "items": { "oneOf": [ { @@ -52024,7 +80940,7 @@ "properties": { "messages": { "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", "items": { "oneOf": [ { @@ -52075,7 +80991,7 @@ "properties": { "messages": { "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", "items": { "oneOf": [ { @@ -52126,7 +81042,7 @@ "properties": { "messages": { "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", "items": { "oneOf": [ { @@ -52177,7 +81093,7 @@ "properties": { "messages": { "type": "array", - "description": "These are the messages that will be spoken to the user as the tool is running.\n\nFor some tools, this is auto-filled based on special fields like `tool.destinations`. For others like the function tool, these can be custom configured.", + "description": "Messages spoken while the tool is running. Multiple request-start messages are variants. For request-response-delayed, same timing means variants and different timings mean staged updates.", "items": { "oneOf": [ { @@ -52222,6 +81138,59 @@ "type", "toolCall" ] + }, + "VapiSipTransportMessage": { + "type": "object", + "properties": { + "transport": { + "type": "string", + "description": "This is the transport type.", + "enum": [ + "vapi.sip" + ] + }, + "sipVerb": { + "type": "string", + "description": "This is the SIP verb to use. Must be one of INFO, MESSAGE, or NOTIFY.", + "enum": [ + "INFO", + "MESSAGE", + "NOTIFY" + ] + }, + "headers": { + "type": "object", + "description": "These are the headers to include with the SIP request." + }, + "body": { + "type": "string", + "description": "This is the body of the SIP request, if any." + } + }, + "required": [ + "transport", + "sipVerb" + ] + }, + "TwilioTransportMessage": { + "type": "object", + "properties": { + "transport": { + "type": "string", + "description": "This is the transport type.", + "enum": [ + "twilio" + ] + }, + "twiml": { + "type": "string", + "description": "This is the TwiML to send to the Twilio call." + } + }, + "required": [ + "transport", + "twiml" + ] } } } diff --git a/fern/apis/webhooks/ai_examples_override.yml b/fern/apis/webhooks/ai_examples_override.yml new file mode 100644 index 000000000..059f40b1a --- /dev/null +++ b/fern/apis/webhooks/ai_examples_override.yml @@ -0,0 +1,16 @@ +paths: + /client: + post: + x-fern-examples: + - request: + message: + type: workflow.node.started + node: {} + response: + body: + message: + type: add-message + message: + content: Hello! How can I assist you with your workflow today? + role: assistant + triggerResponseEnabled: true diff --git a/fern/apis/webhooks/generators.yml b/fern/apis/webhooks/generators.yml index 3741feeea..66ae0f0d6 100644 --- a/fern/apis/webhooks/generators.yml +++ b/fern/apis/webhooks/generators.yml @@ -1,4 +1,6 @@ api: - specs: + specs: - openapi: ./openapi.yml overrides: ./openapi-overrides.yml + settings: + coerce-enums-to-literals: true diff --git a/fern/apis/webhooks/openapi-overrides.yml b/fern/apis/webhooks/openapi-overrides.yml index 8f9aca57c..047e8aed6 100644 --- a/fern/apis/webhooks/openapi-overrides.yml +++ b/fern/apis/webhooks/openapi-overrides.yml @@ -246,6 +246,14 @@ components: name: Asterisk "#": name: Hash + items: + x-fern-enum: + "": + name: Empty + "*": + name: Asterisk + "#": + name: Hash TransferDestinationAssistant: properties: transferMode: diff --git a/fern/assets/styles.css b/fern/assets/styles.css index 9cf81a30c..605bd6104 100644 --- a/fern/assets/styles.css +++ b/fern/assets/styles.css @@ -31,6 +31,21 @@ border: 1px solid #C7D2FE; } +/* Optional: Squad badge (reuse assistant palette for now) */ +.vapi-badge-squad { + background-color: #EEF2FF; + color: #4338CA; + border: 1px solid #C7D2FE; +} + +/* Alpha badge - purple to match dashboard */ +.vapi-badge-alpha { + background-color: rgba(168, 85, 247, 0.2) !important; + color: #A78BFA !important; + border: 1px solid rgba(168, 85, 247, 0.4) !important; + border-color: rgba(168, 85, 247, 0.4) !important; +} + /* Dark mode adjustments */ :is(.dark) .vapi-badge-assistant { background-color: #134E4A; @@ -44,6 +59,48 @@ border: 1px solid #6366F1; } +:is(.dark) .vapi-badge-squad { + background-color: #312E81; + color: #C7D2FE; + border: 1px solid #6366F1; +} + +:is(.dark) .vapi-badge-alpha { + background-color: rgba(168, 85, 247, 0.2) !important; + color: #C4B5FD !important; + border: 1px solid rgba(168, 85, 247, 0.4) !important; + border-color: rgba(168, 85, 247, 0.4) !important; +} + +/* Override Fern's pre-release availability badge to show "Alpha" with purple styling */ +.fern-docs-badge[title="Pre-release"] { + background-color: rgba(168, 85, 247, 0.2) !important; + border-color: rgba(168, 85, 247, 0.4) !important; + font-size: 0 !important; + position: relative !important; + min-width: 52px !important; + min-height: 24px !important; + display: inline-flex !important; +} + +.fern-docs-badge[title="Pre-release"]::after { + content: "Alpha"; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + color: #A78BFA; + font-size: 0.75rem; + line-height: 1; + white-space: nowrap; +} + +:is(.dark) .fern-docs-badge[title="Pre-release"] { + background-color: rgba(168, 85, 247, 0.2) !important; + color: #C4B5FD !important; + border-color: rgba(168, 85, 247, 0.4) !important; +} + /* for a grid of videos */ .video-grid { @@ -221,3 +278,109 @@ html.dark button[data-highlighted] .fern-api-property-meta { .light .fern-theme-default.fern-container { background-color: #fff !important; } + +/* Fix: Make subtitle white on Simulations pages in dark mode */ +:is(.dark) [id*="simulations"] .prose-p\:text-\(color\:--grayscale-a11\) :where(p):not(:where([class~=not-prose],[class~=not-prose] *)) { + color: var(--grayscale-12) !important; +} + +/* Subscribe form on What's New page */ +.subscribe-form-row { + display: flex; + gap: 0.5rem; +} + +.subscribe-form-input { + border: 1px solid #e2e8f0; + border-radius: 0.375rem; + padding: 0.5rem 1rem; + width: 100%; + font-size: 0.875rem; + outline: none; + transition: border-color 0.2s ease-in-out; + color: #1f2937; + background-color: #fff; +} + +.subscribe-form-input:focus { + border-color: #4f46e5; + box-shadow: 0 0 0 1px #4f46e5; +} + +.subscribe-form-button { + background-color: #37aa9d; + color: white; + font-weight: 500; + padding: 0.5rem 1rem; + border-radius: 0.375rem; + border: none; + cursor: pointer; + transition: all 0.2s ease-in-out; + white-space: nowrap; +} + +.subscribe-form-button:hover { + background-color: #2e8b7d; + transform: translateY(-1px); +} + +.subscribe-form-button:active { + transform: translateY(0); +} + +.subscribe-form-button:disabled { + opacity: 0.7; + cursor: not-allowed; + transform: none; +} + +.subscribe-form-message { + margin-top: 0.5rem; + font-size: 0.875rem; + padding: 0.5rem 0.75rem; + border-radius: 0.375rem; +} + +.subscribe-form-message.success { + color: #065f46; + background-color: #d1fae5; +} + +.subscribe-form-message.error { + color: #991b1b; + background-color: #fee2e2; +} + +:is(.dark) .subscribe-form-input { + background-color: #374151; + border-color: #4b5563; + color: #f3f4f6; +} + +:is(.dark) .subscribe-form-input::placeholder { + color: #9ca3af; +} + +:is(.dark) .subscribe-form-input:focus { + border-color: #6366f1; + box-shadow: 0 0 0 1px #6366f1; +} + +:is(.dark) .subscribe-form-button { + background-color: #94ffd2; + color: #1f2937; +} + +:is(.dark) .subscribe-form-button:hover { + background-color: #7cd9b0; +} + +:is(.dark) .subscribe-form-message.success { + color: #a7f3d0; + background-color: #064e3b; +} + +:is(.dark) .subscribe-form-message.error { + color: #fca5a5; + background-color: #7f1d1d; +} \ No newline at end of file diff --git a/fern/assistants/assistant-hooks.mdx b/fern/assistants/assistant-hooks.mdx index 54760f4e1..7657f2e3c 100644 --- a/fern/assistants/assistant-hooks.mdx +++ b/fern/assistants/assistant-hooks.mdx @@ -11,9 +11,11 @@ Assistant hooks let you automate actions when specific events occur during a cal Supported events include: - `call.ending`: When a call is ending +- `call.timeElapsed`: When a specified number of seconds has elapsed from call start - `assistant.speech.interrupted`: When the assistant's speech is interrupted - `customer.speech.interrupted`: When the customer's speech is interrupted - `customer.speech.timeout`: When the customer doesn't speak within a specified time +- `assistant.transcriber.endpointedSpeechLowConfidence`: When a final transcript has low confidence (below threshold but within configurable range) You can combine actions and add filters to control when hooks trigger. Multiple `customer.speech.timeout` hooks can be attached to an assistant with staggered trigger delay to support different actions at different timing in the conversation. @@ -24,16 +26,17 @@ Hooks are defined in the `hooks` array of your assistant configuration. Each hoo - `on`: The event that triggers the hook - `do`: The actions to perform (supports `tool` and `say`) - `filters`: (Optional) Conditions that must be met for the hook to trigger -- `options`: (Optional) Configuration options for certain hook types like `customer.speech.timeout` +- `options`: (Optional) Configuration options for certain hook types like `call.timeElapsed`, `customer.speech.timeout`, and `assistant.transcriber.endpointedSpeechLowConfidence` - `name`: (Optional) Custom name to identify the hook **Action Types:** + - `say`: Speak a message. Use `exact` for predetermined text or `prompt` for AI-generated responses - `tool`: Execute a tool like `transferCall`, `function`, `endCall`, etc. The `call.endedReason` filter can be set to any of the [call ended reasons](/api-reference/calls/get#response.body.endedReason). -The transfer destination type follows the [transfer call tool destinations](/api-reference/tools/create#request.body.transferCall.destinations) schema. +The transfer destination type follows the destinations described in the [transfer call tool guide](/tools/transfer-call#choose-a-destination). See the [Create Tool API reference](/api-reference/tools/create) for the complete tool schema. ## Example: Transfer on pipeline error @@ -42,25 +45,33 @@ Transfer a call to a fallback number if a pipeline error occurs: ```json { - "hooks": [{ - "on": "call.ending", - "filters": [{ - "type": "oneOf", - "key": "call.endedReason", - "oneOf": ["pipeline-error"] - }], - "do": [{ - "type": "tool", - "tool": { - "type": "transferCall", - "destinations": [{ - "type": "number", - "number": "+1234567890", - "callerId": "+1987654321" - }] - } - }] - }] + "hooks": [ + { + "on": "call.ending", + "filters": [ + { + "type": "oneOf", + "key": "call.endedReason", + "oneOf": ["pipeline-error"] + } + ], + "do": [ + { + "type": "tool", + "tool": { + "type": "transferCall", + "destinations": [ + { + "type": "number", + "number": "+1234567890", + "callerId": "+1987654321" + } + ] + } + } + ] + } + ] } ``` @@ -68,24 +79,32 @@ You can also transfer to a SIP destination: ```json { - "hooks": [{ - "on": "call.ending", - "filters": [{ - "type": "oneOf", - "key": "call.endedReason", - "oneOf": ["pipeline-error"] - }], - "do": [{ - "type": "tool", - "tool": { - "type": "transferCall", - "destinations": [{ - "type": "sip", - "sipUri": "sip:user@domain.com" - }] - } - }] - }] + "hooks": [ + { + "on": "call.ending", + "filters": [ + { + "type": "oneOf", + "key": "call.endedReason", + "oneOf": ["pipeline-error"] + } + ], + "do": [ + { + "type": "tool", + "tool": { + "type": "transferCall", + "destinations": [ + { + "type": "sip", + "sipUri": "sip:user@domain.com" + } + ] + } + } + ] + } + ] } ``` @@ -95,57 +114,63 @@ Perform multiple actions—say a message, call a function, and transfer the call ```json { - "hooks": [{ - "on": "call.ending", - "filters": [{ - "type": "oneOf", - "key": "call.endedReason", - "oneOf": ["pipeline-error"] - }], - "do": [ - { - "type": "say", - "exact": "I apologize for the technical difficulty. Let me transfer you to our support team." - }, - { - "type": "tool", - "tool": { - "type": "function", - "function": { - "name": "log_error", - "parameters": { - "type": "object", - "properties": { - "error_type": { - "type": "string", - "value": "pipeline_error" + "hooks": [ + { + "on": "call.ending", + "filters": [ + { + "type": "oneOf", + "key": "call.endedReason", + "oneOf": ["pipeline-error"] + } + ], + "do": [ + { + "type": "say", + "exact": "I apologize for the technical difficulty. Let me transfer you to our support team." + }, + { + "type": "tool", + "tool": { + "type": "function", + "function": { + "name": "log_error", + "parameters": { + "type": "object", + "properties": { + "error_type": { + "type": "string", + "value": "pipeline_error" + } } - } + }, + "description": "Logs the error details for monitoring" }, - "description": "Logs the error details for monitoring" - }, - "async": true, - "server": { - "url": "https://your-server.com/api" + "async": true, + "server": { + "url": "https://your-server.com/api" + } + } + }, + { + "type": "tool", + "tool": { + "type": "transferCall", + "destinations": [ + { + "type": "number", + "number": "+1234567890", + "callerId": "+1987654321" + } + ] } } - }, - { - "type": "tool", - "tool": { - "type": "transferCall", - "destinations": [{ - "type": "number", - "number": "+1234567890", - "callerId": "+1987654321" - }] - } - } - ] - }] + ] + } + ] } ``` - + Use `"oneOf": ["pipeline-error"]` as a catch-all filter for any pipeline-related error reason. @@ -156,13 +181,17 @@ Respond when the assistant's speech is interrupted by the customer: ```json { - "hooks": [{ - "on": "assistant.speech.interrupted", - "do": [{ - "type": "say", - "exact": ["Sorry about that", "Go ahead", "Please continue"] - }] - }] + "hooks": [ + { + "on": "assistant.speech.interrupted", + "do": [ + { + "type": "say", + "exact": ["Sorry about that", "Go ahead", "Please continue"] + } + ] + } + ] } ``` @@ -170,13 +199,17 @@ Handle customer speech interruptions in a similar way: ```json { - "hooks": [{ - "on": "customer.speech.interrupted", - "do": [{ - "type": "say", - "exact": "I apologize for interrupting. Please continue." - }] - }] + "hooks": [ + { + "on": "customer.speech.interrupted", + "do": [ + { + "type": "say", + "exact": "I apologize for interrupting. Please continue." + } + ] + } + ] } ``` @@ -186,19 +219,23 @@ Respond when the customer doesn't speak within a specified time: ```json { - "hooks": [{ - "on": "customer.speech.timeout", - "options": { - "timeoutSeconds": 10, - "triggerMaxCount": 2, - "triggerResetMode": "onUserSpeech" - }, - "do": [{ - "type": "say", - "prompt": "Are you still there? Please let me know how I can help you." - }], - "name": "customer_timeout_check" - }] + "hooks": [ + { + "on": "customer.speech.timeout", + "options": { + "timeoutSeconds": 10, + "triggerMaxCount": 2, + "triggerResetMode": "onUserSpeech" + }, + "do": [ + { + "type": "say", + "prompt": "Are you still there? Please let me know how I can help you." + } + ], + "name": "customer_timeout_check" + } + ] } ``` @@ -209,9 +246,283 @@ The `customer.speech.timeout` hook supports special options: - `triggerResetMode`: Whether to reset the trigger count when user speaks (default: "never") +## Example: Trigger actions at a specific time + +The `call.timeElapsed` hook fires once when a specified number of seconds has elapsed from call start. Use it to enforce call duration limits, prompt wrap-up behavior, or trigger time-based actions. + +Each `call.timeElapsed` hook fires **once** at the specified time. To trigger actions at multiple time points, add separate hooks with different `seconds` values. + +### Basic usage + +Speak a message 5 minutes into the call: + +```json +{ + "hooks": [ + { + "on": "call.timeElapsed", + "options": { + "seconds": 300 + }, + "do": [ + { + "type": "say", + "exact": "Just a heads up, we've been on the call for 5 minutes." + } + ] + } + ] +} +``` + +### Call discipline (wrap-up and graceful close) + +Combine multiple `call.timeElapsed` hooks with `maxDurationSeconds` to enforce structured call discipline. This example begins wrapping up at 8 minutes, warns at 9 minutes, and hard-cuts at 10 minutes: + +```json +{ + "maxDurationSeconds": 600, + "hooks": [ + { + "on": "call.timeElapsed", + "options": { + "seconds": 480 + }, + "do": [ + { + "type": "say", + "exact": "We're approaching our time limit. Let's start wrapping up." + } + ] + }, + { + "on": "call.timeElapsed", + "options": { + "seconds": 540 + }, + "do": [ + { + "type": "say", + "exact": "We have about one minute left. Let me know if there's anything else urgent." + } + ] + }, + { + "on": "call.timeElapsed", + "options": { + "seconds": 590 + }, + "do": [ + { + "type": "say", + "exact": "Thank you for your time. I need to end the call now. Goodbye." + }, + { + "type": "tool", + "tool": { + "type": "endCall" + } + } + ] + } + ] +} +``` + + +The `call.timeElapsed` hook supports one option: +- `seconds`: Number of seconds from call start when the hook should trigger (1-3600) + +The hook fires once at the specified time. `maxDurationSeconds` (default: 600 seconds) acts as a hard cutoff that ends the call immediately. Use `call.timeElapsed` hooks before that limit to allow for a graceful close. + + +### Inject a system message to guide the LLM + +Instead of speaking a fixed message, you can inject a system message into the conversation to change the LLM's behavior for the remainder of the call: + +```json +{ + "hooks": [ + { + "on": "call.timeElapsed", + "options": { + "seconds": 480 + }, + "do": [ + { + "type": "message.add", + "message": { + "role": "system", + "content": "The call has been going on for 8 minutes. Begin wrapping up the conversation. Summarize any action items and ask if there is anything else before ending the call." + } + } + ] + } + ] +} +``` + +## Example: Handle low confidence transcripts + +When a transcriber produces a final transcript with low confidence (below the set confidence threshold or default of 0.4), it's normally discarded. The `assistant.transcriber.endpointedSpeechLowConfidence` hook allows you to handle these borderline cases by triggering actions like asking the user to repeat or logging the event. + +This hook only triggers for **final/endpointed transcripts** that fall within a configurable confidence range. Transcripts with confidence at or above the threshold are processed normally, while those below the minimum range are still discarded. + +### Basic usage + +Ask the user to repeat when a transcript has low confidence: + +```json +{ + "hooks": [ + { + "on": "assistant.transcriber.endpointedSpeechLowConfidence", + "do": [ + { + "type": "say", + "exact": "I'm sorry, I didn't quite catch that. Could you please repeat?" + } + ] + } + ] +} +``` + +### Using confidence options + +Configure a specific confidence range for when the hook should trigger: + +```json +{ + "hooks": [ + { + "on": "assistant.transcriber.endpointedSpeechLowConfidence", + "options": { + "confidenceMin": 0.2, + "confidenceMax": 0.4 + }, + "do": [ + { + "type": "say", + "prompt": "You are having trouble understanding or properly hearing what the user is saying. Based on the conversation in {{transcript}}, ask the user to repeat what they just said." + } + ] + } + ] +} +``` + +### Shorthand syntax + +You can use shorthand syntax similar to `customer.speech.timeout` hooks. The shorthand format is `[confidence=min:max]` where both min and max are optional: + +**Set both min and max:** + +```json +{ + "hooks": [ + { + "on": "assistant.transcriber.endpointedSpeechLowConfidence[confidence=0.2:0.4]", + "do": [ + { + "type": "say", + "exact": "Could you please repeat that?" + } + ] + } + ] +} +``` + +**Set only minimum (max defaults to transcriber's confidence threshold):** + +```json +{ + "hooks": [ + { + "on": "assistant.transcriber.endpointedSpeechLowConfidence[confidence=0.2:]", + "do": [ + { + "type": "say", + "exact": "I didn't catch that clearly. Could you repeat?" + } + ] + } + ] +} +``` + +**Set only maximum (min defaults to max - 0.2):** + +```json +{ + "hooks": [ + { + "on": "assistant.transcriber.endpointedSpeechLowConfidence[confidence=:0.4]", + "do": [ + { + "type": "say", + "exact": "Could you please speak a bit more clearly?" + } + ] + } + ] +} +``` + +### Default behavior + +When no options are specified, the hook uses these defaults: + +- `confidenceMax`: Uses the transcriber's `confidenceThreshold` (typically 0.4) +- `confidenceMin`: `confidenceMax - 0.2` (minimum 0) + +For example, if your transcriber has a `confidenceThreshold` of 0.4: + +- Transcripts with confidence ≥ 0.4: Processed normally +- Transcripts with confidence 0.2-0.4: Hook triggers +- Transcripts with confidence < 0.2: Discarded + +### Multiple hooks for different ranges + +You can configure multiple hooks to handle different confidence ranges with different actions: + +```json +{ + "hooks": [ + { + "on": "assistant.transcriber.endpointedSpeechLowConfidence[confidence=0.3:0.4]", + "do": [ + { + "type": "say", + "exact": "I'm having a bit of trouble hearing you. Could you speak a bit louder?" + } + ] + }, + { + "on": "assistant.transcriber.endpointedSpeechLowConfidence[confidence=0.2:0.3]", + "do": [ + { + "type": "say", + "exact": "I'm sorry, I really couldn't understand that. Could you please repeat what you said?" + } + ] + } + ] +} +``` + + +The `assistant.transcriber.endpointedSpeechLowConfidence` hook supports these options: +- `confidenceMin`: Minimum confidence threshold (0-1, default: confidenceMax - 0.2) +- `confidenceMax`: Maximum confidence threshold (0-1, default: transcriber's confidenceThreshold) + +This hook is supported for transcribers that have `confidenceThreshold` configuration: Deepgram, Gladia, and AssemblyAI. + + ## Example: End call if user hasn't spoken for 30s -Assistant checks with the user at the 10 and 20s mark from when the user is silent, and ends the call after 30s of silence. +Assistant checks with the user at the 10 and 20s mark from when the user is silent, and ends the call after 30s of silence. ```json { @@ -259,8 +570,8 @@ Assistant checks with the user at the 10 and 20s mark from when the user is sile }, "do": [ { - "type" : "say", - "exact" : "I'll be ending the call now, please feel free to call back at any time." + "type": "say", + "exact": "I'll be ending the call now, please feel free to call back at any time." }, { "type": "tool", @@ -276,16 +587,17 @@ Assistant checks with the user at the 10 and 20s mark from when the user is sile } ``` - ## Common use cases - Transfer to a human agent on errors - Route to a fallback system if the assistant fails - Handle customer or assistant interruptions gracefully - Prompt customers who become unresponsive during a call +- Enforce call duration limits with graceful wrap-up behavior +- Handle low confidence transcripts by asking users to repeat or speak more clearly - Log errors or events for monitoring -## Slack Webhook on Call Failure +## Slack Webhook on Call Failure You can set up automatic Slack notifications when calls fail by combining assistant hooks with Slack webhooks. This is useful for monitoring call quality and getting immediate alerts when issues occur. @@ -307,10 +619,10 @@ export default async function(req: Request): Promise { try { const json = await req.json(); console.log(json); - + const callId = json.message.call.id; const reason = json.message.toolCalls[0].function.arguments.properties.callEndedReason.value; - + fetch("", { "method": "POST", "headers": { @@ -320,11 +632,11 @@ export default async function(req: Request): Promise { text: `🚨 Call Failed\nCall ID: ${callId}\nReason: ${reason}` }), }); - + return Response.json({ - results: [{ - "result": "success", - "toolCallId": "hook-function-call" + results: [{ + "result": "success", + "toolCallId": "hook-function-call" }], }); } catch (err) { @@ -340,37 +652,43 @@ Add this hook configuration to your assistant to trigger Slack notifications on ```json { - "hooks": [{ - "on": "call.ending", - "filters": [{ - "type": "oneOf", - "key": "call.endedReason", - "oneOf": ["pipeline-error"] - }], - "do": [{ - "type": "tool", - "tool": { - "type": "function", - "function": { - "name": "report_error", - "parameters": { - "type": "object", - "properties": { - "text": { - "type": "string", - "value": "A call error occurred." - } + "hooks": [ + { + "on": "call.ending", + "filters": [ + { + "type": "oneOf", + "key": "call.endedReason", + "oneOf": ["pipeline-error"] + } + ], + "do": [ + { + "type": "tool", + "tool": { + "type": "function", + "function": { + "name": "report_error", + "parameters": { + "type": "object", + "properties": { + "text": { + "type": "string", + "value": "A call error occurred." + } + } + }, + "description": "Reports a call error to Slack." + }, + "async": false, + "server": { + "url": "" } - }, - "description": "Reports a call error to Slack." - }, - "async": false, - "server": { - "url": "" + } } - } - }] - }] + ] + } + ] } ``` diff --git a/fern/assistants/call-analysis.mdx b/fern/assistants/call-analysis.mdx index 8586156e9..347470146 100644 --- a/fern/assistants/call-analysis.mdx +++ b/fern/assistants/call-analysis.mdx @@ -6,13 +6,68 @@ slug: assistants/call-analysis ## Overview -Call analysis automatically summarizes and evaluates every call for insights and quality control. As soon as a call ends, analysis is triggered in the background and typically completes within a few seconds. The system uses the latest version of Anthropic's Claude Sonnet (with OpenAI GPT-4o as fallback) to: +Call analysis automatically summarizes and evaluates every call for insights and quality control. As soon as a call ends, analysis is triggered in the background and typically completes within a few seconds. The system uses a large language model to: - Summarize the call - Extract structured data - Evaluate call success Results are attached to the call record and can be viewed in the call instance dashboard or retrieved via the API. You can customize the analysis using prompts and schemas in your assistant's `analysisPlan`. +## Recommended: use structured outputs + +We recommend [structured outputs](/assistants/structured-outputs) over the `analysisPlan` for extracting data, summaries, and evaluations from your calls. They are more flexible and are where new development happens. + +The `analysisPlan` configuration described later on this page still works and remains available for existing setups. If you're configuring call analysis for the first time, start with structured outputs. + +## Extracting structured outputs + +A structured output is a reusable definition you create once and attach to an assistant. After each call, Vapi runs it against the conversation and stores the result in `call.artifact.structuredOutputs`. + +To extract structured outputs: + +1. **Create a structured output** with a JSON schema describing what to extract. +2. **Link it to an assistant** through `artifactPlan.structuredOutputIds`. +3. **Read the results** from `call.artifact.structuredOutputs` after the call ends. + +```bash title="Create a structured output" +curl -X POST https://api.vapi.ai/structured-output \ + -H "Authorization: Bearer $VAPI_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "name": "Customer Info", + "type": "ai", + "description": "Extract customer contact information", + "schema": { + "type": "object", + "properties": { + "firstName": { "type": "string", "description": "Customer'\''s first name" }, + "email": { "type": "string", "format": "email", "description": "Customer'\''s email address" } + }, + "required": ["firstName"] + } + }' +``` + +```json title="Link it to an assistant" +{ + "artifactPlan": { + "structuredOutputIds": [""] + } +} +``` + +For the complete walkthrough, see the [structured outputs quickstart](/assistants/structured-outputs-quickstart). For every field and schema option, see the [structured outputs reference](/assistants/structured-outputs). + +## Coming from analysisPlan? + +Each part of the `analysisPlan` has a structured outputs equivalent: + +| `analysisPlan` (stored in `call.analysis`) | Structured outputs equivalent (stored in `call.artifact.structuredOutputs`) | +| --- | --- | +| `summaryPlan` → `summary` | A structured output that summarizes the call | +| `structuredDataPlan` → `structuredData` | A structured output with your JSON schema | +| `successEvaluationPlan` → `successEvaluation` | A structured output that evaluates the call, or a [scorecard](/observability/scorecard-quickstart) | + ## Customization You can customize the following properties in your assistant's `analysisPlan`: diff --git a/fern/assistants/call-recording.mdx b/fern/assistants/call-recording.mdx index 16c215360..797943654 100644 --- a/fern/assistants/call-recording.mdx +++ b/fern/assistants/call-recording.mdx @@ -1,31 +1,168 @@ --- -title: Call recording -subtitle: Record and store calls for analysis and training +title: Call recording, logging and transcribing +subtitle: Record, log, and transcribe calls using artifact plans slug: assistants/call-recording -description: Learn how to record calls and store them for quality assurance and analysis +description: Learn how to configure artifact plans to record calls, generate transcripts, and store logs for analysis --- + + **Deprecated**: The old `recordingEnabled`, `recordingPath`, and `recordingCredentials` properties are deprecated. Use the new `artifactPlan` configuration instead for recording, logging, and transcript generation. + + ## Overview -Vapi provides comprehensive call recording capabilities that allow you to capture, store, and analyze voice conversations for quality assurance, training, and compliance purposes. +Vapi's artifact plan system provides comprehensive call recording, logging, and transcription capabilities that allow you to capture, store, and analyze voice conversations for quality assurance, training, and compliance purposes. -**Call recording enables you to:** +**Artifact plans enable you to:** +- Record audio conversations for quality monitoring +- Generate detailed call logs for debugging and analysis +- Create transcripts for conversation analysis +- Store artifacts in custom storage or Vapi's secure cloud - Monitor conversation quality and assistant performance -- Train and improve your voice AI models - Ensure compliance with regulatory requirements -- Analyze customer interactions for insights -## Recording Configuration +## Use Cases + +### Payment Processing Flows + +Protect sensitive payment information by using a middle assistant with all artifacts disabled: + +```json +{ + "squad": { + "members": [ + { + "assistant": { + "name": "Service Assistant", + "artifactPlan": { + "recordingEnabled": true, + "loggingEnabled": true, + "transcriptPlan": { "enabled": true } + } + } + }, + { + "assistant": { + "name": "Payment Assistant", + "artifactPlan": { + "recordingEnabled": false, + "loggingEnabled": false, + "transcriptPlan": { "enabled": false } + } + } + }, + { + "assistant": { + "name": "Confirmation Assistant", + "artifactPlan": { + "recordingEnabled": true, + "loggingEnabled": true, + "transcriptPlan": { "enabled": true } + } + } + } + ] + } +} +``` + +This flow ensures that: +- Service conversations are recorded for quality assurance +- Payment details (credit card numbers, CVV codes) are never recorded or logged +- Confirmation conversations are recorded for compliance + +### Consent Gathering + +For Enterprise customers, Vapi provides built-in [recording consent plans](/security-and-privacy/recording-consent-plan) that automatically create a consent assistant to request recording permission before transferring to your main assistant. + +The Enterprise consent feature supports both: +- **Verbal consent**: Requires explicit "yes" confirmation from users +- **Implicit consent**: Assumes consent if users stay on the line after hearing the consent message + +The system automatically tracks consent decisions and provides compliance data in the end-of-call report, including whether consent was granted and when it was obtained. + +Alternatively, you can implement custom consent flows using squads: + +```json +{ + "squad": { + "members": [ + { + "assistant": { + "name": "Consent Assistant", + "artifactPlan": { + "recordingEnabled": false, + "loggingEnabled": false, + "transcriptPlan": { "enabled": false } + } + } + }, + { + "assistant": { + "name": "Main Assistant", + "artifactPlan": { + "recordingEnabled": true, + "loggingEnabled": true, + "transcriptPlan": { "enabled": true } + } + } + } + ] + } +} +``` + +The consent assistant runs without generating artifacts, while the main assistant records the actual conversation after consent is obtained. + +## Artifact Plan Configuration + +### Configure via Dashboard + + + + Open the [Dashboard](https://dashboard.vapi.ai/assistants). Select **Assistants**, then select the assistant you want to configure. + -### Enable Recording + + Select the **Advanced** tab, then locate **Recording & Artifacts**. + -You can enable call recording at the assistant level or per individual call: + + Select **Audio Recording**, **Logging**, and **Transcript** to enable or disable each artifact. Choose an **Audio Recording Format** for call recordings. + + + + Select **Video Recording** to enable or disable recording for web calls. + + + + Select **publish** in the unsaved-changes message to apply the update. + + + + + + + +### Basic Configuration + +Configure recording, logging, and transcript generation using the `artifactPlan`: ```json title="Assistant Configuration" { "name": "Customer Support Assistant", - "recordingEnabled": true, + "artifactPlan": { + "recordingEnabled": true, + "recordingFormat": "wav;l16", + "loggingEnabled": true, + "pcapEnabled": true, + "transcriptPlan": { + "enabled": true, + "assistantName": "Assistant", + "userName": "Customer" + } + }, "model": { "provider": "openai", "model": "gpt-4" @@ -40,84 +177,259 @@ You can enable call recording at the assistant level or per individual call: ```json title="Per-Call Configuration" { "assistant": { - "name": "Support Agent" + "name": "Support Agent", + "artifactPlan": { + "recordingEnabled": true, + "recordingFormat": "wav;l16", + "loggingEnabled": true, + "pcapEnabled": true, + "transcriptPlan": { + "enabled": true, + "assistantName": "Support Agent", + "userName": "Customer" + } + } }, - "recordingEnabled": true, "phoneNumberId": "your-phone-number-id" } ``` -### Recording Options +### Artifact Plan Options -Configure recording behavior with these options: +Configure different types of artifacts with these options: -- **`recordingEnabled`**: Enable or disable recording for this assistant/call -- **`recordingChannelCount`**: Number of audio channels to record (1 for mono, 2 for stereo) -- **`recordingFormat`**: Audio format for recordings (mp3, wav, etc.) +- **`recordingEnabled`**: Enable call recording (stored in `call.artifact.recording`) Default: `true` +- **`recordingFormat`**: Audio format for recordings (e.g., "wav;l16", "mp3") Default: "wav;l16" +- **`loggingEnabled`**: Enable detailed call logs (stored in `call.artifact.logUrl`) Default: `true` +- **`pcapEnabled`**: Enable SIP packet capture for phone calls (stored in `call.artifact.pcapUrl`) Default: `true` +- **`transcriptPlan`**: Configure transcript generation with speaker names -## Storage Options +## Storage Configuration ### Default Storage -By default, Vapi stores recordings securely in the cloud: +By default, Vapi stores artifacts securely in the cloud: -- Recordings are encrypted at rest and in transit +- Recordings, logs, and transcripts are encrypted at rest and in transit - Access is controlled through your API credentials -- Recordings are automatically cleaned up based on your retention policy +- Artifacts are automatically cleaned up based on your retention policy ### Custom Storage -For advanced use cases, you can configure custom storage: +Configure custom storage for different artifact types: ```json title="S3 Storage Configuration" { - "recordingEnabled": true, - "recordingPath": "https://your-bucket.s3.amazonaws.com/recordings/", - "recordingCredentials": { - "provider": "aws", - "region": "us-east-1", - "accessKeyId": "your-access-key", - "secretAccessKey": "your-secret-key" - } + "artifactPlan": { + "recordingEnabled": true, + "recordingFormat": "wav;l16", + "loggingEnabled": true, + "pcapEnabled": true, + "recordingUseCustomStorageEnabled": true, + "loggingUseCustomStorageEnabled": true, + "pcapUseCustomStorageEnabled": true, + "recordingPath": "https://your-bucket.s3.amazonaws.com/recordings/", + "loggingPath": "https://your-bucket.s3.amazonaws.com/logs/", + "pcapS3PathPrefix": "/pcaps", + "transcriptPlan": { + "enabled": true, + "assistantName": "Assistant", + "userName": "Customer" + } + }, + "credentials": [ + { + "provider": "aws", + "region": "us-east-1", + "accessKeyId": "your-access-key", + "secretAccessKey": "your-secret-key" + } + ] } ``` ```json title="Google Cloud Storage" { - "recordingEnabled": true, - "recordingPath": "gs://your-bucket/recordings/", - "recordingCredentials": { - "provider": "gcp", - "serviceAccountKey": "your-service-account-json" - } + "artifactPlan": { + "recordingEnabled": true, + "recordingFormat": "wav;l16", + "loggingEnabled": true, + "pcapEnabled": true, + "recordingUseCustomStorageEnabled": true, + "loggingUseCustomStorageEnabled": true, + "pcapUseCustomStorageEnabled": true, + "recordingPath": "gs://your-bucket/recordings/", + "loggingPath": "gs://your-bucket/logs/", + "transcriptPlan": { + "enabled": true, + "assistantName": "Assistant", + "userName": "Customer" + } + }, + "credentials": [ + { + "provider": "gcp", + "serviceAccountKey": "your-service-account-json" + } + ] } ``` -## Accessing Recordings +### Storage Control Options + +Control where each artifact type is stored: + +- **`recordingUseCustomStorageEnabled`**: Use custom storage for recordings (default: true) +- **`loggingUseCustomStorageEnabled`**: Use custom storage for logs (default: true) +- **`pcapUseCustomStorageEnabled`**: Use custom storage for SIP packet capture (default: true) +- **`recordingPath`**: Custom path for recording storage +- **`loggingPath`**: Custom path for log storage +- **`pcapS3PathPrefix`**: S3 path prefix for PCAP files + +## Squad and Transfer Behavior + +### Dynamic Artifact Control + +When handing off between assistants in a Squad, you may choose to change the local context for each assistant via the `contextEngineeringPlan`. By default, only the final context will be used in the artifact and analysis (Structured outputs and success evaluation). To include the full message history across all assistants in the call, set [`artifactPlan.fullMessageHistoryEnabled`](/api-reference/squads/create#request.body.membersOverrides.artifactPlan.fullMessageHistoryEnabled) to true. + +In squads with multiple assistants, artifact generation (recording, logging, transcripts) can be controlled per assistant. When assistants are swapped or transferred during a call: + +- **Recording**: Pauses when `recordingEnabled: false` assistant is active, resumes when `recordingEnabled: true` assistant takes over +- **Logging**: Pauses when `loggingEnabled: false` assistant is active, resumes when `loggingEnabled: true` assistant takes over +- **Transcripts**: Pauses when `transcriptPlan.enabled: false` assistant is active, resumes when `transcriptPlan.enabled: true` assistant takes over + +## Transcript Configuration + +### Automatic Transcription + +Configure transcript generation using the `transcriptPlan`: + +```json +{ + "artifactPlan": { + "transcriptPlan": { + "enabled": true, + "assistantName": "Assistant", + "userName": "Customer" + } + } +} +``` + +### Transcript Plan Options + +- **`enabled`**: Enable or disable transcript generation +- **`assistantName`**: Name to use for assistant messages in transcripts +- **`userName`**: Name to use for user messages in transcripts + +### Transcript Features + +- **Real-time transcription**: Transcripts are generated during the call +- **Speaker identification**: Distinguishes between assistant and user messages +- **Timestamps**: Each message includes timing information +- **OpenAI formatting**: Available in `call.artifact.messagesOpenAIFormatted` + +### Transcript Structure + +```json +{ + "callId": "call-123", + "artifact": { + "transcript": [ + { + "role": "assistant", + "message": "Hello! How can I help you today?", + "time": 0.5 + }, + { + "role": "user", + "message": "I need help with my account", + "time": 3.2 + } + ], + "messagesOpenAIFormatted": [ + { + "role": "assistant", + "content": "Hello! How can I help you today?" + }, + { + "role": "user", + "content": "I need help with my account" + } + ] + } +} +``` + +## Logging Configuration + +### Detailed Call Logs + +Enable comprehensive logging for debugging and analysis: + +```json +{ + "artifactPlan": { + "loggingEnabled": true, + "loggingUseCustomStorageEnabled": true, + "loggingPath": "https://your-bucket.s3.amazonaws.com/logs/" + } +} +``` + +### Log Features + +- **Debug information**: Detailed logs for troubleshooting +- **Performance metrics**: Call timing and performance data +- **Error tracking**: Comprehensive error logs and stack traces + +### Accessing Logs + +Logs are available through: +- **Dashboard**: View logs in the call details page +- **API**: Access via `call.artifact.logUrl` +- **Custom storage**: Store logs in your S3/GCP bucket + +## Accessing Artifacts ### Via Dashboard -1. Navigate to **Calls** in your Vapi dashboard -2. Select a specific call from the list -3. Click on the **Recording** tab to play or download the audio +1. Open the [Dashboard](https://dashboard.vapi.ai/). +2. Select **Logs**, then select **Calls**. +3. Select a call from the list. +4. Review the available call artifacts: + - Use the recording controls to play or download the audio recording when recording is enabled. + - Select **Transcripts** to view the conversation transcript. + - Select **Logs** to review detailed call logs for debugging. + - Download the PCAP file to inspect the packet capture when the call uses SIP and PCAP is enabled. ### Via API -Retrieve recording URLs programmatically: +Retrieve artifact URLs programmatically: ```typescript import { VapiClient } from "@vapi-ai/server-sdk"; const client = new VapiClient({ token: "your-api-key" }); -// Get call details including recording URL +// Get call details including all artifacts const call = await client.calls.get("call-id"); -console.log("Recording URL:", call.recordingUrl); + +console.log("Recording URL:", call.artifact.recording); +console.log("Transcript:", call.artifact.transcript); +console.log("Log URL:", call.artifact.logUrl); +console.log("PCAP URL:", call.artifact.pcapUrl); +console.log("Messages:", call.artifact.messages); +console.log("Nodes:", call.artifact.nodes); ``` + + The `recording` and `logUrl` values are private, authenticated URLs — they can't be downloaded directly. See [Retrieve call artifacts](/assistants/retrieve-call-artifacts) for how to fetch the actual files. + + ## Privacy and Compliance ### Legal Considerations @@ -128,6 +440,15 @@ console.log("Recording URL:", call.recordingUrl); - **Data protection** regulations (GDPR, CCPA, etc.) - **Industry standards** (PCI DSS, HIPAA, etc.) +### Built-in Consent Management + +For Enterprise customers, Vapi provides automated consent management through [recording consent plans](/security-and-privacy/recording-consent-plan). This feature automatically: + +- Creates a consent assistant that requests recording permission +- Handles both verbal and stay-on-line consent types +- Only begins recording after consent is granted +- Maintains audit trails of consent decisions + ### Best Practices - **Inform callers** about recording at the start of conversations @@ -141,60 +462,106 @@ console.log("Recording URL:", call.recordingUrl); ## Recording Analysis -### Transcription +### Call Artifacts -Recorded calls are automatically transcribed for analysis: +Use the comprehensive artifact data for analysis: ```json { "callId": "call-123", - "transcript": [ - { - "role": "assistant", - "message": "Hello! How can I help you today?", - "time": 0.5 - }, - { - "role": "user", - "message": "I need help with my account", - "time": 3.2 + "artifact": { + "transcript": [ + { + "role": "assistant", + "message": "Hello! How can I help you today?", + "time": 0.5 + }, + { + "role": "user", + "message": "I need help with my account", + "time": 3.2 + } + ], + "messages": [ + { + "role": "assistant", + "message": "Hello! How can I help you today?" + }, + { + "role": "user", + "message": "I need help with my account" + } + ], + "nodes": [ + { + "name": "greeting", + "messages": ["Hello! How can I help you today?"], + "variables": {} + } + ], + "variableValues": { + "customerName": "John Doe", + "issueType": "account_access" } - ], - "recordingUrl": "https://api.vapi.ai/recordings/call-123.mp3" + } } ``` -### Call Analysis +### Analysis Use Cases -Use recorded data for insights: +Use artifact data for comprehensive insights: -- **Conversation flow** analysis -- **Response quality** evaluation -- **Customer satisfaction** metrics -- **Assistant performance** tracking +- **Conversation flow** analysis using `artifact.nodes` +- **Response quality** evaluation using `artifact.messages` +- **Customer satisfaction** metrics from transcript analysis +- **Assistant performance** tracking using logs and recordings +- **Variable tracking** using `artifact.variableValues` ## FAQ - - Yes, all recordings are automatically transcribed and available through the API and dashboard. + + Use the `artifactPlan` configuration in your assistant or call settings. Set `recordingEnabled`, `loggingEnabled`, and configure `transcriptPlan.enabled` to `true` to enable all three features. + + + + By default, artifacts are stored securely in Vapi's cloud storage. You can configure custom storage using S3 or Google Cloud Storage with the `recordingPath`, `loggingPath`, and storage control options. + + + + Artifacts are available through the API via `call.artifact.recording`, `call.artifact.transcript`, `call.artifact.logUrl`, and other properties. You can also view them in the Vapi dashboard. - - Default retention is 30 days. You can configure custom retention policies for your account. + + The `transcript` includes timing information and is optimized for conversation analysis. The `messages` property contains the same content but in a simpler format, while `messagesOpenAIFormatted` is structured for OpenAI API compatibility. + + + + Use the `transcriptPlan` configuration with `assistantName` and `userName` properties to customize how speakers are identified in the transcript output. - Yes, you can enable/disable recording at both the assistant level and per individual call. + Yes, you can configure artifact plans at both the assistant level and per individual call. This gives you granular control over what artifacts are generated for each conversation. + + + + PCAP (Packet Capture) is available for phone calls and contains SIP packet data for debugging telephony issues. It's stored in `call.artifact.pcapUrl` when `pcapEnabled` is set to `true`. + + + + Retention periods vary by plan: + - **Pay-As-You-Go:** Up to 30 days for chats and 14 days for calls + - **Enterprise:** Configurable retention policies - - Call recording is available in all supported Vapi regions with local data residency options. + + In squads, each assistant can have different artifact settings. Recording, logging, and transcripts pause when an assistant with disabled artifacts is active, and resume when an assistant with enabled artifacts takes over. This allows for privacy-conscious flows like consent collection. ## Next Steps - **[Call Analysis](/assistants/call-analysis)** - Analyze recorded conversations for insights +- **[Recording Consent Plans](/security-and-privacy/recording-consent-plan)** - Automated consent management for Enterprise customers - **[Privacy Compliance](/security-and-privacy/GDPR)** - Ensure GDPR and privacy compliance - **[API Reference](/api-reference/calls/create)** - Explore recording configuration options diff --git a/fern/assistants/call-timeout-settings.mdx b/fern/assistants/call-timeout-settings.mdx new file mode 100644 index 000000000..7e38d5f7e --- /dev/null +++ b/fern/assistants/call-timeout-settings.mdx @@ -0,0 +1,78 @@ +--- +title: Call timeout settings +subtitle: End inactive calls and limit the total duration of each call. +description: Configure silence and maximum-duration timeouts for assistants, distinguish inactivity from total call duration, and troubleshoot timeout call endings. +--- + +Call timeout settings control when an assistant ends a silent or long-running call. Use them to close inactive calls and set a hard limit on total call duration. + +## How call timeouts work + +**Silence Timeout** ends a call after the configured period of inactivity. **Maximum Duration** ends a call when its total duration reaches the configured limit, even if the conversation is active. + +[`call.timeElapsed` hooks](/assistants/assistant-hooks#example-trigger-actions-at-a-specific-time) can warn the user or begin wrapping up before **Maximum Duration**. The hooks do not replace or extend the hard duration limit. + +## Configure via Dashboard + + + + Open the [Dashboard](https://dashboard.vapi.ai/assistants). Select **Assistants**, then select the assistant you want to configure. + + + + Select the **Advanced** tab, then locate **Call Timeout Settings**. + + + + Set **Silence Timeout** from 5 to 3,600 seconds. + + + + Set **Maximum Duration** from 10 to 43,200 seconds. + + + + Select **publish** in the unsaved-changes message to apply the update. + + + +## API fields + +Use these fields when you create or update an assistant through the API: + +| Dashboard setting | API field | Behavior | +| --- | --- | --- | +| **Silence Timeout** | `silenceTimeoutSeconds` | Ends the call after the configured number of seconds without activity. | +| **Maximum Duration** | [`maxDurationSeconds`](/api-reference/assistants/create#request.body.maxDurationSeconds) | Ends the call after the configured total number of seconds. The allowed range is 10–43,200 seconds. Default is 600 seconds. | + +This example ends a call after 30 seconds of inactivity or 10 minutes of total call time: + +```json +{ + "silenceTimeoutSeconds": 30, + "maxDurationSeconds": 600 +} +``` + + + The current generated schema for regular assistants does not state a minimum + or default for `silenceTimeoutSeconds`. The Dashboard accepts values from 5 + to 3,600 seconds. + + +## Troubleshoot call endings + +Calls that end because of timeout settings are expected call endings, not call errors. + +| Ended reason | What happened | What to check | +| --- | --- | --- | +| `silence-timed-out` | The call reached `silenceTimeoutSeconds` without activity. | Increase **Silence Timeout** if active calls end during normal pauses. | +| `exceeded-max-duration` | The call reached `maxDurationSeconds`. | Increase **Maximum Duration**, or use `call.timeElapsed` hooks to wrap up before the limit. | + +See [call end reasons](/calls/call-ended-reason) for the complete list of ended reasons. For additional diagnostic guidance, see [Troubleshoot call errors](/calls/troubleshoot-call-errors). + +## Related + +- [Assistant hooks](/assistants/assistant-hooks) +- [Call end reasons](/calls/call-ended-reason) +- [Troubleshoot call errors](/calls/troubleshoot-call-errors) diff --git a/fern/assistants/dynamic-variables.mdx b/fern/assistants/dynamic-variables.mdx index 29606af9e..b785885b1 100644 --- a/fern/assistants/dynamic-variables.mdx +++ b/fern/assistants/dynamic-variables.mdx @@ -69,16 +69,27 @@ For example, set the assistant's first message to "Hello, `{{name}}`!" and assig These variables are automatically filled based on the current (UTC) time, so you don't need to set them manually in `variableValues`: -| Variable | Description | Example | -| ----------------------- | --------------------------------- | ------------------------- | -| `{{now}}` | Current date and time (UTC) | Jan 1, 2024 12:00 PM | -| `{{date}}` | Current date (UTC) | Jan 1, 2024 | -| `{{time}}` | Current time (UTC) | 12:00 PM | -| `{{month}}` | Current month (UTC) | January | -| `{{day}}` | Current day of month (UTC) | 1 | -| `{{year}}` | Current year (UTC) | 2024 | -| `{{customer.number}}` | Customer's phone number | +1xxxxxxxxxx | -| `{{customer.X}}` | Any other customer property | | +| Variable | Description | Example | +| --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------ | +| `{{now}}` | Current date and time (UTC). For other timezones, use the LiquidJS `date` filter -- see [Advanced date and time usage](#advanced-date-and-time-usage) below. | Jan 1, 2024 12:00 PM | +| `{{date}}` | Current date (UTC) | Jan 1, 2024 | +| `{{time}}` | Current time (UTC) | 12:00 PM | +| `{{month}}` | Current month (UTC) | January | +| `{{day}}` | Current day of month (UTC) | 1 | +| `{{year}}` | Current year (UTC) | 2024 | +| `{{customer.number}}` | The customer's phone number (caller-ID for inbound calls, destination for outbound calls). | +1xxxxxxxxxx | +| `{{customer.X}}` | Any other customer property you set when creating the call. | | +| `{{phoneNumber.number}}` | The Vapi phone number that received the inbound call or placed the outbound call. | +1xxxxxxxxxx | +| `{{phoneNumber.name}}` | The display name you set on this phone number in the dashboard. | `Main Support Line` | +| `{{call.id}}` | The unique Vapi-generated ID for this call. Useful for correlating with your own logs, support tickets, or webhooks. | `5fe26c8e-...` | +| `{{call.type}}` | The kind of call this is. Useful for branching prompt behavior between channels. | `inboundPhoneCall` / `outboundPhoneCall` / `webCall` | +| `{{transport.callSid}}` | The provider-side call session ID (e.g. Twilio's `CallSid`). Useful for BYOT customers correlating with their own provider logs. | `CA1234...` | +| `{{transport.conversationType}}` | Whether the conversation is over `chat` or `voice`. | `chat` | +| `{{transport.X}}` | Any other transport-related property. | | + + +To pass these values **between tool calls within an assistant** (rather than templating them into prompts), see [Static variables and aliases](/tools/static-variables-and-aliases). That page documents the trust tiers for these variables -- which are signaling-derived and safe to use as a security boundary in tool calls, vs. conversation-derived ones that are not -- and shows how to inject them into tool calls deterministically, without LLM mediation. + ## Advanced date and time usage @@ -116,13 +127,13 @@ Outputs: `Monday, January 01, 2024, 03:45 PM` | `%H:%M` | 15:45 | 24-hour time | | `%A` | Monday | Day of week | | `%b %d, %Y` | Jan 01, 2024 | Abbrev. Month Day | -``` + ## Using dynamic variables in the dashboard To use dynamic variables in the dashboard, include them in your prompts or messages using double curly braces. For example: -``` +```liquid Hello, {{name}}! ``` @@ -131,4 +142,34 @@ When you start a call, you must provide a value for each variable (like `name`) Always use double curly braces (`{{variableName}}`) to reference dynamic variables in your prompts and messages. - \ No newline at end of file + +## Setting assistant prompt using conversation type + +Using the `transport.conversationType` variable in your assistant's system prompt, you can modify how it behaves in chats or calls: + +```liquid +[Identity] +You are a helpful assistant, talking with a customer via {{transport.conversationType}}. + +[Response Guidelines] +{% if transport.conversationType == "chat" -%} +- Format numbers naturally; eg, a US phone number could be +1 (555) 123-4567 +- Use Markdown formatting for lists (both unordered and ordered) +{%- elsif transport.conversationType == "voice" -%} +- Always spell numbers in words; eg, 256 should be 'two hundred and fifty six' +- Only ask one question at a time +- Never use Markdown format; write everything as if it is being said aloud +{%- endif -%} +``` + +## Zero Data Retention mode + +When Zero Data Retention is enabled for your organization or assistant, Vapi does not store any call data, including variable values. This means: + +- Variable values passed via `variableValues` are processed during the call but **not persisted** after the call ends +- Call logs, recordings, and transcriptions are not stored +- Variables are only available in real-time during the active call session + +This ensures compliance with privacy requirements while still allowing you to personalize conversations with dynamic variables. + +For more information, see [Zero Data Retention (ZDR)](/security-and-privacy/zero-data-retention). diff --git a/fern/assistants/email-address-reading.mdx b/fern/assistants/email-address-reading.mdx new file mode 100644 index 000000000..c0a9d0571 --- /dev/null +++ b/fern/assistants/email-address-reading.mdx @@ -0,0 +1,435 @@ +--- +title: Email address reading +subtitle: Get your voice agent to collect, read back, and confirm email addresses clearly +slug: assistants/email-address-reading +--- + +## Overview + +Email addresses are one of the trickiest pieces of information for a voice agent to handle. They contain special characters (`@`, `.`, `-`, `_`), mixed-case text, and domain names that text-to-speech (TTS) engines often mispronounce or blur together when spoken aloud. + +This guide covers three layers of the solution: + +- **Built-in formatting** -- Vapi automatically transforms email characters for TTS so they sound natural, with zero configuration. +- **API configuration** -- You can fine-tune which formatters run, disable email formatting selectively, or customize the entire formatting pipeline. +- **Prompt engineering** -- You instruct the LLM *how* to collect, read back, and confirm emails in conversation so users feel confident their address was captured correctly. + +## How Vapi handles emails automatically + +Vapi's [voice formatting plan](/assistants/voice-formatting-plan) runs a 14-step pipeline that transforms raw LLM text into natural-sounding speech before it reaches the TTS provider. The `email` formatter is **step 8** in this pipeline. It replaces `@` with "at" and `.` with "dot" so the spoken output is intelligible without any prompt changes. + +| Raw LLM output | What the user hears | +|---|---| +| `john.doe@example.com` | "john dot doe at example dot com" | +| `SALES@company.org` | "SALES at company dot org" | +| `jane_smith-work@my-company.co.uk` | "jane underscore smith dash work at my dash company dot co dot uk" | + + +The `email` formatter is enabled by default. You do not need to configure anything for basic email reading to work. + + +### Where email formatting fits in the pipeline + +The formatter runs after acronym and dollar-amount formatting, and before date, time, and phone number formatting. Here is the full 14-step pipeline with the email step highlighted: + +| Step | Formatter key | What it does | Default | +|------|--------------|--------------|---------| +| 1 | `removeAngleBrackets` | Removes `<...>` tags (except ``, ``, `<< >>`) | On | +| 2 | `markdown` | Removes markdown symbols (`_`, `` ` ``, `~`) | On | +| 3 | `asterisk` | Removes text wrapped in `*` or `**` | Off | +| 4 | `newline` | Converts `\n` to `.` for smoother phrasing | On | +| 5 | `colon` | Replaces `:` with `.` | On | +| 6 | `acronym` | Formats acronyms (e.g., `NASA` to `nasa`) | On | +| 7 | `dollarAmount` | `$42.50` to "forty two dollars and fifty cents" | On | +| **8** | **`email`** | **`@` to "at", `.` to "dot" in email addresses** | **On** | +| 9 | `date` | `2023-05-10` to "Wednesday, May 10, 2023" | On | +| 10 | `time` | `14:00` to "14" | On | +| 11 | `distance` / `unit` / `percentage` | `5km` to "5 kilometers", `50%` to "50 percent" | On | +| 12 | `phoneNumber` | `123-456-7890` to "1 2 3 4 5 6 7 8 9 0" | On | +| 13 | `number` | Formats general numbers, years, decimals | On | +| 14 | `stripAsterisk` | Removes remaining `*` characters | On | + + +For full details on every step, see the [voice formatting plan](/assistants/voice-formatting-plan) reference. + + +## Configuring email formatting via the API + +The email formatter runs automatically with no configuration needed. However, you can customize the behavior through the `formatPlan` on your assistant's voice configuration. + +### Configuration path + +``` +assistant.voice.chunkPlan.formatPlan +``` + +The relevant TypeScript type: + +```typescript title="FormatPlan type definition" +interface FormatPlan { + enabled?: boolean; // default: true + numberToDigitsCutoff?: number; // default: 2025 + replacements?: FormatPlanReplacementsItem[]; // default: [] + formattersEnabled?: FormatPlanFormattersEnabledItem[]; // default: all formatters +} +``` + +The `formattersEnabled` array accepts any combination of these values: `removeAngleBrackets`, `markdown`, `asterisk`, `newline`, `colon`, `acronym`, `dollarAmount`, `email`, `date`, `time`, `distance`, `unit`, `percentage`, `phoneNumber`, `number`, `stripAsterisk`. + + +The `formattersEnabled` property was introduced on **2025-02-20**. Before that date, you could only toggle all formatting on or off with the `enabled` flag. If you are using an older API version, use `enabled: false` to disable all formatting. + + +### Default behavior (no configuration needed) + +By default, all formatters -- including `email` -- are enabled. You do not need to set anything for email addresses to be read correctly: + +```json title="Default -- email formatting is already on" +{ + "voice": { + "chunkPlan": { + "formatPlan": { + "enabled": true + } + } + } +} +``` + +### Enable only specific formatters + +If you want tight control over which transformations run, pass only the formatter keys you need. This example enables only the `email` and `phoneNumber` formatters: + + +```json title="JSON (API / Dashboard)" +{ + "voice": { + "chunkPlan": { + "formatPlan": { + "formattersEnabled": ["email", "phoneNumber"] + } + } + } +} +``` +```typescript title="TypeScript SDK" +const assistant = await vapi.assistants.create({ + // ... other configuration + voice: { + chunkPlan: { + formatPlan: { + formattersEnabled: ["email", "phoneNumber"] + } + } + } +}); +``` +```python title="Python SDK" +assistant = client.assistants.create( + # ... other configuration + voice={ + "chunkPlan": { + "formatPlan": { + "formattersEnabled": ["email", "phoneNumber"] + } + } + } +) +``` + + + +When you set `formattersEnabled`, **only** the listed formatters run. All others are disabled. Make sure to include every formatter you need. + + +### Disable email formatting while keeping all others + +Omit `email` from the `formattersEnabled` array. The TTS provider will then receive the raw `@` and `.` characters, and pronunciation depends entirely on the provider and your prompt: + +```json title="All formatters except email" +{ + "voice": { + "chunkPlan": { + "formatPlan": { + "formattersEnabled": [ + "removeAngleBrackets", + "markdown", + "newline", + "colon", + "acronym", + "dollarAmount", + "date", + "time", + "distance", + "unit", + "percentage", + "phoneNumber", + "number", + "stripAsterisk" + ] + } + } + } +} +``` + +### Disable all formatting + +To send raw LLM output directly to TTS with no transformations at all: + +```json title="Disable all formatting" +{ + "voice": { + "chunkPlan": { + "formatPlan": { + "enabled": false + } + } + } +} +``` + + +Disabling all formatting means numbers, currencies, dates, phone numbers, and emails will all be sent raw to the TTS provider. Most providers will produce unnatural or garbled speech for these patterns. + + +## Why prompt engineering still matters + +Even though TTS formatting handles the character-level pronunciation, the LLM still controls *how* the conversation flows. Without explicit instructions, the agent might: + +- Read the email once at normal speed and move on, leaving the user unsure. +- Fail to spell out ambiguous parts (was it "Jon" or "John"?). +- Mispronounce uncommon domain names. +- Skip a confirmation step entirely. + +Good prompt instructions solve these problems at the conversational level. + +## System prompt: collecting an email + +When asking a user for their email, instruct the agent to be patient and explicit about what it needs. The following snippet can be added to your system prompt. + +```md wordWrap title="System prompt -- collecting email" +[Email Collection] +When you need to collect the user's email address: +1. Ask clearly: "Could you please tell me your email address?" +2. Listen to the full response before repeating anything back. +3. Once you have the email, read it back using these pronunciation rules: + - Say "@" as "at" + - Say "." as "dot" + - Say "-" as "dash" + - Say "_" as "underscore" +4. After reading it back, ask "Is that correct?" +5. If the user says no, ask them to spell it out letter by letter. +6. Never guess or autocorrect the email. Use exactly what the user provides. +``` + +## System prompt: reading back and confirming an email + +The confirmation step is where most agents fail. They read the email too fast or only once. This snippet teaches the agent to slow down and spell when needed. + +```md wordWrap title="System prompt -- confirming email" +[Email Confirmation] +When reading an email address back to the user: +1. Speak slowly and clearly. Pause briefly between each part of the email + (username, "at", domain, "dot", extension). +2. For the username part, if it contains common words, say the words. + If it is ambiguous or uncommon, spell it out letter by letter. + For example: + - "john.doe" → "john dot doe" + - "jdoe42" → "j, d, o, e, four, two" + - "msmith" → "m, s, m, i, t, h" +3. For the domain, use the familiar name if it is a well-known provider: + - "gmail.com" → "gmail dot com" + - "yahoo.com" → "yahoo dot com" + - "outlook.com" → "outlook dot com" + - "hotmail.com" → "hotmail dot com" + If the domain is uncommon, spell it out letter by letter. +4. Always end with: "Is that correct?" +5. If the user corrects any part, repeat the entire email back again + after applying the correction. +``` + +## Spelling out letter by letter + +For ambiguous usernames or unfamiliar domains, letter-by-letter spelling removes all doubt. Add this instruction to your prompt so the agent knows when and how to spell. + +```md wordWrap title="System prompt -- letter-by-letter spelling" +[Letter-by-Letter Spelling] +When spelling out part of an email: +- Say each letter individually with a brief pause between letters. +- For numbers, say the digit name ("one", "two", "three"), not the numeral. +- For uppercase vs lowercase, only mention case if the email is case-sensitive + or the user specifically asks. +- Use the NATO phonetic alphabet only if the user is having trouble + understanding individual letters. For example: + "b as in bravo, d as in delta" +``` + + +Most email providers treat addresses as case-insensitive, so you typically do not need to distinguish uppercase from lowercase. Your prompt can note this to keep the conversation simpler. + + +## Handling common domains naturally + +You can make the agent sound more natural by teaching it to recognize popular email domains and say them as single words rather than spelling them out. + +```md wordWrap title="System prompt -- common domains" +[Common Email Domains] +When reading these domains, say them as words, not spelled out: +- gmail.com → "gmail dot com" +- yahoo.com → "yahoo dot com" +- outlook.com → "outlook dot com" +- hotmail.com → "hotmail dot com" +- icloud.com → "icloud dot com" +- aol.com → "A O L dot com" +- protonmail.com → "proton mail dot com" +For any domain not in this list, spell it out letter by letter to avoid confusion. +``` + +## Complete example: appointment booking agent + +Below is a full system prompt section you can copy into your assistant configuration. It combines all the techniques above into a single, production-ready block. + +```md wordWrap title="Complete system prompt section" +[Identity] +You are Sarah, a friendly appointment scheduling assistant for Acme Dental. + +[Email Collection and Confirmation] +When you need the user's email address: +1. Ask: "What email address should we send the confirmation to?" +2. Wait for the full response. Do not interrupt. +3. Read the email back to the user following these rules: + - Say "@" as "at" + - Say "." as "dot" + - Say "-" as "dash" + - Say "_" as "underscore" + - Speak slowly with a brief pause between each part. + - For well-known domains (gmail, yahoo, outlook, hotmail, icloud), + say the domain name naturally. + - For unfamiliar domains, spell them out letter by letter. + - For the username, if it is a recognizable name or word, say it normally. + If it looks like an abbreviation or random string, spell it out letter + by letter. +4. After reading the email, ask: "Did I get that right?" +5. If the user says no: + - Ask: "Could you spell it out for me letter by letter?" + - Listen carefully, then read the corrected version back. + - Ask again: "Is that correct now?" +6. Do not proceed to the next step until the user confirms the email. +7. Never modify, autocorrect, or guess any part of the email address. + +[Example Conversation] +Agent: "What email address should we send the confirmation to?" +User: "It's jsmith42@newcompany.io" +Agent: "Let me read that back. j, s, m, i, t, h, four, two ...at... new company + ...dot... i, o. Did I get that right?" +User: "Yes, that's correct." +``` + + +Including an example conversation in your system prompt helps the LLM understand the exact pacing and format you expect. This is one of the most effective techniques for consistent behavior. + + +## Using pronunciation dictionaries for domains + +If your agents frequently encounter a specific company or domain name that TTS mispronounces, you can use [pronunciation dictionaries](/assistants/pronunciation-dictionaries) (available with ElevenLabs voices) to set the correct pronunciation at the TTS level. + +For example, if the domain "vapi.ai" is being pronounced as "vappy dot ay-eye", you could create an alias rule: + +```json title="Pronunciation dictionary rule" +{ + "rules": [ + { + "stringToReplace": "vapi", + "type": "alias", + "alias": "vaahpee" + } + ] +} +``` + +This approach is complementary to prompt engineering -- pronunciation dictionaries fix TTS-level pronunciation, while prompt instructions control the conversational flow. + +## Using custom keywords for transcription accuracy + +If the speech-to-text (STT) transcriber is mishearing specific email domains or usernames, [custom keywords](/customization/custom-keywords) can boost transcription accuracy for those terms. + +For example, if users frequently mention their company email domain "contoso.com" and the transcriber misinterprets it, you can add "contoso" as a custom keyword to improve recognition. + +## Best practices + + + + Never assume an email is correct after hearing it once. Always read the + complete email back and wait for confirmation before proceeding. This single + step prevents the majority of email capture errors. + + + + First, try reading the email back naturally (words and common domains). + If the user says it is wrong, switch to letter-by-letter spelling for + the entire address. This keeps simple emails fast while still handling + complex ones reliably. + + + + Instruct the agent to never modify any part of the email address. + Common mistakes include changing "jon" to "john" or assuming ".com" + when the user said ".co". Treat the email as an exact string. + + + + Users sometimes interrupt mid-readback with a correction. Instruct the + agent to accept the correction, incorporate it, and then restart the + full readback from the beginning so both parties are aligned. + + + + Vapi's built-in `formatEmails` transformer handles the TTS-level + conversion of "@" and "." automatically. Disabling the voice formatting + plan will cause the TTS to receive raw characters, which may produce + garbled output. Keep `voice.chunkPlan.formatPlan.enabled` set to `true` + (the default). + + + +## Common issues + + + + This usually happens when voice formatting is disabled. Verify that + `voice.chunkPlan.formatPlan.enabled` is set to `true` (the default). + See the [voice formatting plan](/assistants/voice-formatting-plan) for + details. + + + + Add an explicit instruction like "Do not proceed until the user confirms + the email" to your system prompt. Reinforcing this with an example + conversation in the prompt helps the LLM follow the flow consistently. + + + + LLMs sometimes try to be helpful by fixing perceived typos. Add a clear + rule: "Never modify, autocorrect, or guess any part of the email address. + Use exactly what the user provides." + + + + Letters like "b" and "d", or "m" and "n", sound similar over phone audio. + If this happens frequently, instruct the agent to ask the user to use + the NATO phonetic alphabet ("b as in bravo") or use + [custom keywords](/customization/custom-keywords) to improve + transcription accuracy for commonly confused terms. + + + +## Next steps + +Now that your agent handles email addresses reliably: + +- **[Voice formatting plan](/assistants/voice-formatting-plan)** -- Full reference for all 14 formatting steps and customization options. +- **[Prompting guide](/prompting-guide)** -- General techniques for writing effective voice AI prompts. +- **[Pronunciation dictionaries](/assistants/pronunciation-dictionaries)** -- Fine-tune TTS pronunciation for specific words and names. +- **[Custom keywords](/customization/custom-keywords)** -- Improve transcription accuracy for specific terms. +- **[Speech configuration](/customization/speech-configuration)** -- Configure endpointing, silence detection, and other speech settings. diff --git a/fern/assistants/end-call-phrases.mdx b/fern/assistants/end-call-phrases.mdx new file mode 100644 index 000000000..7949abe06 --- /dev/null +++ b/fern/assistants/end-call-phrases.mdx @@ -0,0 +1,96 @@ +--- +title: End call phrases +subtitle: End calls when an assistant says a configured phrase. +description: End call phrases let assistants end calls after saying configured text. Choose reliable phrases and prevent unintended transcript matches during calls. +--- + +End call phrases are configured phrases that end a call after the assistant says them. A customer can initiate the closing exchange by saying goodbye, but the customer's words do not trigger the match directly. The assistant must respond with a configured phrase, such as "have a good day." + +The typical sequence is: + +1. The customer indicates that the conversation is over. +2. The assistant responds with a configured end call phrase. +3. Vapi detects the phrase in the assistant's transcript. +4. Vapi waits for the assistant to finish speaking, then ends the call. + +## How phrase matching works + +Matching is case-insensitive and checks for each phrase as a substring of the assistant's transcript. After a match, Vapi lets the assistant finish speaking before ending the call. Specific multi-word phrases are safer than short conversational words. + +Your assistant's prompt controls when it says the configured phrase. Instruct the assistant to use the phrase when the customer ends the conversation or when the assistant has completed its task. + +Avoid unnecessary punctuation and whitespace inside a phrase. A short phrase such as `bye` can match unintended assistant speech and end the call too early. + +## Configure via Dashboard + + + + Open the [Dashboard](https://dashboard.vapi.ai/assistants). Select **Assistants**, then select the assistant you want to configure. + + + + In the assistant editor, find **End Call Message** and **End Call Phrases**. + + + + In **End Call Phrases**, enter phrases as a comma-separated list. Use specific phrases, for example, `goodbye, take care, have a good day`. + + + + Instruct the assistant to say one of the configured phrases when the customer ends the conversation or the assistant completes its task. + + + + Select **Publish**, review the changes, then select **Quick Publish**. + + + +## API field + +Use [`endCallPhrases`](/api-reference/assistants/create#request.body.endCallPhrases) when you create or update an assistant. The field is an array of strings, and each phrase must contain 2–140 characters. + +```json +{ + "endCallPhrases": [ + "goodbye", + "take care", + "have a good day" + ] +} +``` + +## Choose phrases that avoid false matches + +Use phrases that are specific to the end of a conversation. Test each phrase against the assistant's normal speech so common words do not end calls unexpectedly. + +| Avoid | Prefer | Why | +| --- | --- | --- | +| `bye` | `goodbye for now` | A multi-word phrase is less likely to appear inside unrelated speech. | +| `done` | `we are all done for today` | The longer phrase describes a clear conclusion. | +| `thanks` | `thank you for calling` | The specific phrase is less likely to match a routine acknowledgment. | + +## Compare end call phrases and the End Call Tool + +Both options let an assistant end a call, but they support different decision patterns. + +| Option | Use when | +| --- | --- | +| End call phrases | The assistant uses simple, predictable spoken conclusions. | +| [End Call Tool](/tools/default-tools#end-call) | The model must decide when to end the call using conversation context or more complex conditions. | + +## Troubleshoot unexpected call endings + +| Symptom | Likely cause | What to check | +| --- | --- | --- | +| The call ends too early | A short or common phrase matched unintended assistant speech. | Replace the phrase with a more specific multi-word conclusion. | +| The call does not end | The assistant's transcript does not contain the configured phrase as a substring. | Compare the configured value with the assistant's transcript and remove unnecessary punctuation or whitespace. | + +Calls ended by a matched phrase use the `assistant-said-end-call-phrase` ended reason. This is an expected call ending, not a call error. + +See [call end reasons](/calls/call-ended-reason) for the complete list of ended reasons. For additional diagnostic guidance, see [Troubleshoot call errors](/calls/troubleshoot-call-errors). + +## Related + +- [Built-in call tools](/tools/default-tools) +- [Call end reasons](/calls/call-ended-reason) +- [Troubleshoot call errors](/calls/troubleshoot-call-errors) diff --git a/fern/assistants/examples/appointment-scheduling.mdx b/fern/assistants/examples/appointment-scheduling.mdx new file mode 100644 index 000000000..c4a433462 --- /dev/null +++ b/fern/assistants/examples/appointment-scheduling.mdx @@ -0,0 +1,277 @@ +--- +title: Appointment scheduling assistant +subtitle: Build an AI receptionist that books, reschedules, and cancels appointments using Assistants and tools +slug: assistants/examples/appointment-scheduling +description: Build a voice AI appointment scheduling assistant with Google Calendar integration, availability checking, and automated confirmations using Vapi Assistants. +--- + +## Overview + +Build an AI-powered appointment scheduling assistant that handles inbound calls for booking, rescheduling, and canceling appointments. This approach uses a single Assistant with tools for calendar availability, customer lookups, and confirmations. + +**Assistant Capabilities:** +* Real-time availability checks and booking +* Reschedule and cancel with confirmation +* Customer verification and data lookups +* SMS/email confirmations via tools + +**What You'll Build:** +* An assistant with a focused prompt for scheduling flows +* Tools for calendar availability and booking +* Optional CSV knowledge bases for customers/services +* A phone number attached to your assistant + +## Prerequisites + +* A [Vapi account](https://dashboard.vapi.ai/) +* Google Calendar or a scheduling backend + +## 1. Prepare data (optional) + +Use sample CSVs for customers, services, and appointments during development. + + + +
+ + + + + + + + + +
+
+ + + + 1. Open your [Vapi Dashboard](https://dashboard.vapi.ai) → Files + 2. Upload the three CSVs and note their file IDs + + + + ```typescript + import { VapiClient } from "@vapi-ai/server-sdk"; + import fs from "fs"; + + const vapi = new VapiClient({ token: process.env.VAPI_API_KEY! }); + + async function upload(file: string) { + const res = await vapi.files.create({ file: fs.createReadStream(file) }); + console.log(file, res.id); + return res.id; + } + + const servicesFileId = await upload("services.csv"); + const customersFileId = await upload("customers.csv"); + const appointmentsFileId = await upload("appointments.csv"); + ``` + + + ```python + import requests, os + + def upload(path: str): + r = requests.post( + "https://api.vapi.ai/file", + headers={"Authorization": f"Bearer {os.getenv('VAPI_API_KEY')}"}, + files={"file": open(path, "rb")}, + ) + r.raise_for_status() + print(path, r.json()["id"]) + return r.json()["id"] + + services_file_id = upload("services.csv") + customers_file_id = upload("customers.csv") + appointments_file_id = upload("appointments.csv") + ``` + + + +
+ +--- + +## 2. Create calendar tools + +Use the Google Calendar integration for availability and booking, or your own API via a custom tool. + + + + See: [Google Calendar Integration](/tools/google-calendar) + + Configure tools for: + - `check_availability(service, date)` + - `book_appointment(customer, service, time)` + - `reschedule_appointment(appointmentId, time)` + - `cancel_appointment(appointmentId)` + + + See: [Custom Tools](/tools/custom-tools) + + Define function tools that call your scheduling backend. Attach CSV knowledge bases (customers/services) if using the sample data above. + + + +--- + +## 3. Create the assistant + + + + + + - Go to Assistants → Create Assistant → Blank template + - Name it `Receptionist` + + + ```txt title="System Prompt" maxLines=12 + You are an AI receptionist for a barbershop. Your goals: + 1) Verify the customer + 2) Offer booking, rescheduling, or cancellation + 3) Confirm details and send a confirmation + + When needed, call tools: check_availability, book_appointment, reschedule_appointment, cancel_appointment. + Keep replies under 30 words. Confirm date/time clearly. + ``` + + + Add your scheduling tools to the assistant and publish. + + + + + ```typescript + import { VapiClient } from "@vapi-ai/server-sdk"; + + const vapi = new VapiClient({ token: process.env.VAPI_API_KEY! }); + + const systemPrompt = `You are an AI receptionist for a barbershop. Verify the customer, then offer booking, rescheduling, or cancellation. Use scheduling tools when needed. Keep replies under 30 words.`; + + const assistant = await vapi.assistants.create({ + name: "Receptionist", + firstMessage: "Welcome to Tony's Barbershop! How can I help you today?", + model: { + provider: "openai", + model: "gpt-4o", + messages: [{ role: "system", content: systemPrompt }], + // toolIds: [ "CHECK_AVAILABILITY_ID", "BOOK_ID", "RESCHEDULE_ID", "CANCEL_ID" ] + } + }); + ``` + + + ```python + from vapi import Vapi + import os + + client = Vapi(token=os.getenv("VAPI_API_KEY")) + + assistant = client.assistants.create( + name="Receptionist", + first_message="Welcome to Tony's Barbershop! How can I help you today?", + model={ + "provider": "openai", + "model": "gpt-4o", + "messages": [{"role": "system", "content": "You are an AI receptionist for a barbershop. Verify the customer, then handle booking/rescheduling/cancel."}] + } + ) + ``` + + + +--- + +## 4. Make calls + + + + ```typescript title="create web call" + import { VapiClient } from "@vapi-ai/server-sdk"; + + const vapi = new VapiClient({ token: process.env.VAPI_API_KEY! }); + + await vapi.calls.create({ + transport: { type: "web" }, + assistant: { assistantId: "your-assistant-id" } + }); + ``` + + ```typescript title="create phone call" + await vapi.calls.create({ + phoneNumberId: "your-phone-number-id", + customer: { number: "+15551234567" }, + assistant: { assistantId: "your-assistant-id" } + }); + ``` + + + + ```python title="create web call" + import os + from vapi import Vapi + + client = Vapi(token=os.getenv("VAPI_API_KEY")) + + client.calls.create( + transport={"type": "web"}, + assistant_id="your-assistant-id", + ) + ``` + + ```python title="create phone call" + client.calls.create( + phone_number_id="your-phone-number-id", + customer={"number": "+15551234567"}, + assistant_id="your-assistant-id", + ) + ``` + + + + ```bash + curl -X POST "https://api.vapi.ai/call/web" \ + -H "Authorization: Bearer $VAPI_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "assistant": { "assistantId": "your-assistant-id" } + }' + ``` + + + + ```bash + curl -X POST "https://api.vapi.ai/call" \ + -H "Authorization: Bearer $VAPI_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "assistant": { "assistantId": "your-assistant-id" }, + "phoneNumberId": "your-phone-number-id", + "customer": { "number": "+15551234567" } + }' + ``` + + + +## 5. Test and validate + + + + Create a phone number and assign your assistant. See [Phone calls quickstart](/quickstart/phone). + + + - New booking → check availability → book → confirm + - Reschedule existing appointment → confirm + - Cancel appointment → confirm + + + +## Next steps + +- **Tools**: [Google Calendar](/tools/google-calendar), [Custom Tools](/tools/custom-tools) +- **Structured outputs**: [Extract structured data](/assistants/structured-outputs-quickstart) +- **Multichannel**: [Web integration](/quickstart/web) + diff --git a/fern/assistants/examples/docs-agent.mdx b/fern/assistants/examples/docs-agent.mdx index fd2b1c896..50bc9de79 100644 --- a/fern/assistants/examples/docs-agent.mdx +++ b/fern/assistants/examples/docs-agent.mdx @@ -20,7 +20,7 @@ You'll learn to: ## Prerequisites - [Vapi account](https://dashboard.vapi.ai/) with API access -- Documentation content - `llms.txt` file ([example](https://docs.vapi.ai/llms.txt)) could work great; it could be available out-of-box with your documentation framework (e.g. [Fern](https://buildwithfern.com/learn/docs/developer-tools/llms-txt), [Mintlify](https://mintlify.com/docs/ai-ingestion#%2Fllms-full-txt)) +- Documentation content - `llms.txt` file ([example](https://docs.vapi.ai/llms.txt)) could work great; it could be available out-of-box with your documentation framework (e.g. [Fern](https://buildwithfern.com/learn/docs/ai-features/llms-txt), [Mintlify](https://mintlify.com/docs/ai-ingestion#%2Fllms-full-txt)) - [LlamaCloud account](https://cloud.llamaindex.ai/) for indexing ## Get started @@ -137,7 +137,8 @@ Guidelines: // Configure voice settings voice={ "provider": "vapi", - "voiceId": "Harry" + "version": 2, + "voiceId": "Elliot" }, // Configure transcription transcriber={ @@ -229,7 +230,7 @@ Guidelines: 3. Configure the assistant: - **Name**: `Docs agent` - **Model**: Claude Sonnet 4 (Anthropic) - - **Voice**: Harry (Vapi) + - **Voice**: Elliot (Vapi) - **First Message**: `Hey I'm Harry, a support agent. How can I help you today? You can ask me questions about Vapi, how to get started or our documentation.` - **System Prompt**: Use a helpful documentation assistant prompt with guidelines for using the docsquery tool 4. Add the `docsquery` tool in the Tools section @@ -274,7 +275,8 @@ Guidelines: // Configure voice settings voice: { provider: "vapi", - voiceId: "Harry" + version: 2, + voiceId: "Elliot" }, // Configure transcription transcriber: { @@ -341,7 +343,8 @@ Guidelines: // Configure voice settings voice={ "provider": "vapi", - "voiceId": "Harry" + "version": 2, + "voiceId": "Elliot" }, // Configure transcription transcriber={ diff --git a/fern/assistants/examples/inbound-support.mdx b/fern/assistants/examples/inbound-support.mdx index d0b726861..7ee43619c 100644 --- a/fern/assistants/examples/inbound-support.mdx +++ b/fern/assistants/examples/inbound-support.mdx @@ -7,7 +7,7 @@ description: Build a voice AI banking support agent with tools for account looku ## Overview -Build a banking support agent with function tools, CSV knowledge bases, and voice test suites. The agent handles account verification, balance inquiries, and transaction history via phone calls. +Build a banking support agent with function tools and CSV knowledge bases. The agent handles account verification, balance inquiries, and transaction history via phone calls. **Agent Capabilities:** * Account lookup and verification via phone number @@ -15,7 +15,6 @@ Build a banking support agent with function tools, CSV knowledge bases, and voic **What You'll Build:** * Retrieval tools and CSV knowledge bases for account/transaction data -* Voice test suites for automated quality assurance * Inbound phone number configuration for 24/7 availability ## Prerequisites @@ -973,180 +972,15 @@ You have access to CSV files with account and transaction data: --- -## 6. Create a Test Suite for an Assistant - - - - - - - Open your [dashboard.vapi.ai](https://dashboard.vapi.ai). - - Below the `Build` section, find and expand the `Test` section. - - In the expanded section, click `Voice Test Suites`. - - - - On the `Test Suites` page, click `Create Test Suite`. - - Click on `New Test Suite` and change the name to `Support Hotline Test Suite`. - - Set the `Assistant` to `Tom`. - - Set the `Phone Number` to `Vapi Support Hotline`. - - Under `Test Cases`, click `Generate Tests`. - - Use the following prompt to generate the test case: - - ```txt title="Test Case Prompt" wordWrap - Test that the assistant can verify a customer account using phone number, retrieve their current balance, and provide recent transaction history. - ``` - - - Accept the generated test case. - - Click `Run Test Suite` to execute the tests. - - - - Click `Run Tests` to execute the tests. - - - - - ```typescript - import { VapiClient } from "@vapi-ai/server-sdk"; - - const vapi = new VapiClient({ token: "YOUR_VAPI_API_KEY" }); - - const testSuite = await vapi.testSuites.create({ - name: "Support Hotline Test Suite", - assistantId: "YOUR_ASSISTANT_ID", - phoneNumberId: "YOUR_PHONE_NUMBER_ID", - testCases: [ - { - name: "Account verification and balance check", - description: "Test that the assistant can verify a customer account using phone number, retrieve their current balance, and provide recent transaction history.", - steps: [ - { - type: "userMessage", - content: "Hi, I need to check my account balance" - }, - { - type: "assertion", - condition: "Assistant asks for phone number verification" - }, - { - type: "userMessage", - content: "My phone number ends in 1234" - }, - { - type: "assertion", - condition: "Assistant provides balance information" - } - ] - } - ] - }); - - console.log(`Test suite created with ID: ${testSuite.id}`); - ``` - - **Next:** Go to your [Vapi Dashboard](https://dashboard.vapi.ai) → Test → Voice Test Suites to run the test suite and view results. - - - ```python - import requests - - def create_test_suite(): - url = "https://api.vapi.ai/test-suite" - headers = { - "Authorization": f"Bearer {YOUR_VAPI_API_KEY}", - "Content-Type": "application/json" - } - - data = { - "name": "Support Hotline Test Suite", - "assistantId": "YOUR_ASSISTANT_ID", - "phoneNumberId": "YOUR_PHONE_NUMBER_ID", - "testCases": [ - { - "name": "Account verification and balance check", - "description": "Test that the assistant can verify a customer account using phone number, retrieve their current balance, and provide recent transaction history.", - "steps": [ - { - "type": "userMessage", - "content": "Hi, I need to check my account balance" - }, - { - "type": "assertion", - "condition": "Assistant asks for phone number verification" - }, - { - "type": "userMessage", - "content": "My phone number ends in 1234" - }, - { - "type": "assertion", - "condition": "Assistant provides balance information" - } - ] - } - ] - } - - response = requests.post(url, headers=headers, json=data) - return response.json() - - # Create the test suite - test_suite = create_test_suite() - print(f"Test suite created with ID: {test_suite['id']}") - ``` - - **Next:** Go to your [Vapi Dashboard](https://dashboard.vapi.ai) → Test → Voice Test Suites to run the test suite and view results. - - - ```bash - # Create the test suite - curl -X POST https://api.vapi.ai/test-suite \ - -H "Authorization: Bearer YOUR_VAPI_API_KEY" \ - -H "Content-Type: application/json" \ - -d '{ - "name": "Support Hotline Test Suite", - "assistantId": "YOUR_ASSISTANT_ID", - "phoneNumberId": "YOUR_PHONE_NUMBER_ID", - "testCases": [ - { - "name": "Account verification and balance check", - "description": "Test that the assistant can verify a customer account using phone number, retrieve their current balance, and provide recent transaction history.", - "steps": [ - { - "type": "userMessage", - "content": "Hi, I need to check my account balance" - }, - { - "type": "assertion", - "condition": "Assistant asks for phone number verification" - }, - { - "type": "userMessage", - "content": "My phone number ends in 1234" - }, - { - "type": "assertion", - "condition": "Assistant provides balance information" - } - ] - } - ] - }' - ``` - - **Next:** Go to your [Vapi Dashboard](https://dashboard.vapi.ai) → Test → Voice Test Suites to run the test suite and view results. - - - ## Next Steps -Just like that, you've built a 24/7 customer support hotline that can handle inbound calls, create support tickets, and run automated tests to ensure it's working as expected. +Just like that, you've built a 24/7 customer support hotline that can handle inbound calls and answer balance and transaction questions. Consider the reading the following guides to further enhance your assistant: -* [**Knowledge Bases**](../knowledge-base/) - Learn more about knowledge bases to build knowledge-based agents. +* [**Knowledge Bases**](/knowledge-base) - Learn more about knowledge bases to build knowledge-based agents. * [**External Integrations**](../tools/) - Configure integrations with [Google Calendar](../tools/google-calendar), [Google Sheets](../tools/google-sheets), [Slack](../tools/slack), etc. -* [**Workflows**](../workflows/) - Learn about workflows to build voice agents for more complex use cases. +* [**Squads**](/squads) - Learn how to compose multiple assistants and transfer seamlessly for complex use cases. Need help? Chat with the team on our [Discord](https://discord.com/invite/pUFNcf2WmH) or mention us on [X/Twitter](https://x.com/Vapi_AI). diff --git a/fern/assistants/examples/lead-qualification.mdx b/fern/assistants/examples/lead-qualification.mdx new file mode 100644 index 000000000..ff761c360 --- /dev/null +++ b/fern/assistants/examples/lead-qualification.mdx @@ -0,0 +1,172 @@ +--- +title: Lead qualification assistant +subtitle: Build an outbound sales assistant that qualifies leads and books meetings using tools +slug: assistants/examples/lead-qualification +description: Build a voice AI outbound sales assistant with BANT data capture, CRM integration, objection handling, and automated follow-ups using Vapi Assistants. +--- + +## Overview + +Create an outbound sales assistant that calls prospects, qualifies them using BANT signals, and books meetings. The assistant uses tools to look up leads, score qualification, update CRM, and schedule on a calendar. + +**Assistant Capabilities:** +* BANT data capture with structured outputs +* Objection handling and call outcome logging +* Calendar booking and follow-up creation +* CRM updates with next steps + +**What You'll Build:** +* Focused sales prompt with clear call flow +* Tools for lead lookup, scoring, CRM update, and scheduling +* Optional CSV knowledge bases for demo leads/products + +## Prerequisites + +* A [Vapi account](https://dashboard.vapi.ai/) +* CRM or spreadsheet data; Google Calendar or scheduling backend + +## 1. Prepare sample data (optional) + + + +
+ + + + + + + + + +
+
+ + + + Upload `leads.csv`, `products.csv`, and `call_outcomes.csv` and note file IDs. + + + + ```typescript + import { VapiClient } from "@vapi-ai/server-sdk"; + import fs from "fs"; + const vapi = new VapiClient({ token: process.env.VAPI_API_KEY! }); + async function upload(p: string) { return (await vapi.files.create({ file: fs.createReadStream(p) })).id; } + const leadsFileId = await upload("leads.csv"); + const productsFileId = await upload("products.csv"); + const outcomesFileId = await upload("call_outcomes.csv"); + ``` + + + +
+ +--- + +## 2. Create sales tools + +Configure function tools or your CRM API for: +- `lookup_lead(leadId)` +- `score_lead(budget, authority, need, timeline)` +- `update_crm(leadId, callOutcome, nextSteps)` +- `book_meeting(prospect, time)` + +See [Custom Tools](/tools/custom-tools) and [Google Calendar](/tools/google-calendar). + +--- + +## 3. Define the assistant + + + + + + - Name: `Outbound SDR` + - First message: concise opener asking permission to talk + + + ```txt title="System Prompt" maxLines=12 + You are an outbound SDR. Goals: get permission, qualify with BANT, schedule a meeting, and log the outcome. Keep answers ≤ 25 words and be respectful. Use tools when needed. + ``` + + + Capture: `permission_status`, `bant_budget`, `bant_authority`, `bant_need`, `bant_timeline`, `meeting_time`, `call_outcome`. + See [Structured outputs](/assistants/structured-outputs). + + + + + ```typescript + import { VapiClient } from "@vapi-ai/server-sdk"; + const vapi = new VapiClient({ token: process.env.VAPI_API_KEY! }); + const systemPrompt = `Outbound SDR. Get permission, qualify with BANT, then book. Keep responses short. Use lookup_lead, score_lead, update_crm, book_meeting.`; + const assistant = await vapi.assistants.create({ + name: "Outbound SDR", + firstMessage: "Hi, this is Alex from TechFlow. Is now a good time to chat for 2 minutes?", + model: { provider: "openai", model: "gpt-4o", messages: [{ role: "system", content: systemPrompt }] } + }); + ``` + + + +--- + +## 4. Make calls + + + + ```typescript title="create web call" + import { VapiClient } from "@vapi-ai/server-sdk"; + const vapi = new VapiClient({ token: process.env.VAPI_API_KEY! }); + await vapi.calls.create({ transport: { type: "web" }, assistant: { assistantId: "your-assistant-id" } }); + ``` + + ```typescript title="create phone call" + await vapi.calls.create({ phoneNumberId: "your-phone-number-id", customer: { number: "+15551234567" }, assistant: { assistantId: "your-assistant-id" } }); + ``` + + + + ```python title="create web call" + import os + from vapi import Vapi + client = Vapi(token=os.getenv("VAPI_API_KEY")) + client.calls.create(transport={"type": "web"}, assistant_id="your-assistant-id") + ``` + + ```python title="create phone call" + client.calls.create(phone_number_id="your-phone-number-id", customer={"number": "+15551234567"}, assistant_id="your-assistant-id") + ``` + + + + ```bash + curl -X POST "https://api.vapi.ai/call/web" \ + -H "Authorization: Bearer $VAPI_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ "assistant": { "assistantId": "your-assistant-id" } }' + ``` + + + + ```bash + curl -X POST "https://api.vapi.ai/call" \ + -H "Authorization: Bearer $VAPI_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ "assistant": { "assistantId": "your-assistant-id" }, "phoneNumberId": "your-phone-number-id", "customer": { "number": "+15551234567" } }' + ``` + + + +## 5. Test outbound calls + +Create a phone number or trigger an outbound call. See [Phone calls](/quickstart/phone). + +## Next steps + +- **CRM integration**: Connect your CRM via [Custom Tools](/tools/custom-tools) +- **Calendar**: [Google Calendar](/tools/google-calendar) +- **Escalation**: Use a [Squad](/squads) to hand off to a specialized closer + diff --git a/fern/assistants/examples/multilingual-agent.mdx b/fern/assistants/examples/multilingual-agent.mdx index 0726fffe5..a85e6fe15 100644 --- a/fern/assistants/examples/multilingual-agent.mdx +++ b/fern/assistants/examples/multilingual-agent.mdx @@ -18,7 +18,7 @@ Build a dynamic customer support agent for GlobalTech International that automat * Advanced prompting for cultural context awareness -**Alternative Approach**: For a more structured multilingual experience with explicit language selection, see our [Workflow-based multilingual support](../../workflows/examples/multilingual-support) that guides customers through language selection and dedicated conversation paths. +**Alternative Approach**: For a more structured multilingual experience with explicit language selection, see our [Squad-based multilingual support](../../squads/examples/multilingual-support) that guides customers through language selection and dedicated conversation paths. ## Prerequisites @@ -298,8 +298,8 @@ We will be creating a dynamic multilingual customer support agent for GlobalTech // Option 2: Google Multilingual const googleTranscriber = { provider: "google", - model: "latest", - language: "multilingual" + model: "gemini-2.0-flash", + language: "Multilingual" }; // Update assistant with transcriber @@ -320,8 +320,8 @@ We will be creating a dynamic multilingual customer support agent for GlobalTech # Option 2: Google Multilingual google_transcriber = { "provider": "google", - "model": "latest", - "language": "multilingual" + "model": "gemini-2.0-flash", + "language": "Multilingual" } # Update assistant with transcriber @@ -356,8 +356,8 @@ We will be creating a dynamic multilingual customer support agent for GlobalTech -d '{ "transcriber": { "provider": "google", - "model": "latest", - "language": "multilingual" + "model": "gemini-2.0-flash", + "language": "Multilingual" } }' ``` @@ -371,49 +371,24 @@ We will be creating a dynamic multilingual customer support agent for GlobalTech ## 4. Configure Multilingual Voice Synthesis - + - 1. In the **Voice** section of your assistant: - 2. **Provider**: Select `Azure` (best multilingual coverage) - 3. **Voice**: Choose primary voice `en-US-AriaNeural` (English) - 4. **Add fallback voices**: - - Spanish: `es-ES-ElviraNeural` (Spain) or `es-MX-DaliaNeural` (Mexico) - - French: `fr-FR-DeniseNeural` (France) or `fr-CA-SylvieNeural` (Canada) - 5. **Alternative providers**: ElevenLabs, OpenAI, or PlayHT all support multiple languages + 1. In the **Voice** section of your assistant, select **Vapi**. + 2. Choose a Vapi Voice. + 3. Set **Version** to `2`. + 4. Leave the language unset, or set it to `auto`. + + Voice fallbacks activate when synthesis fails. They do not select a different voice based on the detected language. ```typescript - // Multi-language voice configuration + // Vapi Voices V2 automatically selects the synthesis language. const multilingualVoice = { - provider: "azure", - voiceId: "en-US-AriaNeural", // Primary English voice - fallbackPlan: { - voices: [ - { - provider: "azure", - voiceId: "es-ES-ElviraNeural" // Spanish (Spain) - }, - { - provider: "azure", - voiceId: "fr-FR-DeniseNeural" // French (France) - }, - { - provider: "azure", - voiceId: "es-MX-DaliaNeural" // Spanish (Mexico) - }, - { - provider: "azure", - voiceId: "fr-CA-SylvieNeural" // French (Canada) - } - ] - } - }; - - // Alternative: ElevenLabs multilingual - const elevenLabsVoice = { - provider: "11labs", - voiceId: "multilingual-v2" // Supports multiple languages + provider: "vapi", + voiceId: "Elliot", + version: 2, + language: "auto" }; await vapi.assistants.update("YOUR_ASSISTANT_ID", { @@ -423,30 +398,12 @@ We will be creating a dynamic multilingual customer support agent for GlobalTech ```python - # Multi-language voice configuration + # Vapi Voices V2 automatically selects the synthesis language. multilingual_voice = { - "provider": "azure", - "voiceId": "en-US-AriaNeural", # Primary English voice - "fallbackPlan": { - "voices": [ - { - "provider": "azure", - "voiceId": "es-ES-ElviraNeural" # Spanish (Spain) - }, - { - "provider": "azure", - "voiceId": "fr-FR-DeniseNeural" # French (France) - }, - { - "provider": "azure", - "voiceId": "es-MX-DaliaNeural" # Spanish (Mexico) - }, - { - "provider": "azure", - "voiceId": "fr-CA-SylvieNeural" # French (Canada) - } - ] - } + "provider": "vapi", + "voiceId": "Elliot", + "version": 2, + "language": "auto" } # Update assistant with voice configuration @@ -467,20 +424,10 @@ We will be creating a dynamic multilingual customer support agent for GlobalTech -H "Content-Type: application/json" \ -d '{ "voice": { - "provider": "azure", - "voiceId": "en-US-AriaNeural", - "fallbackPlan": { - "voices": [ - { - "provider": "azure", - "voiceId": "es-ES-ElviraNeural" - }, - { - "provider": "azure", - "voiceId": "fr-FR-DeniseNeural" - } - ] - } + "provider": "vapi", + "voiceId": "Elliot", + "version": 2, + "language": "auto" } }' ``` @@ -1082,92 +1029,15 @@ Keep responses concise (under 50 words) while being thorough and helpful.""" --- -## Alternative: Workflow-Based Language Selection - -For a more structured approach with explicit language selection, see our comprehensive [Workflow-based multilingual support](../../workflows/examples/multilingual-support) guide. This approach lets customers choose their language at the start of the call, then routes them to dedicated conversation paths optimized for each language. +## Alternative: Squad-Based Language Selection - - - ```typescript - const languageSelectionWorkflow = await vapi.workflows.create({ - name: "GlobalTech Multilingual Workflow", - nodes: [ - { - id: "language_selection", - type: "conversation", - firstMessage: "Hello! Hola! Bonjour! Welcome to GlobalTech International. Please say 'English', 'Español', or 'Français' to continue in your preferred language.", - systemPrompt: "Listen for the customer's language preference and extract it.", - extractVariables: [ - { - name: "preferred_language", - type: "string", - description: "Customer's preferred language", - enum: ["english", "spanish", "french"] - } - ] - }, - { - id: "english_support", - type: "conversation", - condition: "preferred_language == 'english'", - firstMessage: "Thank you for choosing English. I'm Maria, your support representative. How can I help you today?", - systemPrompt: "You are Maria, GlobalTech's English support agent. Be direct, friendly, and professional.", - voice: { - provider: "azure", - voiceId: "en-US-AriaNeural" - } - }, - { - id: "spanish_support", - type: "conversation", - condition: "preferred_language == 'spanish'", - firstMessage: "Gracias por elegir español. Soy María, su representante de soporte. ¿Cómo puedo ayudarle hoy?", - systemPrompt: "Eres María, agente de soporte en español de GlobalTech. Sé cálida, respetuosa y usa 'usted' inicialmente.", - voice: { - provider: "azure", - voiceId: "es-ES-ElviraNeural" - } - }, - { - id: "french_support", - type: "conversation", - condition: "preferred_language == 'french'", - firstMessage: "Merci d'avoir choisi le français. Je suis Maria, votre représentante du support. Comment puis-je vous aider aujourd'hui?", - systemPrompt: "Vous êtes Maria, agent de support français de GlobalTech. Soyez polie, courtoise et formelle.", - voice: { - provider: "azure", - voiceId: "fr-FR-DeniseNeural" - } - } - ] - }); - ``` - - - - **Clearer language selection**: Customers explicitly choose their language - - **Dedicated language paths**: Each language has its own conversation flow - - **Optimized voices**: Language-specific voices for better quality - - **Easier maintenance**: Separate prompts and logic for each language - - **Better analytics**: Track language preferences and usage patterns - - +For a more structured approach with explicit language selection, see our comprehensive [Squad-based multilingual support](/squads/examples/multilingual-support) guide. This approach lets customers choose their language at the start of the call, then routes them to dedicated conversation paths optimized for each language. ## Provider Support Summary -**Speech-to-Text (Transcription):** -- **Deepgram**: Nova 2, Nova 3 with "Multi" language setting -- **Google**: Latest models with "Multilingual" language setting -- **All other providers**: Single language only, no automatic detection - -**Text-to-Speech (Voice Synthesis):** -- **Azure**: 400+ voices across 140+ languages (recommended for coverage) -- **ElevenLabs**: 30+ languages with premium quality -- **OpenAI**: 50+ languages with consistent quality -- **PlayHT**: 80+ languages, cost-effective -- **All providers**: Support multiple languages natively +Automatic detection and code-switching require provider-specific transcriber settings. Review [Multilingual support](/customization/multilingual) and the individual [transcriber provider pages](/providers/transcriber/overview) for current configurations. -**Language Models:** -- **All major LLMs** (GPT-4o, Claude, Gemini, Llama, etc.): Native multilingual support +For speech synthesis, confirm that the selected model and voice support every language in your assistant's system prompt. Vapi Voices V2 can select the synthesis language automatically. Other providers may require a provider-specific model, voice, or language setting. ## Next Steps @@ -1175,9 +1045,9 @@ Just like that, you've built a dynamic multilingual customer support agent that Consider reading the following guides to further enhance your multilingual implementation: -* [**Workflow-based Multilingual Support**](../../workflows/examples/multilingual-support) - Compare with structured language selection approach -* [**Multilingual Configuration Guide**](../../../customization/multilingual) - Learn about all multilingual configuration options -* [**Custom Tools**](../../../tools/custom-tools) - Build advanced multilingual tools and integrations +* [**Squad-based Multilingual Support**](/squads/examples/multilingual-support) - Compare with structured language selection approach +* [**Multilingual Configuration Guide**](/customization/multilingual) - Learn about all multilingual configuration options +* [**Custom Tools**](/tools/custom-tools) - Build advanced multilingual tools and integrations Need help with multilingual implementation? Chat with the team on our [Discord](https://discord.com/invite/pUFNcf2WmH) or mention us on [X/Twitter](https://x.com/Vapi_AI). diff --git a/fern/assistants/examples/support-escalation.mdx b/fern/assistants/examples/support-escalation.mdx index 0e25524c2..0dd42f5af 100644 --- a/fern/assistants/examples/support-escalation.mdx +++ b/fern/assistants/examples/support-escalation.mdx @@ -981,7 +981,6 @@ async function getEscalationWithQueueManagement(context: any) { You've built a sophisticated customer support escalation system using assistants! Consider these enhancements: -* **[Property management call routing](/workflows/examples/property-management)** - Explore the visual workflow approach * **[Call Analysis](/assistants/call-analysis)** - Analyze escalation patterns and optimize routing * **[Custom Tools](/tools/custom-tools)** - Build additional tools for advanced support logic * **[Webhooks](/server-url)** - Learn more about webhook security and advanced event handling diff --git a/fern/assistants/flush-syntax.mdx b/fern/assistants/flush-syntax.mdx index 4ed7c5334..dbdea9579 100644 --- a/fern/assistants/flush-syntax.mdx +++ b/fern/assistants/flush-syntax.mdx @@ -53,8 +53,12 @@ VAPI supports three flush formats with case-insensitive matching: ```html title="Self-closing (Recommended)" - ``` ```html title="Opening tag" - ``` ```html title="Closing tag" + ``` + ```html title="Opening tag" + + ``` + ```html title="Closing tag" + ``` diff --git a/fern/assistants/idle-messages.mdx b/fern/assistants/idle-messages.mdx index f3dd7608b..8aa41ee8a 100644 --- a/fern/assistants/idle-messages.mdx +++ b/fern/assistants/idle-messages.mdx @@ -19,6 +19,43 @@ Idle messages automatically prompt users during periods of inactivity to maintai to avoid interrupting system processes. +## Configure via Dashboard + + + + Open the [Dashboard](https://dashboard.vapi.ai/assistants). Select **Assistants**, then select the assistant you want to configure. + + + + In the assistant editor, find **Idle Messages**, **Max Idle Messages**, and **Idle Timeout**. + + + + Under **Idle Messages**, select **Select idle messages**, then choose one or more preset messages. + + + + Set **Max Idle Messages**, then set **Idle Timeout**. + + + + Select **Publish**, review the changes, then select **Quick Publish**. + + + + + The Dashboard provides preset idle messages. To use custom exact messages or + model-generated messages, configure [Assistant Hooks](/assistants/assistant-hooks). + + + + + + + + + + ## How idle messages work When a user stops speaking, Vapi starts a timer. Based on the configured timeout periods in `customer.speech.timeout` hooks, the assistant will trigger the action, which can be configured to say messages to the user. diff --git a/fern/assistants/keypad-input-settings.mdx b/fern/assistants/keypad-input-settings.mdx new file mode 100644 index 000000000..0e3f3fdaa --- /dev/null +++ b/fern/assistants/keypad-input-settings.mdx @@ -0,0 +1,85 @@ +--- +title: Keypad input settings +subtitle: Configure how an assistant collects keypad input from callers. +description: Keypad input settings let assistants collect caller-entered digits. Configure timeouts and delimiters for menus, codes, and account information during calls. +--- + +Keypad input settings let an assistant receive dual-tone multi-frequency (DTMF) input from a caller. Use them to collect account numbers, menu selections, confirmation codes, and other keypad entries. + +## How keypad input works + +The assistant processes keypad input when the configured timeout expires or the caller enters a delimiter, whichever happens first. Set the timeout to 0 when input should only be processed after the caller enters a delimiter. + +When Vapi processes the collected digits, it adds them to the conversation as a user message, for example, `User's Keypad Entry: 1234`. The entry is available to the model and is saved in the call's messages and transcript when transcript artifacts are enabled. See [Handle sensitive input](#handle-sensitive-input) before collecting confidential values. + +Keypad input receives tones from the caller. The [DTMF tool](/tools/default-tools#dial-keypad-dtmf) does the opposite: it lets the assistant send keypad tones to another phone system, for example, when navigating an interactive voice response (IVR) menu. + +## Configure via Dashboard + + + + Open the [Dashboard](https://dashboard.vapi.ai/assistants). Select **Assistants**, then select the assistant you want to configure. + + + + Select the **Advanced** tab, then locate **Keypad Input Settings**. + + + + Select **Enable Keypad Input**. + + + + Set **Timeout** from 0 to 10 seconds. Set it to 0 to wait for a delimiter. + + + + Under **Delimiter**, choose **#** or **\***. + + + + Select **publish** in the unsaved-changes message to apply the update. + + + +## API fields + +Configure caller keypad input with `keypadInputPlan` when you create or update an assistant: + +| Field | Type | Behavior | +| --- | --- | --- | +| `enabled` | boolean | Enables caller keypad input. Default is `false`. | +| `timeoutSeconds` | number | Waits 0–10 seconds before processing the collected input. Default is 2 seconds. Set it to `0` to wait for a delimiter. | +| `delimiters` | string enum | Processes input when the caller enters `#` or `*`. Allowed values are `#`, `*`, and `""`. | + +This example processes input after 2 seconds or when the caller enters `#`: + +```json +{ + "keypadInputPlan": { + "enabled": true, + "timeoutSeconds": 2, + "delimiters": "#" + } +} +``` + +## Handle sensitive input + +Keypad input can collect general caller data, but sensitive values need additional controls. For payment information, follow the [PCI compliance guide](/security-and-privacy/pci) to isolate collection and prevent sensitive artifacts from being recorded or logged. + +## Troubleshoot keypad input + +| Symptom | Likely cause | What to check | +| --- | --- | --- | +| Input is processed before the delimiter | The timeout expires first. | Increase **Timeout**, or set it to 0 to require a delimiter. | +| Input is never processed | The timeout is 0 and the caller did not enter the configured delimiter. | Confirm the caller enters the selected **Delimiter**. | +| The assistant does not send tones to another system | Keypad input only receives tones from callers. | Add the [DTMF tool](/tools/default-tools#dial-keypad-dtmf) when the assistant must send tones. | + +Keypad input does not have a dedicated call-ended reason. Review the call transcript and logs to confirm whether the assistant received and processed the caller's input. + +## Related + +- [PCI compliance](/security-and-privacy/pci) +- [Built-in call tools](/tools/default-tools) +- [IVR navigation](/ivr-navigation) diff --git a/fern/assistants/model-intelligence/metrics-methodology.mdx b/fern/assistants/model-intelligence/metrics-methodology.mdx new file mode 100644 index 000000000..71a3057c3 --- /dev/null +++ b/fern/assistants/model-intelligence/metrics-methodology.mdx @@ -0,0 +1,93 @@ +--- +title: Performance metrics and methodology reference +subtitle: See how Vapi sources and calculates latency, cost, and quality metrics. +description: The performance metrics reference explains how Vapi sources and calculates latency, cost, and quality data for each supported transcriber, model, and voice. +slug: assistants/model-intelligence/metrics-methodology +--- + +Vapi measures latency from production calls. Cost metrics are calculated estimates. Quality metrics come from Vapi or third-party benchmarks. + +## Source summary + +| Metric | Component | What it measures | Source | +|---|---|---|---| +| **Latency** | Transcriber, model, voice | Typical response time | Median from Vapi production calls | +| **Cost** | Transcriber, model, voice | Estimated cost per minute | [Calculated estimate based on typical usage](/assistants/model-intelligence/understanding-cost) | +| **Word error rate (WER)** | Transcriber | The percentage of words the transcriber gets wrong | [Daily benchmark](https://www.daily.co/blog/benchmarking-stt-for-voice-agents/) | +| **Intelligence** | Model | Reasoning and task capability | [Artificial Analysis benchmark](https://artificialanalysis.ai/models) | +| **Humanness** | Voice | How human the voice sounds | [Vapi Humanness Index](https://humannessindex.vapi.ai/) | + +## Latency + +Vapi reports the median response time for each component based on production calls. + +| Component | Latency measurement | +|---|---| +| Transcriber | Time to convert speech to text | +| Model | Time to first token | +| Voice | Time to first audio from the text-to-speech provider | + +The displayed total is simply the sum of the three component medians, so treat it as a rough estimate rather than an exact figure. + + +The total excludes [endpointing](/customization/speech-configuration) and transport time. + + +See [how latency works](/assistants/model-intelligence/understanding-latency) for help understanding latency and why more capable models tend to be slower. + +## Cost + +In order to estimate cost, we came up with a number of assumptions based on actual Vapi data. However, costs vary greatly depending on actual call performance and agent behavior. The displayed cost is an estimated rate per minute, use it to compare models rather than predict your exact bill. + + +For contracted customers, certain pricing may vary depending on your agreement. Please contact your account team for the most accurate estimate. + + +| Component | Estimation basis | +|---|---| +| Transcriber | Audio minutes for the caller and assistant | +| Model | Prompt size, tool definitions, prompt caching, and provider rates | +| Voice | Characters spoken based on typical speaking volume | + +LLM cost depends on the assistant's configuration. Vapi uses the assistant's prompt and tool definitions, so two assistants on the same model can show different estimates. The calculation also uses each provider's cached-input rate when prompt caching is supported. + + +The estimate assumes a moderate cache-hit rate, so actual costs for large prompts are often lower. It excludes growing conversation history, so actual costs for long calls are often higher. + + +See [how cost works](/assistants/model-intelligence/understanding-cost) for the formulas and assumptions behind each estimate. + +## Quality + +Each component has a quality metric that helps you compare performance. + +### Transcriber word error rate (WER) + +Word error rate (WER) measures the percentage of words a transcriber gets wrong. Lower values are better. A WER of 5% means about 1 in 20 words is transcribed incorrectly. + +Vapi sources WER from [Daily](https://www.daily.co/blog/benchmarking-stt-for-voice-agents/), a third-party speech-to-text benchmark. This provides a consistent comparison across providers instead of relying on self-reported accuracy. + +### Intelligence metric for models + +The **Intelligence** metric measures a model's reasoning and task capability. Vapi sources the score from the [Artificial Analysis](https://artificialanalysis.ai/models) Intelligence Index. This third-party benchmark scores models from 0 to 100 across reasoning and knowledge tasks. + +Voice agents run LLMs with reasoning turned off to keep latency low. The displayed scores reflect reasoning-off performance. The smartest voice agents run at around 20-30 intelligence score, be sure to compare models to each other for a relative benchmark. + +### Humanness metric for voices + +The **Humanness** metric measures how natural a voice sounds. Vapi measures it with the first-party [**Vapi Humanness Index**](https://humannessindex.vapi.ai/). The index uses a blind listening test to score voices from 1 to 100. A higher score means the voice is harder to distinguish from a human. + +## Data refresh schedule + +Vapi refreshes performance metrics weekly as models change and more call data becomes available. The metrics reflect each model at its last update rather than a continuous live feed. + +## Related + + + + The full formulas and assumptions behind the cost estimate. + + + What voice-to-voice latency measures and why it varies by model. + + diff --git a/fern/assistants/model-intelligence/overview.mdx b/fern/assistants/model-intelligence/overview.mdx new file mode 100644 index 000000000..81e8fc0e1 --- /dev/null +++ b/fern/assistants/model-intelligence/overview.mdx @@ -0,0 +1,41 @@ +--- +title: Model Intelligence for transcribers, models, and voices +subtitle: Choose assistant components with curated Model Presets and Performance Metrics. +description: Model Intelligence helps you choose transcribers, models, and voices with curated presets and weekly refreshed performance metrics for latency, cost, and quality. +slug: assistants/model-intelligence/overview +--- + +Model Intelligence is a Vapi feature that helps you choose the transcriber, model, and voice for your assistant. Choose a preset for a strong default combination or compare every option using weekly refreshed performance metrics. + +## Key concepts + +| Term | Definition | +|---|---| +| **Model Presets** | Curated configurations that bundle a transcriber, model, and voice tuned for one goal. | +| **Performance metrics** | The latency, cost, and quality metrics shown on every component, so you can compare options directly. | +| **Customized** | The state an assistant moves to when you change any single component away from its preset. | + +## How it works + +When building a voice agent, Vapi orchestrates the transcriber, model, and voice. You can swap each component for any supported provider and model, which gives you flexibility when building an assistant. + +**Model Presets** bundle the three components into a curated combination. Choose **Balanced**, **High Intelligence**, **Ultra Fast**, or **Cost Saver** based on your goal. Presets provide a dependable setup without requiring you to tune each component. + +**Performance metrics** show latency, cost, and quality data for every transcriber, model, and voice. The data appears on component panels and the dropdown menu for each component. Use it to compare options and build the combination your assistant needs. See the [performance metrics reference](/assistants/model-intelligence/metrics-methodology) for how each metric is sourced and calculated. + +If you change one component from its preset, the assistant moves to **Customized**. Every other preset setting remains unchanged, and you can continue editing any component. + +## Start with presets and optimize with performance metrics + +[Model Presets](/assistants/model-intelligence/presets) give you a dependable starting point when you do not know which component to choose. [Performance metrics](/assistants/model-intelligence/metrics-methodology) help you compare options and optimize your configuration with data instead of guessing. + +## Related + + + + See all four presets, when to use each, and how to apply or customize one. + + + How every latency, cost, and quality metric is sourced. + + diff --git a/fern/assistants/model-intelligence/presets.mdx b/fern/assistants/model-intelligence/presets.mdx new file mode 100644 index 000000000..5fc27b594 --- /dev/null +++ b/fern/assistants/model-intelligence/presets.mdx @@ -0,0 +1,119 @@ +--- +title: Model Presets for transcribers, models, and voices +subtitle: Configure an assistant's transcriber, model, and voice with one preset. +description: Model presets optimize for balanced performance, reasoning, low latency, or low cost. Learn when to use each preset and how to apply or customize its configuration. +slug: assistants/model-intelligence/presets +--- + +**Model Presets** are curated configurations that bundle a transcriber, model, and voice for a specific goal. Use a preset for a dependable setup or as a starting point for further customization. + +## How it works + +New assistants use **Balanced** as the default. When you start from one of Vapi’s use-case templates, the assistant uses the preset that best fits the template. + +Presets are a starting point rather than a lock - you can fine-tune or swap out any component to better fit your use case. + +## Presets at a glance + +| Preset | Optimizes for | Best for | +|---|---|---| +| **Balanced** | A strong all-round mix of quality, speed, and cost | Most assistants; start here if you're unsure | +| **High Intelligence** | Reasoning and conversation quality | Complex, nuanced, or high-stakes conversations | +| **Ultra Fast** | Lowest latency | Fast, responsive, high-volume conversations | +| **Cost Saver** | Lowest cost per minute | Simple, high-volume calls where cost matters most | + +## Choose a preset + +Choose the preset that best matches your use case. Start with **Balanced** if you are unsure. + +### Balanced + +**Balanced** is the default for new assistants and the best starting point for most use cases. It provides a strong mix of quality, responsiveness, and cost. + +Choose **Balanced** when any of the following apply. + +- You're building a new assistant and aren't sure which preset fits. +- Your use case covers support, scheduling, FAQs, or qualification. +- You want an all-around dependable setup out of the box. + + +If you later need more reasoning, faster responses, or lower cost, switch to the preset built for that. + + +### High Intelligence + +**High Intelligence** prioritizes reasoning and conversation quality. Use it when the assistant needs to handle nuance, follow multi-step logic, or reason reliably across tools and context. + +Choose **High Intelligence** when any of the following apply. + +- Conversations are complex, open-ended, or high-stakes. +- The assistant needs to reason through multi-step problems or use tools reliably. +- Accuracy and quality matter more than speed or cost. + + +More capable models respond a little slower and cost more per minute than **Balanced**. See [how latency works](/assistants/model-intelligence/understanding-latency) for why more capable models take longer to respond. + + +### Ultra Fast + +**Ultra Fast** prioritizes low latency and responsive conversations. Use it when response speed matters more than complex reasoning. + +Choose **Ultra Fast** when any of the following apply. + +- Responsiveness is the priority and replies should feel fast. +- Calls are high-volume and relatively straightforward. +- The flow is scripted or transactional rather than open-ended. + + +The fastest models are smaller and less capable, so **Ultra Fast** may not suit complex reasoning or heavy tool use. Choose **Balanced** or **High Intelligence** if difficult tasks produce quality issues. + + +### Cost Saver + +**Cost Saver** prioritizes the lowest cost per minute. Use it for high-volume calls when cost is the main constraint. + +Choose **Cost Saver** when any of the following apply. + +- Call volume is high and you're optimizing spend. +- Interactions are simple or scripted. +- A small quality trade-off is acceptable in exchange for lower cost. + + +The lowest-cost models are less capable, so this preset fits simpler interactions best. See [how cost works](/assistants/model-intelligence/understanding-cost) for what drives cost per minute. + + +## The Customized state + +Swapping a model out of any component moves your assistant to **Customized** and the **Performance Metrics** displayed will update to match the new configuration. + +## Apply a Model Preset + + + + Open your assistant in the Vapi Dashboard, then open **Assistant**. + + + Choose an option under **Model Presets**. The transcriber, model, voice, and displayed totals update to match the preset. + + + Click the pencil icon on the transcriber, model, or voice panel. Use the dropdown menu in the settings panel to switch out the model or provider. Your assistant moves to **Customized**. **Performance Metrics** update to reflect your choices. + + + Click **Publish** to apply your changes. + + + +## Verify the configuration + +The option you chose is highlighted under **Model Presets**. Confirm the component panels and displayed totals match the preset or your custom configuration. + +## Related + + + + Learn how presets and performance metrics help you choose components. + + + How every latency, cost, and quality metric is sourced. + + diff --git a/fern/assistants/model-intelligence/understanding-cost.mdx b/fern/assistants/model-intelligence/understanding-cost.mdx new file mode 100644 index 000000000..1aa8d4092 --- /dev/null +++ b/fern/assistants/model-intelligence/understanding-cost.mdx @@ -0,0 +1,97 @@ +--- +title: How voice agent component costs and estimates work +subtitle: Learn what drives costs across the transcriber, model, and voice. +description: Understand how Vapi estimates transcriber, model, and voice costs per minute, including prompt caching assumptions and the effects of conversation history. +slug: assistants/model-intelligence/understanding-cost +--- + +The cost to run a voice agent mainly depends on the costs of the transcriber, LLM, and voice. Each component uses a different billing unit, so we've made some assumptions in order to provide a way for you to compare estimated cost per minute. + + +The Cost number within **Performance Metrics** provide estimates for comparison rather than exact quotes. Use them to compare models consistently and understand what affects cost. See [Vapi pricing](https://vapi.ai/pricing) for current pricing. For contracted customers, certain pricing may depend on your agreement, please contact your account team for contract-specific rates. + + +## Key concepts + +| Term | Definition | +|---|---| +| Input tokens per minute | Tokens sent to the model each minute based on your prompt size, tool-definition size, and a typical request rate. | +| Effective input rate | The per-token input rate blended between standard and cached rates when the model supports prompt caching. | +| Output tokens per minute | Tokens the model generates each minute based on typical Vapi call data. | + +## Component billing units + +Each component uses a different billing unit. + +| Component | Billing unit | +|---|---| +| Transcriber | Minutes of audio | +| Model | 1 million input and output tokens | +| Voice | Characters of spoken text | + +### Transcriber cost + +Transcription is billed per minute of audio. Vapi transcribes audio from both the caller and the assistant. The estimate therefore includes two audio channels. This cost scales with call duration rather than your prompt or configuration. + +### Voice cost + +The Voice model is billed per character of spoken text. The estimate uses the number of characters spoken in a typical minute. Cost increases when the assistant speaks more. + +### LLM cost + +Model cost varies more than transcriber or voice cost because it heavily depends on the assistant's configuration. Vapi calculates the estimate from the assistant's actual prompt and tool definitions, so two assistants using the same LLM model can show different cost estimates. + +The estimate uses each provider's input and output token rates. + +| Calculation | Formula | +|---|---| +| **Input cost** | Input tokens per minute × effective input rate | +| **Output cost** | Output tokens per minute × output rate | +| **Estimated model cost per minute** | Input cost + output cost | + +#### Input tokens per minute + +**Input tokens per minute** is the largest cost factor you can control. Vapi calculates it from your [system prompt](/prompting-guide), [tool definitions](/tools), and a typical number of model requests per minute. Longer prompts and more tools increase the estimate, while leaner configurations reduce it. + +Vapi estimates 5 requests per turn. We use number of requests rather than conversational turns, since a single turn can trigger multiple requests, and providers bill each request. + +#### Effective input rate + +**Effective input rate** accounts for prompt caching. Cached input is stable prompt content that providers reuse across requests. Many providers offer a discounted rate for this input. + +When a model supports caching, Vapi blends its standard and cached rates based on an assumed 50% cache hit rate. Otherwise, Vapi uses the standard rate. The calculation uses the actual rates for each model and provider. + +#### Output tokens per minute + +Vapi estimates 150 **output tokens per minute** based on typical generated speech in production call data. It prices those tokens at the model’s output rate. + +## Estimate limitations + +Two assumptions can cause actual model cost to differ from the estimate. + +| Scenario | Typical effect | Reason | +|---|---|---| +| Large prompts with caching supported | Actual cost is often lower | Actual cache use is usually higher than the estimate assumes | +| Long calls | Actual cost is often higher | Growing conversation history is sent again with each request | + +These deliberate simplifications keep estimates comparable across models. Vapi may refine them over time. + +## Reduce cost + +You can reduce cost in four ways. + +- Shorten your system prompt and tool definitions. This often has the largest effect on model cost. +- Use models that support prompt caching for large, stable prompts. Providers charge less for prompt content reused from cache, which lowers model cost. +- Choose a lower-cost model when the use case allows. The [Cost Saver preset](/assistants/model-intelligence/presets#cost-saver) optimizes components for the lowest cost per minute. +- Keep calls focused. Shorter, more focused conversations cost less and tend to provide a better experience. + +## Related + + + + Compare presets or apply Cost Saver. + + + See how Vapi calculates model cost estimates. + + diff --git a/fern/assistants/model-intelligence/understanding-latency.mdx b/fern/assistants/model-intelligence/understanding-latency.mdx new file mode 100644 index 000000000..42d9af059 --- /dev/null +++ b/fern/assistants/model-intelligence/understanding-latency.mdx @@ -0,0 +1,59 @@ +--- +title: How voice-to-voice latency works in voice agents +subtitle: Learn what voice-to-voice latency measures and why capable models respond more slowly. +description: Understand voice-to-voice latency, the components included in Vapi performance metrics, and how model capability, endpointing, and transport affect response time. +slug: assistants/model-intelligence/understanding-latency +--- + +Voice-to-voice latency is the gap between when a caller finishes speaking and when your assistant starts responding. It is a major factor in whether a conversation feels natural or frustrating. This page explains how Vapi measures latency and how to compare models. + +## Voice-to-voice latency sequence + +Voice-to-voice latency combines five stages that run in sequence. Each stage begins after the previous one. + +1. **Transport:** The caller's audio travels over the network for processing. +2. **Endpointing:** Vapi detects that the caller has finished speaking. +3. **Transcription:** The transcriber converts the caller's speech to text. +4. **Model response:** The model reads the transcript and begins generating a reply. Vapi measures this stage as time to first token. +5. **Speech synthesis:** The voice provider turns the reply into audio. Vapi measures this stage as time to first audio. + +A caller's total voice-to-voice latency is roughly the sum of all five stages. + +## What the displayed latency measures + +**Performance metrics** show latency for each component. The displayed total adds the median latency for the transcriber, model, and voice. This should be treated as a rough estimate. + +Vapi calculates each median from production calls, which reflect a typical call - half of calls are faster and half are slower. Individual calls can vary. + +The displayed total excludes [endpointing](/customization/speech-configuration) and transport time. Both contribute to the delay a caller experiences. Endpointing can account for a meaningful share of that delay. Improving endpointing can make an assistant feel more responsive even though it is not included in the displayed total. + +## Model capability and latency + +More capable models usually respond more slowly. A model's time to first token is often the largest component of voice-to-voice latency. More capable models tend to be larger and take longer to begin generating a response. + +[**Ultra Fast**](/assistants/model-intelligence/presets#ultra-fast) uses speed-optimized models for lower latency. [**High Intelligence**](/assistants/model-intelligence/presets#high-intelligence) accepts higher latency for greater capability. Neither preset is always better than the other; choose based on whether your use case needs faster responses or stronger reasoning. + +## How to judge latency + +Use the displayed latency to compare models and then test the assistant in a real conversation. + +- Lower latency improves the experience only until callers stop noticing the difference. +- People naturally pause between turns. A response can feel natural without being instant. +- Endpointing, turn-taking, and silence handling all affect how latency feels. + +Testing the assistant in a real conversation provides the most reliable evaluation. A model with slightly higher latency can still feel natural. Choosing the lowest number may sacrifice capability that your use case needs. + + +Other latency figures may use ideal lab conditions or measure only one component, while Vapi reports medians from actual production calls. Compare figures only when their scope and conditions match. + + +## Related + + + + Compare presets or apply Ultra Fast. + + + See how Vapi calculates latency. + + diff --git a/fern/assistants/pronunciation-dictionaries.mdx b/fern/assistants/pronunciation-dictionaries.mdx index 03dfa698b..3c2f7d361 100644 --- a/fern/assistants/pronunciation-dictionaries.mdx +++ b/fern/assistants/pronunciation-dictionaries.mdx @@ -8,7 +8,24 @@ slug: assistants/pronunciation-dictionaries Pronunciation dictionaries allow you to customize how your AI assistant pronounces specific words, names, acronyms, or technical terms. This feature is particularly useful for ensuring consistent pronunciation of brand names, proper nouns, or industry-specific terminology that might be mispronounced by default. -**Note:** Pronunciation dictionaries are exclusive to ElevenLabs voices and require specific model configurations. +Pronunciation dictionaries are supported by the following voice providers: + +- **ElevenLabs** — phoneme rules (IPA and CMU Arpabet) and alias rules +- **Cartesia** — "sounds-like" aliases and IPA notation (sonic-3 model only) +- **Vapi built-in voices** — pronunciation dictionaries via a unified locator + +## Dictionary routing + +Adding a pronunciation dictionary to a Vapi Voice can change its underlying text-to-speech provider. For example, adding a Cartesia dictionary to a supported Vapi Voice v2 configuration routes the voice through Cartesia Sonic 3.5, with xAI as a fallback. + +Voice markup is provider-specific. xAI uses [speech tags](https://docs.x.ai/developers/model-capabilities/audio/text-to-speech#speech-tags), while Cartesia uses [SSML-like tags](https://docs.cartesia.ai/build-with-cartesia/capability-guides/ssml-tags). Vapi does not translate markup between providers, so a tag supported by one provider might be spoken aloud by another instead of being applied. + +Choose your pacing approach based on whether portability or precise timing matters more: + +- **For pacing across providers**, use commas, semicolons, and periods. These produce more consistent pacing across TTS providers than provider-specific markup. +- **For precise timing**, use markup supported by the active primary provider. For example, a supported Vapi Voice v2 configuration with a Cartesia dictionary routes through Cartesia, so use Cartesia [`` tags](https://docs.cartesia.ai/build-with-cartesia/capability-guides/ssml-tags#pauses-and-breaks). + +Test prompt formatting after adding or removing a pronunciation dictionary. If you use provider-specific markup, also test the fallback route; the xAI fallback might not interpret Cartesia markup as intended. ## How Pronunciation Dictionaries Work @@ -47,13 +64,16 @@ Corrected pronunciations: ## Prerequisites -- A Vapi assistant configured with an ElevenLabs voice -- Understanding of phonetic notation (IPA or CMU Arpabet) for phoneme-based rules +- A Vapi assistant configured with an **ElevenLabs**, **Cartesia**, or **Vapi** voice +- For ElevenLabs: understanding of phonetic notation (IPA or CMU Arpabet) for phoneme-based rules +- For Cartesia: the `sonic-3` voice model (pronunciation dictionaries are only available on sonic-3) - Access to Vapi's API for dictionary creation ## Types of Pronunciation Rules -### Phoneme Rules +### ElevenLabs Rules + +#### Phoneme Rules Phoneme rules specify exact pronunciation using phonetic alphabets. These provide the most precise control over pronunciation. @@ -66,15 +86,28 @@ Phoneme rules only work with specific ElevenLabs models: - `eleven_turbo_v2` - `eleven_flash_v2` -### Alias Rules +#### Alias Rules Alias rules replace words with alternative spellings or phrases. These work with all ElevenLabs models and are useful for: - Converting acronyms to full phrases (e.g., "UN" → "United Nations") - Providing phonetic spellings for difficult words - Standardizing pronunciation across different contexts +### Cartesia Rules + +Cartesia pronunciation dictionaries use a `text` and `alias` format. Each entry maps a word to its pronunciation. Cartesia supports two alias styles: + +- **Sounds-like guidance**: A plain-English hint for how to say the word (e.g., `"VAH-pee"`) +- **IPA notation**: Precise phonetic spelling wrapped in angle brackets (e.g., `"<<ˈ|v|ɑ|ˈ|p|i>>"`) + + + Cartesia pronunciation dictionaries are only available with the `sonic-3` (or newer) model. In the dashboard, the pronunciation dictionary option only appears once you select a supported model. + + ## Implementation +### ElevenLabs + Use Vapi's API to create a pronunciation dictionary with your custom rules. @@ -116,7 +149,13 @@ Alias rules replace words with alternative spellings or phrases. These work with "pronunciationDictionaryId": "rjshI10OgN6KxqtJBqO4", "versionId": "xJl0ImZzi3cYp61T0UQG", "name": "My Custom Dictionary", - "rules": [...], + "rules": [ + { + "stringToReplace": "UN", + "type": "alias", + "alias": "United Nations" + } + ], "createdAt": "2024-01-15T10:30:00Z" } ``` @@ -153,6 +192,99 @@ Alias rules replace words with alternative spellings or phrases. These work with +### Cartesia + + + + Use Vapi's API to create a Cartesia pronunciation dictionary. + + ```bash + POST https://api.vapi.ai/provider/cartesia/pronunciation-dictionary + Content-Type: application/json + Authorization: Bearer YOUR_API_KEY + ``` + + ```json + { + "name": "My Cartesia Dictionary", + "items": [ + { + "text": "Vapi", + "alias": "VAH-pee" + }, + { + "text": "Nginx", + "alias": "Engine-X" + }, + { + "text": "GIF", + "alias": "<<ˈ|dʒ|ɪ|f>>" + } + ] + } + ``` + + The API will respond with a dictionary object containing an `id` you'll use in the next step. + + + + Add the pronunciation dictionary ID to your Cartesia voice configuration. + + ```json + { + "voice": { + "model": "sonic-3", + "voiceId": "your-cartesia-voice-id", + "provider": "cartesia", + "pronunciationDictId": "dict_abc123" + } + } + ``` + + + + Create a test call or use the Vapi playground to verify that your custom pronunciations are working correctly. + + + +### Vapi Built-in Voices + + + + For Vapi v1 built-in voices, create the pronunciation dictionary through the ElevenLabs endpoint shown above. The response includes both a dictionary ID and a `versionId`; keep both values. + + Vapi built-in voices use a unified `pronunciationDictionary` field, but most v1 built-in voices route through ElevenLabs under the hood. Do not assume a Cartesia dictionary ID works with every Vapi built-in voice. Cartesia dictionary IDs only apply to Vapi voices that are routed to a Cartesia Sonic voice path. + + + + Add the ElevenLabs pronunciation dictionary locator to your Vapi voice configuration. + + ```json + { + "voice": { + "provider": "vapi", + "version": 1, + "voiceId": "Kylie", + "pronunciationDictionary": [ + { + "pronunciationDictId": "rjshI10OgN6KxqtJBqO4", + "versionId": "xJl0ImZzi3cYp61T0UQG" + } + ] + } + } + ``` + + + For ElevenLabs-backed dictionaries, `versionId` is required. It pins the exact dictionary version that the Vapi voice should use. + + + + + Create a test call or use the Vapi playground to verify that your custom pronunciations are working correctly. + + + ## Using Your Own ElevenLabs Account (BYOK) If you're using your own ElevenLabs API key (Bring Your Own Key), you can create pronunciation dictionaries directly in your ElevenLabs account and reference them in Vapi: @@ -179,14 +311,16 @@ If you're using your own ElevenLabs API key (Bring Your Own Key), you can create ## Managing Pronunciation Dictionaries -### List Your Dictionaries +### ElevenLabs + +#### List Your Dictionaries ```bash GET https://api.vapi.ai/provider/11labs/pronunciation-dictionary Authorization: Bearer YOUR_API_KEY ``` -### Update Dictionary Rules +#### Update Dictionary Rules ```bash PATCH https://api.vapi.ai/provider/11labs/pronunciation-dictionary/{dictionaryId} @@ -207,6 +341,34 @@ Authorization: Bearer YOUR_API_KEY } ``` +### Cartesia + +#### List Your Dictionaries + +```bash +GET https://api.vapi.ai/provider/cartesia/pronunciation-dictionary +Authorization: Bearer YOUR_API_KEY +``` + +#### Update Dictionary Items + +```bash +PATCH https://api.vapi.ai/provider/cartesia/pronunciation-dictionary/{dictionaryId} +Content-Type: application/json +Authorization: Bearer YOUR_API_KEY +``` + +```json +{ + "items": [ + { + "text": "Vapi", + "alias": "VAH-pee" + } + ] +} +``` + ## Best Practices @@ -214,14 +376,14 @@ Authorization: Bearer YOUR_API_KEY - **Order Matters**: Rules are applied in the order they appear in the dictionary. The first matching rule is used. - **Testing**: Always test pronunciation changes with your specific voice and model combination. - **Phoneme Accuracy**: Ensure proper stress marking for multi-syllable words when using phoneme rules. -- **Model Compatibility**: Remember that phoneme rules only work with specific ElevenLabs models. +- **Model Compatibility**: ElevenLabs phoneme rules only work with `eleven_turbo_v2` and `eleven_flash_v2`. Cartesia pronunciation dictionaries require the `sonic-3` model. ## Common Issues **Pronunciation Not Applied** -- Verify you're using a compatible ElevenLabs model for phoneme rules -- Check that the `stringToReplace` exactly matches the text in your content (case-sensitive) +- Verify you're using a compatible model (ElevenLabs phoneme rules need specific models; Cartesia needs `sonic-3`) +- Check that the word to replace exactly matches the text in your content (case-sensitive) - Ensure the pronunciation dictionary is properly referenced in your voice configuration **SSML Conflicts** @@ -230,4 +392,4 @@ Authorization: Bearer YOUR_API_KEY **Performance Impact** - Large dictionaries may slightly increase processing time -- Consider organizing rules by frequency of use for optimal performance \ No newline at end of file +- Consider organizing rules by frequency of use for optimal performance diff --git a/fern/assistants/quickstart.mdx b/fern/assistants/quickstart.mdx new file mode 100644 index 000000000..f7f35262b --- /dev/null +++ b/fern/assistants/quickstart.mdx @@ -0,0 +1,275 @@ +--- +title: Assistants quickstart +subtitle: Build your first assistant and make a phone call in minutes +slug: assistants/quickstart +--- + +## Overview + +Create a voice assistant, connect it to a phone number, and make your first calls. You can complete this quickstart in the Dashboard or with the Vapi API. + +**In this quickstart, you'll:** + +- Create and test an assistant +- Connect the assistant to a phone number +- Make inbound and outbound calls + +## Prerequisites + +- [A Vapi account](https://dashboard.vapi.ai) +- For cURL or SDK requests, a [Vapi API key](/security-and-privacy/api-keys) + +## 1. Create an assistant + + +By default, when you create an assistant, the transcriber, model, and voice are set to the [Balanced preset](/assistants/model-intelligence/presets#balanced). + + + + + + + Open the [Dashboard](https://dashboard.vapi.ai) and select **Assistants**. + + + + Select **Create Assistant** to create a blank assistant. + + + To start from a predefined template instead, select the down arrow next to **Create Assistant**, then choose a template. + + + + + Replace the content in **First Message** and **System Prompt** with the following examples. + + **First message** + + ```txt title="First message" wordWrap + Hello! How can I help you today? + ``` + + **System prompt** + + ```txt title="System prompt" wordWrap + You are a friendly phone support assistant. Greet the caller and offer help. Keep responses under 30 words. If a transfer is requested, confirm the reason first. + ``` + + + Assistant editor with First Message and System Prompt fields visible and the other assistant names blurred + + + + + Select **Publish**, review the changes, then select **Quick Publish**. Publishing creates a new [assistant version](/assistants/versioning/versioning-assistants). + + + + Select **Talk** to start a web call. When prompted, allow the Dashboard to use your microphone. + + + + + + + + Export your Vapi API key as an environment variable. + + ```bash + export VAPI_API_KEY="YOUR_VAPI_API_KEY" + ``` + + + + ```bash + curl --request POST \ + --url https://api.vapi.ai/assistant \ + --header "Authorization: Bearer $VAPI_API_KEY" \ + --header "Content-Type: application/json" \ + --data '{ + "name": "Support Assistant", + "firstMessage": "Hello! How can I help you today?", + "model": { + "provider": "openai", + "model": "gpt-4o", + "messages": [ + { + "role": "system", + "content": "You are a friendly phone support assistant. Greet the caller and offer help. Keep responses under 30 words. If a transfer is requested, confirm the reason first." + } + ] + } + }' + ``` + + Copy the `id` from the response. You will use it as `YOUR_ASSISTANT_ID` in the next steps. + + + + + + ```typescript + import { VapiClient } from "@vapi-ai/server-sdk"; + + const vapi = new VapiClient({ token: process.env.VAPI_API_KEY! }); + + const assistant = await vapi.assistants.create({ + name: "Support Assistant", + firstMessage: "Hello! How can I help you today?", + model: { + provider: "openai", + model: "gpt-4o", + messages: [ + { + role: "system", + content: "You are a friendly phone support assistant. Greet the caller and offer help. Keep responses under 30 words. If a transfer is requested, confirm the reason first." + } + ] + } + }); + ``` + + + +## 2. Connect a phone number + + + + + + Open the [Dashboard](https://dashboard.vapi.ai) and select **Phone Numbers**. + + + + Select **Create Phone Number**, then choose **Free Vapi Number**. To use a number from another provider, choose the corresponding import option instead. + + + Create Phone Number dialog with Free Vapi Number selected and the Area Code field visible + + + + + Enter a three-digit US area code in **Area Code**, then select **Create**. + + Your first free Vapi number does not require a payment method. To create additional free Vapi numbers, add a payment method. You can create up to five free Vapi numbers in total. + + + Free Vapi phone numbers support US area codes only. For international use, import a number from another provider. + + + + + Open the phone number. Under **Inbound Settings**, choose the assistant you created in **Assistant**, then select **Save**. + + + + + + + + Replace `YOUR_ASSISTANT_ID` with the assistant ID returned in the previous section. + + ```bash + curl --request POST \ + --url https://api.vapi.ai/phone-number \ + --header "Authorization: Bearer $VAPI_API_KEY" \ + --header "Content-Type: application/json" \ + --data '{ + "provider": "vapi", + "numberDesiredAreaCode": "415", + "assistantId": "YOUR_ASSISTANT_ID" + }' + ``` + + Copy the `id` from the response. You will use it as `YOUR_PHONE_NUMBER_ID` to make an outbound call. + + + + + + ```typescript + const phoneNumber = await vapi.phoneNumbers.create({ + provider: "vapi", + numberDesiredAreaCode: "415", + assistantId: assistant.id + }); + ``` + + + +## 3. Make your first calls + +### Test an inbound call + +Call the phone number you created. Your assistant answers with its configured first message. + +### Place an outbound call + + + + + + Open the [Dashboard](https://dashboard.vapi.ai), select **Phone Numbers**, then select the phone number that will place the call. + + + + Select **Test**. + + + + Choose **Single Number**, enter the destination phone number, and choose your assistant in **Assistant**. + + + + Select **Call** to start the call immediately, or select **Schedule Call** to place it later. + + + + + Test Outbound Call panel with Single Number, destination number, and assistant controls + + + + + ```bash + curl --request POST \ + --url https://api.vapi.ai/call \ + --header "Authorization: Bearer $VAPI_API_KEY" \ + --header "Content-Type: application/json" \ + --data '{ + "phoneNumberId": "YOUR_PHONE_NUMBER_ID", + "assistantId": "YOUR_ASSISTANT_ID", + "customer": { + "number": "+15551234567" + } + }' + ``` + + + + ```typescript + await vapi.calls.create({ + phoneNumberId: phoneNumber.id, + assistantId: assistant.id, + customer: { number: "+15551234567" } + }); + ``` + + + +## Next steps + +- **Add tools**: [Custom tools](/tools/custom-tools) +- **Tune speech**: [Speech configuration](/customization/speech-configuration) +- **Use a preset**: [Model Intelligence presets](/assistants/model-intelligence/presets) bundle a transcriber, model, and voice for common use cases. +- **Structure data**: [Structured outputs](/assistants/structured-outputs) +- **Move to multi-assistant**: [Squads](/squads) diff --git a/fern/assistants/retrieve-call-artifacts.mdx b/fern/assistants/retrieve-call-artifacts.mdx new file mode 100644 index 000000000..de82e44ba --- /dev/null +++ b/fern/assistants/retrieve-call-artifacts.mdx @@ -0,0 +1,74 @@ +--- +title: Retrieve call artifacts +subtitle: Download recordings and call logs from Vapi's private storage using authenticated, short-lived URLs. +description: How to download call recordings and logs from Vapi's private storage using your Private API Key and short-lived, authenticated redirect URLs. +slug: assistants/retrieve-call-artifacts +--- + +## Overview + + +Call recording storage is now access-controlled. If your integration fetches recordings, logs, PCAP, or video directly, migrate to the authenticated endpoints below to avoid disruption. + +Some private storage URLs contain `hipaa-recordings` in the path. That's an internal naming detail, it doesn't mean HIPAA applies to your account. + + +Call recordings and logs are stored in a private bucket. These URLs aren't directly downloadable. + +To retrieve a recording or log file, call the Vapi API with a [Vapi private API key](/security-and-privacy/api-keys). The API responds with a `302` redirect to a short-lived, authenticated download URL. + + + Never expose your Private API Key in client-side code or commit it to version control. Store it as a secret in your backend environment. + + +## Get your private API key + +Follow the [Vapi API key guide](/security-and-privacy/api-keys) to create, view, or copy a private key. + +## Integration + +To download or retrieve a recording or log file, send your Private API Key in the `Authorization` header: + +``` +Authorization: Bearer +``` + +Each endpoint responds with a `302` redirect to a short-lived signed URL. Most HTTP clients follow redirects by default — for example, `curl -L` follows the redirect and downloads the artifact in a single command. + +## Available endpoints + +Base URL: `https://api.vapi.ai` + +| Endpoint | Returns | +| --- | --- | +| `GET /call/{id}/mono-recording` | Combined mono recording (WAV/MP3) | +| `GET /call/{id}/stereo-recording` | Stereo recording, customer + assistant on separate channels (WAV/MP3) | +| `GET /call/{id}/customer-recording` | Customer-only mono recording (WAV/MP3) | +| `GET /call/{id}/assistant-recording` | Assistant-only mono recording (WAV/MP3) | +| `GET /call/{id}/video-recording` | Video recording, when enabled (MP4) | +| `GET /call/{id}/call-logs` | Structured call logs (gzipped JSONL) | +| `GET /call/{id}/pcap` | Packet capture, when enabled (PCAP) | + +## Example + +Download a stereo recording for a given call: + +```bash +curl -L \ + -H "Authorization: Bearer $VAPI_PRIVATE_API_KEY" \ + -o recording.wav \ + https://api.vapi.ai/call//stereo-recording +``` + +Download call logs: + +```bash +curl -L \ + -H "Authorization: Bearer $VAPI_PRIVATE_API_KEY" \ + -o call-logs.jsonl.gz \ + https://api.vapi.ai/call//call-logs +``` + + + Signed URLs returned by these endpoints expire after a short period. Always request a fresh URL from the API rather than caching the redirect target. + diff --git a/fern/assistants/structured-outputs-examples.mdx b/fern/assistants/structured-outputs-examples.mdx index 26560fc24..36472a2f5 100644 --- a/fern/assistants/structured-outputs-examples.mdx +++ b/fern/assistants/structured-outputs-examples.mdx @@ -1122,6 +1122,67 @@ Process loan or credit applications with financial information. ``` +## Conditional extraction + +Attach [conditions](/assistants/structured-outputs#conditional-generation) to a structured output so it only runs when a call is worth analyzing. This keeps noisy, incomplete calls out of your data and makes the reason for a skip visible in the assistant preview, call logs, and sessions. + +This example only extracts a post-call outcome when the customer actually reached and ended the conversation (at least 6 messages, 15 seconds, and a customer-ended call): + + +```typescript title="TypeScript (Server SDK)" +const outcome = await vapi.structuredOutputs.create({ + name: "Call Outcome", + type: "ai", + description: "Capture the outcome and any follow-up requested by the customer", + schema: { + type: "object", + properties: { + outcome: { + type: "string", + enum: ["resolved", "callback-requested", "escalated", "no-resolution"] + }, + followUpNotes: { type: "string" } + }, + required: ["outcome"] + }, + conditions: [ + { type: "minMessages", count: 6 }, + { type: "minCallDuration", seconds: 15 }, + { type: "endedReason", operator: "oneOf", values: ["customer-ended-call"] } + ] +}); +``` + +```bash title="cURL" +curl -X POST https://api.vapi.ai/structured-output \ + -H "Authorization: Bearer $VAPI_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "name": "Call Outcome", + "type": "ai", + "description": "Capture the outcome and any follow-up requested by the customer", + "schema": { + "type": "object", + "properties": { + "outcome": { + "type": "string", + "enum": ["resolved", "callback-requested", "escalated", "no-resolution"] + }, + "followUpNotes": { "type": "string" } + }, + "required": ["outcome"] + }, + "conditions": [ + { "type": "minMessages", "count": 6 }, + { "type": "minCallDuration", "seconds": 15 }, + { "type": "endedReason", "operator": "oneOf", "values": ["customer-ended-call"] } + ] + }' +``` + + +On a call that ends before those thresholds are met — a wrong number, a hang-up, a voicemail — the output is skipped instead of producing an empty or misleading result. + ## Best practices for complex schemas diff --git a/fern/assistants/structured-outputs-quickstart.mdx b/fern/assistants/structured-outputs-quickstart.mdx index 30ae147d1..9cd34874d 100644 --- a/fern/assistants/structured-outputs-quickstart.mdx +++ b/fern/assistants/structured-outputs-quickstart.mdx @@ -1,6 +1,7 @@ --- title: Structured outputs quickstart subtitle: Get started with structured data extraction in 5 minutes +description: Set up structured data extraction from calls in a few minutes. Create a schema, link it to an assistant, test extraction, and configure HIPAA-safe storage settings. slug: assistants/structured-outputs-quickstart --- @@ -8,24 +9,42 @@ slug: assistants/structured-outputs-quickstart This quickstart guide will help you set up structured outputs to automatically extract customer information from phone calls. In just a few minutes, you'll create a structured output, link it to an assistant, and test data extraction. + + ### What are structured outputs? -Structured outputs are AI-powered data extraction templates that automatically capture and organize information from conversations. They work by: +Structured outputs are AI-powered analysis and extraction tools that intelligently process conversation data after calls end. They go beyond simple data extraction to provide intelligent analysis and evaluation. They work by: -1. **Listening to conversations** - As your assistant talks with customers, structured outputs analyze the conversation in real-time -2. **Extracting key information** - Based on your defined schema, they identify and extract relevant data points like names, emails, preferences, and issues -3. **Validating and formatting** - The extracted data is validated against your schema rules and formatted into clean, structured JSON -4. **Delivering results** - The structured data is available immediately after the call ends via API or webhooks +1. **Processing complete call context** - After the call ends, structured outputs analyze the full transcript, messages, tool call results, and call metadata +2. **Intelligent extraction & analysis** - Based on your schema, they can extract data, evaluate outcomes, analyze sentiment, determine success criteria, and summarize complex interactions +3. **Validating and formatting** - Results are validated against your schema rules and formatted into clean, structured JSON +4. **Delivering insights** - The processed data and insights are available via API or webhooks once analysis is complete ### When are structured outputs generated? Structured outputs are processed: -- **During the call** - Data is extracted in real-time as the conversation happens -- **After call completion** - Final validation and formatting occurs when the call ends +- **After call completion** - The full conversation is analyzed once the call ends +- **Processing time** - Typically completes within a few seconds after call termination - **Available via** - Call artifacts in the API response or webhook events +### What data do structured outputs have access to? + +When processing, structured outputs can analyze: +- **Complete transcript** - The full conversation between assistant and customer +- **Messages history** - All messages exchanged during the call +- **Tool call results** - Outcomes from any tools or functions executed +- **Assistant context** - System prompts and configuration used during the call + ### Why use structured outputs? +**Beyond simple data extraction:** +- **Call evaluation** - Determine if objectives were met (appointment booked, issue resolved) +- **Sentiment analysis** - Understand customer satisfaction and emotional state +- **CSAT scoring** - Extract customer satisfaction scores from feedback +- **Intelligent summaries** - Generate contextual summaries of complex conversations +- **Success metrics** - Evaluate agent performance and call outcomes + +**Operational benefits:** - **Automate data entry** - No more manual transcription or form filling - **Ensure consistency** - Every call captures the same structured information - **Enable integrations** - Automatically sync data to CRMs, ticketing systems, or databases @@ -45,79 +64,88 @@ A customer support assistant that automatically extracts: Sign up at [dashboard.vapi.ai](https://dashboard.vapi.ai) - Get your API key from the Dashboard settings + Get a [Vapi API key](/security-and-privacy/api-keys) ## Step 1: Create your structured output -You can create structured outputs using either the Dashboard UI or the API. - -### Option A: Using the Dashboard (Recommended for beginners) +Define what information you want to extract using a [JSON Schema](https://json-schema.org/learn/getting-started-step-by-step). JSON Schema is a standard for describing data structures - [learn more about JSON Schema here](https://json-schema.org/understanding-json-schema/). - - - 1. Log in to [dashboard.vapi.ai](https://dashboard.vapi.ai) - 2. Click on **Structured Outputs** in the left sidebar - 3. Click **Create New Structured Output** - - - - 1. **Name**: Enter "Support Ticket" - 2. **Type**: Select "AI" (for automatic extraction) - 3. **Description**: Add "Extract support ticket information from customer calls" - - - - Use the visual schema builder or paste this JSON directly: - ```json - { - "type": "object", - "properties": { - "customer": { - "type": "object", - "properties": { - "name": {"type": "string", "description": "Customer full name"}, - "email": {"type": "string", "format": "email", "description": "Customer email"}, - "phone": {"type": "string", "description": "Customer phone number"} - }, - "required": ["name"] - }, - "issue": { + + + + + 1. Log in to [dashboard.vapi.ai](https://dashboard.vapi.ai) + 2. Click on **Structured Outputs** in the left sidebar + 3. Click **Create New Structured Output** + + + + 1. **Name**: Enter "Support Ticket" + 2. **Type**: Select "Object" + 3. **Description**: Add "Extract support ticket information from customer calls" + + + + Use the visual schema builder: + ```json + { "type": "object", "properties": { - "description": {"type": "string", "description": "Issue description"}, - "category": { - "type": "string", - "enum": ["billing", "technical", "general", "complaint"], - "description": "Issue category" + "customer": { + "type": "object", + "properties": { + "name": {"type": "string", "description": "Customer full name"}, + "email": {"type": "string", "format": "email", "description": "Customer email"}, + "phone": {"type": "string", "description": "Customer phone number"} + }, + "required": ["name"] }, - "priority": { - "type": "string", - "enum": ["low", "medium", "high", "urgent"], - "description": "Priority level" + "issue": { + "type": "object", + "properties": { + "description": {"type": "string", "description": "Issue description"}, + "category": { + "type": "string", + "enum": ["billing", "technical", "general", "complaint"], + "description": "Issue category" + }, + "priority": { + "type": "string", + "enum": ["low", "medium", "high", "urgent"], + "description": "Priority level" + } + }, + "required": ["description", "category"] + }, + "followUp": { + "type": "object", + "properties": { + "required": {"type": "boolean", "description": "Whether follow-up is needed"}, + "method": { + "type": "string", + "enum": ["email", "phone", "none"], + "description": "Preferred follow-up method" + }, + "notes": {"type": "string", "description": "Additional notes for follow-up"} + } } }, - "required": ["description", "category"] + "required": ["customer", "issue"] } - }, - "required": ["customer", "issue"] - } - ``` - - - - 1. Click **Create Structured Output** - 2. Copy the generated ID from the details page - 3. You'll use this ID to link to your assistant - - - -### Option B: Using the API - -Define what information you want to extract using a [JSON Schema](https://json-schema.org/learn/getting-started-step-by-step). JSON Schema is a standard for describing data structures - [learn more about JSON Schema here](https://json-schema.org/understanding-json-schema/). - - + ``` + + + + 1. Click **Create Structured Output** + 2. In the structured output dialog, you can directly attach it to an assistant + 3. Select an existing assistant to attach this output to that assistant + + + + + ```bash title="cURL" curl -X POST https://api.vapi.ai/structured-output \ -H "Authorization: Bearer $VAPI_API_KEY" \ @@ -191,356 +219,364 @@ curl -X POST https://api.vapi.ai/structured-output \ } }' ``` - -```javascript title="Node.js" -const response = await fetch('https://api.vapi.ai/structured-output', { - method: 'POST', - headers: { - 'Authorization': `Bearer ${process.env.VAPI_API_KEY}`, - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ - name: "Support Ticket", - type: "ai", - description: "Extract support ticket information from customer calls", - schema: { - type: "object", - properties: { - customer: { - type: "object", - properties: { - name: { - type: "string", - description: "Customer full name" - }, - email: { - type: "string", - format: "email", - description: "Customer email address" - }, - phone: { - type: "string", - description: "Customer phone number" - } + + + + ```typescript +import { VapiClient } from "@vapi-ai/server-sdk"; + +const vapi = new VapiClient({ token: process.env.VAPI_API_KEY! }); + +const structuredOutput = await vapi.structuredOutputs.create({ + name: "Support Ticket", + type: "ai", + description: "Extract support ticket information from customer calls", + schema: { + type: "object", + properties: { + customer: { + type: "object", + properties: { + name: { + type: "string", + description: "Customer full name" + }, + email: { + type: "string", + format: "email", + description: "Customer email address" }, - required: ["name"] + phone: { + type: "string", + description: "Customer phone number" + } }, - issue: { - type: "object", - properties: { - description: { - type: "string", - description: "Description of the customer issue" - }, - category: { - type: "string", - enum: ["billing", "technical", "general", "complaint"], - description: "Issue category" - }, - priority: { - type: "string", - enum: ["low", "medium", "high", "urgent"], - description: "Issue priority level" - } + required: ["name"] + }, + issue: { + type: "object", + properties: { + description: { + type: "string", + description: "Description of the customer issue" + }, + category: { + type: "string", + enum: ["billing", "technical", "general", "complaint"], + description: "Issue category" }, - required: ["description", "category"] + priority: { + type: "string", + enum: ["low", "medium", "high", "urgent"], + description: "Issue priority level" + } }, - followUp: { - type: "object", - properties: { - required: { - type: "boolean", - description: "Whether follow-up is needed" - }, - method: { - type: "string", - enum: ["email", "phone", "none"], - description: "Preferred follow-up method" - }, - notes: { - type: "string", - description: "Additional notes for follow-up" - } + required: ["description", "category"] + }, + followUp: { + type: "object", + properties: { + required: { + type: "boolean", + description: "Whether follow-up is needed" + }, + method: { + type: "string", + enum: ["email", "phone", "none"], + description: "Preferred follow-up method" + }, + notes: { + type: "string", + description: "Additional notes for follow-up" } } - }, - required: ["customer", "issue"] - } - }) + } + }, + required: ["customer", "issue"] + } }); -const structuredOutput = await response.json(); console.log('Created structured output:', structuredOutput.id); // Save this ID - you'll need it in the next step ``` + -```python title="Python" -import requests + + ```python +from vapi import Vapi import os -response = requests.post( - 'https://api.vapi.ai/structured-output', - headers={ - 'Authorization': f'Bearer {os.environ["VAPI_API_KEY"]}', - 'Content-Type': 'application/json' - }, - json={ - "name": "Support Ticket", - "type": "ai", - "description": "Extract support ticket information from customer calls", - "schema": { - "type": "object", - "properties": { - "customer": { - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "Customer full name" - }, - "email": { - "type": "string", - "format": "email", - "description": "Customer email address" - }, - "phone": { - "type": "string", - "description": "Customer phone number" - } +vapi = Vapi(token=os.environ.get("VAPI_API_KEY")) + +structured_output = vapi.structured_outputs.create( + name="Support Ticket", + type="ai", + description="Extract support ticket information from customer calls", + schema={ + "type": "object", + "properties": { + "customer": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Customer full name" }, - "required": ["name"] + "email": { + "type": "string", + "format": "email", + "description": "Customer email address" + }, + "phone": { + "type": "string", + "description": "Customer phone number" + } }, - "issue": { - "type": "object", - "properties": { - "description": { - "type": "string", - "description": "Description of the customer issue" - }, - "category": { - "type": "string", - "enum": ["billing", "technical", "general", "complaint"], - "description": "Issue category" - }, - "priority": { - "type": "string", - "enum": ["low", "medium", "high", "urgent"], - "description": "Issue priority level" - } + "required": ["name"] + }, + "issue": { + "type": "object", + "properties": { + "description": { + "type": "string", + "description": "Description of the customer issue" + }, + "category": { + "type": "string", + "enum": ["billing", "technical", "general", "complaint"], + "description": "Issue category" }, - "required": ["description", "category"] + "priority": { + "type": "string", + "enum": ["low", "medium", "high", "urgent"], + "description": "Issue priority level" + } }, - "followUp": { - "type": "object", - "properties": { - "required": { - "type": "boolean", - "description": "Whether follow-up is needed" - }, - "method": { - "type": "string", - "enum": ["email", "phone", "none"], - "description": "Preferred follow-up method" - }, - "notes": { - "type": "string", - "description": "Additional notes for follow-up" - } + "required": ["description", "category"] + }, + "followUp": { + "type": "object", + "properties": { + "required": { + "type": "boolean", + "description": "Whether follow-up is needed" + }, + "method": { + "type": "string", + "enum": ["email", "phone", "none"], + "description": "Preferred follow-up method" + }, + "notes": { + "type": "string", + "description": "Additional notes for follow-up" } } - }, - "required": ["customer", "issue"] - } + } + }, + "required": ["customer", "issue"] } ) -structured_output = response.json() -print(f'Created structured output: {structured_output["id"]}') +print(f'Created structured output: {structured_output.id}') # Save this ID - you'll need it in the next step ``` - + + - -Save the returned `id` from the response - you'll need it to link to your assistant. - + +In the API approach, you'll need to save the returned `id` to attach it to an assistant. In the Dashboard, you can attach it directly when creating the structured output. + -## Step 2: Create an assistant with structured outputs +## Step 2: Create and test a call -Now create an assistant that uses your structured output: +Now test your structured output by making a call. - -```bash title="cURL" -curl -X POST https://api.vapi.ai/assistant \ - -H "Authorization: Bearer $VAPI_API_KEY" \ - -H "Content-Type: application/json" \ - -d '{ - "name": "Customer Support Agent", - "firstMessage": "Hello! I'\''m here to help you with your support request. Can you please tell me your name and describe the issue you'\''re experiencing?", - "model": { - "provider": "openai", - "model": "gpt-4-turbo-preview", - "messages": [ - { - "role": "system", - "content": "You are a helpful customer support agent. Gather the customer'\''s information and understand their issue. Be empathetic and professional." - } - ] - }, - "voice": { - "provider": "vapi", - "voiceId": "jennifer" - }, - "artifactPlan": { - "structuredOutputIds": ["YOUR_STRUCTURED_OUTPUT_ID_HERE"] - } - }' -``` + +**Prerequisites**: You need an assistant already created with: +- The structured output from Step 1 attached in `artifactPlan.structuredOutputIds` +- A model and voice configured +- System prompt appropriate for your use case -```javascript title="Node.js" -const assistant = await fetch('https://api.vapi.ai/assistant', { - method: 'POST', - headers: { - 'Authorization': `Bearer ${process.env.VAPI_API_KEY}`, - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ - name: "Customer Support Agent", - firstMessage: "Hello! I'm here to help you with your support request. Can you please tell me your name and describe the issue you're experiencing?", - model: { - provider: "openai", - model: "gpt-4-turbo-preview", - messages: [ - { - role: "system", - content: "You are a helpful customer support agent. Gather the customer's information and understand their issue. Be empathetic and professional." - } - ] - }, - voice: { - provider: "vapi", - voiceId: "jennifer" - }, - artifactPlan: { - structuredOutputIds: [structuredOutput.id] // Use the ID from step 1 - } - }) -}).then(res => res.json()); +You can create an assistant via the Dashboard or API, then use its ID in the examples below. + -console.log('Created assistant:', assistant.id); + + + + + 1. Navigate to your assistant (from **Assistants** in the sidebar) + 2. Ensure your structured output is attached in the **Artifact Plan** section + 3. Click **Talk to Assistant** in the top right corner + 4. The assistant will start speaking + + + + Try saying: "Hi, my name is John Smith. My email is john@example.com. I'm having trouble logging into my account - it keeps showing an error message. This is pretty urgent for me." + + + + Click **End Call** when you're done testing + + + + + + ```typescript +import { VapiClient } from "@vapi-ai/server-sdk"; + +const vapi = new VapiClient({ token: process.env.VAPI_API_KEY! }); + +// Start a web call with your assistant (replace with your assistant ID) +const call = await vapi.calls.create({ + assistantId: "your-assistant-id", // Use an assistant with structured outputs attached + type: "webCall" +}); + +console.log('Call started:', call.id); +console.log('Join URL:', call.webCallUrl); + +// For phone calls, use: +// const call = await vapi.calls.create({ +// assistantId: "your-assistant-id", +// type: "outboundPhoneCall", +// phoneNumberId: "your-phone-number-id", +// customer: { +// number: "+1234567890" +// } +// }); ``` + -```python title="Python" -assistant_response = requests.post( - 'https://api.vapi.ai/assistant', - headers={ - 'Authorization': f'Bearer {os.environ["VAPI_API_KEY"]}', - 'Content-Type': 'application/json' - }, - json={ - "name": "Customer Support Agent", - "firstMessage": "Hello! I'm here to help you with your support request. Can you please tell me your name and describe the issue you're experiencing?", - "model": { - "provider": "openai", - "model": "gpt-4-turbo-preview", - "messages": [ - { - "role": "system", - "content": "You are a helpful customer support agent. Gather the customer's information and understand their issue. Be empathetic and professional." - } - ] - }, - "voice": { - "provider": "vapi", - "voiceId": "jennifer" - }, - "artifactPlan": { - "structuredOutputIds": [structured_output["id"]] # Use the ID from step 1 - } - } -) + + ```python +from vapi import Vapi +import os -assistant = assistant_response.json() -print(f'Created assistant: {assistant["id"]}') -``` - +vapi = Vapi(token=os.environ.get("VAPI_API_KEY")) -## Step 3: Test with a phone call +# Start a web call with your assistant (replace with your assistant ID) +call = vapi.calls.create( + assistant_id="your-assistant-id", # Use an assistant with structured outputs attached + type="webCall" +) -Make a test call to your assistant: +print(f'Call started: {call.id}') +print(f'Join URL: {call.web_call_url}') + +# For phone calls, use: +# call = vapi.calls.create( +# assistant_id="your-assistant-id", +# type="outboundPhoneCall", +# phone_number_id="your-phone-number-id", +# customer={ +# "number": "+1234567890" +# } +# ) +``` + - -```bash title="cURL" + + ```bash +# Start a web call curl -X POST https://api.vapi.ai/call \ -H "Authorization: Bearer $VAPI_API_KEY" \ -H "Content-Type: application/json" \ -d '{ - "assistantId": "YOUR_ASSISTANT_ID_HERE", - "customer": { - "number": "+1234567890" - } + "assistantId": "your-assistant-id", + "type": "webCall" }' -``` -```javascript title="Node.js" -const call = await fetch('https://api.vapi.ai/call', { - method: 'POST', - headers: { - 'Authorization': `Bearer ${process.env.VAPI_API_KEY}`, - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ - assistantId: assistant.id, - customer: { - number: "+1234567890" // Replace with your phone number - } - }) -}).then(res => res.json()); - -console.log('Call initiated:', call.id); +# For phone calls: +# curl -X POST https://api.vapi.ai/call \ +# -H "Authorization: Bearer $VAPI_API_KEY" \ +# -H "Content-Type: application/json" \ +# -d '{ +# "assistantId": "your-assistant-id", +# "type": "outboundPhoneCall", +# "phoneNumberId": "your-phone-number-id", +# "customer": { +# "number": "+1234567890" +# } +# }' ``` - -```python title="Python" -call_response = requests.post( - 'https://api.vapi.ai/call', - headers={ - 'Authorization': f'Bearer {os.environ["VAPI_API_KEY"]}', - 'Content-Type': 'application/json' - }, - json={ - "assistantId": assistant["id"], - "customer": { - "number": "+1234567890" # Replace with your phone number - } - } -) - -call = call_response.json() -print(f'Call initiated: {call["id"]}') -``` - + + During the call, try saying something like: "Hi, my name is John Smith. My email is john@example.com. I'm having trouble logging into my account - it keeps showing an error message. This is pretty urgent for me." -## Step 4: Retrieve extracted data +## Step 3: Retrieve extracted data After the call ends, retrieve the extracted information: - -```bash title="cURL" -curl -X GET "https://api.vapi.ai/call/YOUR_CALL_ID_HERE" \ - -H "Authorization: Bearer $VAPI_API_KEY" -``` + + + + + 1. Navigate to **Call Logs** in the left sidebar + 2. Click on your recent call to view details + + + + 1. In the call details, find the **Structured Outputs** section + 2. View the extracted JSON data for your "Support Ticket" output + 3. The data will be displayed in a formatted JSON view showing each output with its ID, name, and result + + + + ### How structured outputs appear in Call Logs + + When you view a call in the Call Logs page, structured outputs are displayed in the following format: + + ```json + { + "550e8400-e29b-41d4-a716-446655440001": { + "name": "Support Ticket", + "result": { + "customer": { + "name": "John Smith", + "email": "john@example.com", + "phone": "+1234567890" + }, + "issue": { + "description": "Unable to login to account, receiving error message", + "category": "technical", + "priority": "urgent" + }, + "followUp": { + "required": true, + "method": "email", + "notes": "Customer needs immediate assistance with login issue" + } + } + } + } + ``` + + **Structure explanation:** + - **Root level**: Contains output IDs (UUIDs) as keys + - **name**: The name of the structured output configuration + - **result**: The actual extracted data based on your schema + - For object schemas: Contains the nested structure with all extracted fields + - For boolean schemas: Contains `true` or `false` + - For string schemas: Contains the extracted text + - For number schemas: Contains the numeric value + + + If you have multiple structured outputs attached to an assistant, each will appear with its own UUID key in the structuredOutputs object. + + + + + ```typescript +import { VapiClient } from "@vapi-ai/server-sdk"; + +const vapi = new VapiClient({ token: process.env.VAPI_API_KEY! }); -```javascript title="Node.js" // Wait a few seconds after call ends for processing setTimeout(async () => { - const callData = await fetch(`https://api.vapi.ai/call/${call.id}`, { - headers: { - 'Authorization': `Bearer ${process.env.VAPI_API_KEY}` - } - }).then(res => res.json()); + const callData = await vapi.calls.get(call.id); const outputs = callData.artifact?.structuredOutputs; @@ -552,32 +588,41 @@ setTimeout(async () => { } }, 5000); ``` + -```python title="Python" + + ```python +from vapi import Vapi import time import json +import os + +vapi = Vapi(token=os.environ.get("VAPI_API_KEY")) # Wait a few seconds after call ends for processing time.sleep(5) -call_data = requests.get( - f'https://api.vapi.ai/call/{call["id"]}', - headers={ - 'Authorization': f'Bearer {os.environ["VAPI_API_KEY"]}' - } -).json() +call_data = vapi.calls.get(call.id) -outputs = call_data.get('artifact', {}).get('structuredOutputs', {}) +outputs = call_data.artifact.get('structuredOutputs', {}) if call_data.artifact else {} for output_id, data in outputs.items(): print('Extracted Support Ticket:') print(json.dumps(data['result'], indent=2)) ``` - + + + + ```bash +curl -X GET "https://api.vapi.ai/call/YOUR_CALL_ID_HERE" \ + -H "Authorization: Bearer $VAPI_API_KEY" +``` + + ### Expected output -You should see extracted data like this: +The extracted data (the `result` field from the API response) will look like this: ```json { @@ -599,103 +644,160 @@ You should see extracted data like this: } ``` -## Step 5: Set up webhook (optional) + +When accessing via API, this data is nested inside the structured output object at `call.artifact.structuredOutputs[outputId].result`. The Dashboard shows the complete structure including the output ID and name. + -To automatically receive extracted data when calls end, set up a webhook: +## HIPAA Compliance & Storage Settings - -```javascript title="Express.js webhook handler" -const express = require('express'); -const app = express(); + +**Important for HIPAA users:** When HIPAA mode is enabled, Vapi does not store structured outputs by default. This protects privacy but limits your ability to view structured outputs in Insights and Call Logs. + -app.use(express.json()); +### Understanding the default behavior -app.post('/vapi/webhook', (req, res) => { - const { type, call } = req.body; - - if (type === 'call.ended') { - const outputs = call.artifact?.structuredOutputs; - - if (outputs) { - Object.entries(outputs).forEach(([outputId, data]) => { - if (data.result) { - // Process the extracted support ticket - console.log('New support ticket:', data.result); - - // Example: Create ticket in your system - createSupportTicket({ - customer: data.result.customer, - issue: data.result.issue, - priority: data.result.issue.priority, - followUp: data.result.followUp - }); - } - }); - } - } - - res.status(200).send('OK'); -}); +When your organization or assistant has HIPAA mode enabled: +- **Structured outputs are NOT stored** - Results are generated but not persisted in Vapi's systems +- **Limited visibility** - You cannot view outputs in the Dashboard's Call Logs or Insights +- **Privacy first** - This ensures sensitive data is not retained +- **Webhook access only** - You can still receive outputs via webhooks during the call -function createSupportTicket(ticketData) { - // Your ticket creation logic here - console.log('Creating ticket in system:', ticketData); -} +This default behavior protects patient privacy and ensures compliance with HIPAA regulations. -app.listen(3000, () => { - console.log('Webhook server running on port 3000'); -}); -``` +### Enabling storage for non-sensitive outputs -```python title="Flask webhook handler" -from flask import Flask, request, jsonify +For structured outputs that extract **non-sensitive, non-PHI information**, you can override this behavior using the `compliancePlan.forceStoreOnHipaaEnabled` setting. -app = Flask(__name__) + +**Your responsibility:** You must ensure that any structured output with storage enabled does NOT extract or generate PHI or sensitive data. + -@app.route('/vapi/webhook', methods=['POST']) -def vapi_webhook(): - data = request.json - - if data.get('type') == 'call.ended': - call = data.get('call', {}) - outputs = call.get('artifact', {}).get('structuredOutputs', {}) - - for output_id, output_data in outputs.items(): - if output_data.get('result'): - # Process the extracted support ticket - print('New support ticket:', output_data['result']) - - # Example: Create ticket in your system - create_support_ticket({ - 'customer': output_data['result']['customer'], - 'issue': output_data['result']['issue'], - 'priority': output_data['result']['issue']['priority'], - 'followUp': output_data['result']['followUp'] - }) - - return jsonify({'status': 'ok'}), 200 +#### Safe use cases for storage override -def create_support_ticket(ticket_data): - # Your ticket creation logic here - print('Creating ticket in system:', ticket_data) +Enable storage for these types of non-sensitive outputs: -if __name__ == '__main__': - app.run(port=3000) -``` - +- **Boolean outcomes**: `appointmentBooked: true/false`, `callSuccessful: true/false` +- **General categories**: `issueCategory: "billing" | "technical" | "general"` +- **Satisfaction scores**: `csatScore: 1-10` +- **Call metrics**: `sentiment: "positive" | "neutral" | "negative"` +- **Success indicators**: `issueResolved: boolean`, `followUpRequired: boolean` + +#### Never enable storage for these + +**Do not** enable storage for outputs that extract: +- Patient names, dates of birth, or contact information +- Diagnosis, treatment, or medication information +- Medical record numbers or identifiers +- Social security numbers +- Credit card or payment details -Then update your assistant with the webhook URL: +### Configuration examples + + + 1. Navigate to **Structured Outputs** in the left sidebar + 2. Create or edit a structured output + 3. Expand the **Compliance Settings** section + 4. Enable the toggle for "Enable Storage of Structured Outputs while on HIPAA Mode" + 5. **Recommendation**: Only enable if your output does not extract sensitive information + + + ```bash -curl -X PATCH "https://api.vapi.ai/assistant/YOUR_ASSISTANT_ID" \ +# Creating a HIPAA-safe structured output with storage enabled +curl -X POST https://api.vapi.ai/structured-output \ -H "Authorization: Bearer $VAPI_API_KEY" \ -H "Content-Type: application/json" \ -d '{ - "server": { - "url": "https://your-domain.com/vapi/webhook" + "name": "Appointment Booked", + "type": "ai", + "description": "Boolean indicator of whether appointment was booked", + "schema": { + "type": "boolean", + "description": "Whether an appointment was successfully booked during the call" + }, + "compliancePlan": { + "forceStoreOnHipaaEnabled": true } }' ``` + + + +```typescript +import { VapiClient } from "@vapi-ai/server-sdk"; + +const vapi = new VapiClient({ token: process.env.VAPI_API_KEY! }); + +// Safe: Boolean outcome, no PHI +const structuredOutput = await vapi.structuredOutputs.create({ + name: "Appointment Booked", + type: "ai", + description: "Boolean indicator of whether appointment was booked", + schema: { + type: "boolean", + description: "Whether an appointment was successfully booked during the call" + }, + compliancePlan: { + forceStoreOnHipaaEnabled: true // Safe because output contains no PHI + } +}); + +// Update existing structured output to enable storage +await vapi.structuredOutputs.update(structuredOutput.id, { + compliancePlan: { + forceStoreOnHipaaEnabled: true + } +}); +``` + + + +```python +from vapi import Vapi +import os + +vapi = Vapi(token=os.environ.get("VAPI_API_KEY")) + +# Safe: Boolean outcome, no PHI +structured_output = vapi.structured_outputs.create( + name="Appointment Booked", + type="ai", + description="Boolean indicator of whether appointment was booked", + schema={ + "type": "boolean", + "description": "Whether an appointment was successfully booked during the call" + }, + compliance_plan={ + "forceStoreOnHipaaEnabled": True + } +) + +# Update existing structured output to enable storage +vapi.structured_outputs.update( + structured_output.id, + compliance_plan={ + "forceStoreOnHipaaEnabled": True + } +) +``` + + + + +**IMPORTANT:** Only set `forceStoreOnHipaaEnabled: true` if you are certain your structured output does NOT extract PHI or sensitive data. Review your schema carefully before enabling storage. + + +### Best practices for HIPAA compliance + +1. **Default to privacy**: Keep storage disabled for all outputs that might contain PHI +2. **Review schemas carefully**: Ensure your extraction logic cannot accidentally capture sensitive data +3. **Use specific schemas**: Design narrow schemas that target only non-sensitive data +4. **Test thoroughly**: Verify outputs don't contain PHI before enabling storage +5. **Document decisions**: Maintain records of which outputs have storage enabled and why +6. **Regular audits**: Periodically review stored outputs to ensure compliance + +For more information about HIPAA compliance with Vapi, see our [HIPAA Compliance Guide](/security-and-privacy/hipaa). ## Next steps @@ -737,23 +839,49 @@ You can attach multiple structured outputs to extract different types of data: The `structuredOutputIds` are UUIDs returned when you create each structured output configuration. -### Conditional extraction +### Example: Intelligent analysis with multiple outputs -Use conditional logic in your schema to handle different scenarios: +Structured outputs can perform sophisticated analysis beyond simple data extraction. Here's a real example showing various types of intelligent evaluation: ```json { - "if": { - "properties": { - "requestType": {"const": "appointment"} - } + "2ca00f20-f2c3-4d74-af2e-52842be5885c": { + "name": "informationOnFileIsCorrect", + "result": false }, - "then": { - "required": ["preferredDate", "preferredTime"] + "4748e1aa-6c7a-49e6-bbde-c4365ef69c6e": { + "name": "Appointment Rescheduled", + "result": false + }, + "4d4bac33-2cea-43d4-a3b3-4554932b8933": { + "name": "CSAT", + "result": 8 + }, + "7898e478-c8dc-4ff8-a3f6-4a46555a957f": { + "name": "Appointment Booked", + "result": true + }, + "a0ca58b1-c343-4628-b088-bf53aabacab9": { + "name": "Call Summary", + "result": "The user called to schedule a consultation appointment for next week, specifically on Wednesday afternoon..." + }, + "b5a390d8-87c5-4015-b1ad-ed237201bdf0": { + "name": "Success Evaluation - Pass/Fail", + "result": true } } ``` +This example demonstrates intelligent extraction capabilities: +- **Call outcome evaluation**: `Appointment Booked` (true) - Analyzed if the call's objective was achieved +- **Data verification**: `informationOnFileIsCorrect` (false) - Evaluated if customer data needed updates +- **Success metrics**: `Success Evaluation - Pass/Fail` (true) - Determined overall call success based on multiple criteria +- **CSAT extraction**: `CSAT` (8) - Extracted satisfaction score from customer feedback +- **Intelligent summarization**: `Call Summary` - Generated contextual summary of the conversation +- **Process tracking**: `Appointment Rescheduled` (false) - Tracked specific actions taken during the call + +Each output analyzes the complete call context including transcript, tool results, and metadata to provide actionable insights. + ### Validation patterns Common validation patterns for reliable extraction: @@ -801,4 +929,4 @@ Common validation patterns for reliable extraction: Need assistance? We're here to help: - [API Documentation](/api-reference) - [Discord Community](https://discord.gg/pUFNcf2WmH) -- [Support](mailto:support@vapi.ai) \ No newline at end of file +- [Support](mailto:support@vapi.ai) diff --git a/fern/assistants/structured-outputs.mdx b/fern/assistants/structured-outputs.mdx index b7a53ea8e..17e1493df 100644 --- a/fern/assistants/structured-outputs.mdx +++ b/fern/assistants/structured-outputs.mdx @@ -1,6 +1,7 @@ --- title: Structured outputs subtitle: Extract structured data from conversations using AI-powered analysis +description: Extract structured, schema-defined data from voice calls using AI-powered analysis. Covers field types, extraction timing, limitations, and HIPAA storage behavior. slug: assistants/structured-outputs --- @@ -23,8 +24,8 @@ Structured outputs enable automatic extraction of specific information from voic Use the API to create a reusable structured output definition - - Connect the structured output to one or more assistants or workflows + + Connect the structured output to one or more assistants Data is automatically extracted after each call and stored in call artifacts @@ -37,9 +38,9 @@ Structured outputs enable automatic extraction of specific information from voic ```typescript title="TypeScript (Server SDK)" -import { Vapi } from '@vapi-ai/server-sdk'; +import { VapiClient } from '@vapi-ai/server-sdk'; -const vapi = new Vapi({ apiKey: process.env.VAPI_API_KEY }); +const vapi = new VapiClient({ token: process.env.VAPI_API_KEY }); const structuredOutput = await vapi.structuredOutputs.create({ name: "Customer Info", @@ -75,9 +76,10 @@ console.log('Created structured output:', structuredOutput.id); ``` ```python title="Python (Server SDK)" -from vapi_python import Vapi +import os +from vapi import Vapi -vapi = Vapi(api_key=os.environ['VAPI_API_KEY']) +vapi = Vapi(token=os.environ['VAPI_API_KEY']) structured_output = vapi.structured_outputs.create( name="Customer Info", @@ -236,10 +238,10 @@ for output_id, data in outputs.items(): ```javascript title="Webhook Response" // In your webhook handler app.post('/vapi/webhook', (req, res) => { - const { type, call } = req.body; + const { message } = req.body; - if (type === 'call.ended') { - const outputs = call.artifact?.structuredOutputs; + if (message.type === 'end-of-call-report') { + const outputs = message.artifact?.structuredOutputs; if (outputs) { Object.entries(outputs).forEach(([outputId, data]) => { @@ -439,9 +441,100 @@ Use `if/then/else` for conditional requirements: } ``` +## Conditional generation + +By default, every linked structured output runs after each call. Attach **conditions** to a structured output so it only generates when the call meets your criteria — for example, skip extraction on calls that barely started, or only run an output when the call ended a certain way. + + +Conditions gate **whether the output runs at all**. This is different from the [`if/then/else` schema logic](#conditional-logic) above, which shapes the data *within* a single extraction. + + +### How conditions work + +- Add a `conditions` array to a structured output. +- **Every condition must pass** for the output to run (AND semantics). +- When `conditions` is omitted or empty, no user-defined conditions gate the output (runtime defaults still apply). +- On update (`PATCH`), send `conditions: null` to clear a previously saved gate. + +When a condition isn't met, the output is **skipped** rather than failed. Skipped outputs are surfaced in the **assistant preview**, **call logs**, and **sessions**, so you can see which outputs ran and which were gated out. + +### Condition types + +| Type | Fields | Output runs when | +|------|--------|------------------| +| `minMessages` | `count` (integer ≥ 0) | The conversation has at least `count` messages. `count: 0` removes the runtime default minimum. | +| `minCallDuration` | `seconds` (integer ≥ 0) | The call lasted at least `seconds` seconds. | +| `endedReason` | `operator` (`oneOf` or `notOneOf`), `values` (array of strings) | The call's [ended reason](/calls/call-ended-reason) passes the membership test against `values`. `oneOf` runs the output only if the ended reason is in `values`; `notOneOf` runs it only if the ended reason is not in `values`. | + +### Example + +Only extract a call summary when the call had a real conversation (at least 4 messages and 10 seconds) and the customer ended it: + + +```typescript title="TypeScript (Server SDK)" +const structuredOutput = await vapi.structuredOutputs.create({ + name: "Call Summary", + type: "ai", + description: "Summarize the conversation", + schema: { + type: "object", + properties: { + summary: { type: "string" } + } + }, + conditions: [ + { type: "minMessages", count: 4 }, + { type: "minCallDuration", seconds: 10 }, + { type: "endedReason", operator: "oneOf", values: ["customer-ended-call"] } + ] +}); +``` + +```python title="Python (Server SDK)" +structured_output = vapi.structured_outputs.create( + name="Call Summary", + type="ai", + description="Summarize the conversation", + schema={ + "type": "object", + "properties": { + "summary": {"type": "string"} + } + }, + conditions=[ + {"type": "minMessages", "count": 4}, + {"type": "minCallDuration", "seconds": 10}, + {"type": "endedReason", "operator": "oneOf", "values": ["customer-ended-call"]} + ] +) +``` + +```bash title="cURL" +curl -X POST https://api.vapi.ai/structured-output \ + -H "Authorization: Bearer $VAPI_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "name": "Call Summary", + "type": "ai", + "description": "Summarize the conversation", + "schema": { + "type": "object", + "properties": { + "summary": { "type": "string" } + } + }, + "conditions": [ + { "type": "minMessages", "count": 4 }, + { "type": "minCallDuration", "seconds": 10 }, + { "type": "endedReason", "operator": "oneOf", "values": ["customer-ended-call"] } + ] + }' +``` + + ## Custom models -Configure which AI model performs the extraction: +By default, structured outputs are extracted with GPT-4.1. Configure the `model` to use a different provider or model, or to supply your own extraction prompts: ```typescript title="TypeScript" @@ -464,7 +557,7 @@ const structuredOutput = await vapi.structuredOutputs.create({ }, model: { provider: "openai", - model: "gpt-4-turbo-preview", + model: "gpt-4.1", temperature: 0.1, messages: [ { @@ -473,7 +566,7 @@ const structuredOutput = await vapi.structuredOutputs.create({ }, { role: "user", - content: "Analyze the sentiment of this conversation:\n{{transcript}}" + content: "Extract {{structuredOutput.name}} using this schema:\n{{structuredOutput.schema}}\n\nAnalyze the sentiment of this conversation:\n{{transcript}}" } ] } @@ -500,7 +593,7 @@ structured_output = vapi.structured_outputs.create( }, model={ "provider": "openai", - "model": "gpt-4-turbo-preview", + "model": "gpt-4.1", "temperature": 0.1, "messages": [ { @@ -509,7 +602,7 @@ structured_output = vapi.structured_outputs.create( }, { "role": "user", - "content": "Analyze the sentiment of this conversation:\n{{transcript}}" + "content": "Extract {{structuredOutput.name}} using this schema:\n{{structuredOutput.schema}}\n\nAnalyze the sentiment of this conversation:\n{{transcript}}" } ] } @@ -522,57 +615,44 @@ structured_output = vapi.structured_outputs.create( Use these variables in custom prompts: - `{{transcript}}` - Full conversation transcript -- `{{messages}}` - Conversation messages array -- `{{callEndedReason}}` - How the call ended +- `{{messages}}` - Conversation messages array (JSON) +- `{{endedReason}}` - How the call ended +- `{{duration}}` - Call duration in seconds +- `{{startedAt}}` - Call start time (ISO 8601) +- `{{endedAt}}` - Call end time (ISO 8601) +- `{{systemPrompt}}` - The assistant's system prompt +- `{{structuredOutput}}` - The full structured output definition - `{{structuredOutput.name}}` - Output name - `{{structuredOutput.description}}` - Output description - `{{structuredOutput.schema}}` - Schema definition + +When you supply custom `messages`, reference either `{{transcript}}` or `{{messages}}` for the conversation, and a variation of `{{structuredOutput}}` so the model has the schema definition. + + ## API reference - +The full set of request fields, response types, and query parameters lives in the API reference. Refer there for all possible values rather than duplicating them here. ### Create structured output - - Display name for the structured output (max 40 characters) - - - - Must be set to "ai" - - - - Description of what data to extract - - - - JSON Schema defining the structure of data to extract - - - - Array of assistant IDs to link this output to - + - - Custom model configuration for extraction - +See [Create structured output](/api-reference/structured-outputs/structured-output-controller-create) for every request field, including `type`, `conditions`, `model`, and `assistantIds`. ### Update structured output - -To update the top level schema type after creation, you must include `?schemaOverride=true` as a query parameter in the URL - + +Updating the top-level schema type after creation requires the `?schemaOverride=true` query parameter. See [Update structured output](/api-reference/structured-outputs/structured-output-controller-update). + ### List structured outputs -Query parameters: -- `page` - Page number (default: 1) -- `limit` - Results per page (default: 20, max: 100) +See [List structured outputs](/api-reference/structured-outputs/structured-output-controller-find-all) for all query parameters, including filtering, sorting, and pagination. ### Delete structured output @@ -712,7 +792,7 @@ Query parameters: ### Performance tips - **Keep schemas focused**: Extract only what you need to minimize processing time -- **Use appropriate models**: GPT-4 for complex schemas, GPT-3.5 for simple ones +- **Use appropriate models**: use a capable model (for example, GPT-4.1) for complex schemas; lighter models can handle simpler ones - **Set low temperature**: Use 0.1 or lower for consistent extraction - **Monitor success rates**: Track extraction failures and adjust schemas accordingly @@ -758,19 +838,6 @@ if (data.result === null) { - Make fields optional if they might not be mentioned - Verify data types match expected values -## HIPAA compliance - - -**Important for HIPAA-enabled organizations:** - -If your organization has HIPAA compliance enabled (`hipaaEnabled: true`), structured outputs are **disabled by default** to protect PHI (Protected Health Information). - -To use structured outputs with HIPAA compliance: -- Contact the Vapi team to enable structured outputs -- Ensure you understand the implications for PHI handling -- Follow all HIPAA compliance best practices when extracting sensitive health data - - ## Limitations diff --git a/fern/assistants/versioning/overview.mdx b/fern/assistants/versioning/overview.mdx new file mode 100644 index 000000000..a808f3520 --- /dev/null +++ b/fern/assistants/versioning/overview.mdx @@ -0,0 +1,41 @@ +--- +title: Versioning +subtitle: Save, publish, and restore versions of your assistants and tools +description: Versioning saves published assistant and tool configurations so you can make changes in a draft, review their history, and restore an earlier version. +slug: assistants/versioning +--- + +Versioning lets you change an [assistant](/assistants) or [tool](/tools) without affecting live calls. Publish the draft when it is ready, review earlier versions, or restore an earlier configuration. + +## The versioning lifecycle + +Assistants and tools both support drafts, publishing, and version history: + +- **Draft**: Contains your unpublished changes. Drafts are per user, so your edits stay separate from your teammates'. Draft changes do not affect live calls. +- **Publish**: Creates a new version from the draft. The new version becomes the current published version. +- **History**: Keeps every published version so you can review what changed and when. +- **Restore an assistant**: Immediately creates a new current version from an earlier configuration and replaces any draft changes. +- **Restore a tool**: Loads an earlier configuration into the draft. Publish the restored draft to create the next current version. + + +The **current** version is the configuration used by live calls. Publishing a draft makes the new version current. Restoring an assistant version creates a new current version immediately. + + +## Which version a call uses + +- **Inbound calls** use the assistant's current published version. You cannot select another version for an inbound call. +- **Outbound and web calls** use the current published version by default. To use a specific published version, pass `assistantVersion` with `assistantId` in the [create call request](/api-reference/calls/create). + +## Next steps + + + + Publish, view history, and restore versions of an assistant. + + + Publish, view history, and restore versions of a tool. + + + Choose the tool versions an assistant uses and learn how restoring an assistant affects them. + + diff --git a/fern/assistants/versioning/versioning-assistants.mdx b/fern/assistants/versioning/versioning-assistants.mdx new file mode 100644 index 000000000..a4c84921b --- /dev/null +++ b/fern/assistants/versioning/versioning-assistants.mdx @@ -0,0 +1,109 @@ +--- +title: Versioning with assistants +subtitle: Publish, view history, and restore versions of an assistant +description: Publish assistant changes, review version history, restore an earlier configuration as a new current version, and select the published assistant version for a call. +slug: assistants/versioning/versioning-assistants +--- + +## How assistant versioning works + +[Assistants](/assistants) follow the [versioning lifecycle](/assistants/versioning). Edit the draft, then publish it to create a version. Published versions do not change. To reuse an earlier configuration, restore it. Vapi immediately creates a new version from that configuration and makes it current. + +The assistant list and header show the selected version. A draft appears separately when the assistant has unpublished changes. + + + Jamie assistant with the Versions menu open and version v1 named First draft marked Current + + +## Publish a new version + +Publishing turns your current draft into a new version and makes it the **current** version. + + + + Make changes to the assistant. Vapi saves your edits automatically as a draft. The changes do not affect live calls. + + + Select **Publish** to compare the draft with the current published version. In the diff, you can copy individual lines, wrap long lines, move between changes, or copy the complete diff. + + + Publish Assistant dialog comparing Jamie's draft first message with the current published version + + + + Give the version a name. You can also add a short description so teammates understand what changed and why. + + + Publish Assistant dialog with Clarify opening message entered as the version name and a description of the update + + + + Select **Publish** to create the version and make it current. To publish with the default settings, select **Quick Publish**. To remove the draft changes, select **Discard Changes…**. + + + +## View version history + +Open the version menu in the assistant header to see recent versions. Select **View Full History** to see all versions. The current published version is marked **Current**. Each version includes its version number, name, description, and publication time. + + + Jamie assistant Version History panel showing Clarify opening message as the current v2 and First draft as v1 + + +From the version history, you can: + +- Select **View changes** to compare a version with the previous version +- Select **Export** to download a version as JSON +- Select **Restore** to make an earlier configuration current as a new version + + + Changes in v2 compared with v1 showing the updated firstMessage value + + +## Restore a previous version + +Open the version history and select **Restore** for an earlier version. Review the confirmation, then select **Restore version**. Vapi immediately creates a new version from the selected configuration and makes the new version current. For example, restoring v1 while v2 is current creates v3 with the v1 configuration. + + + Restore version confirmation explaining that restoring v1 as the active version takes effect immediately + + + +Restoring a version takes effect immediately and replaces any current draft changes. + + +The new version includes the tool version selections saved with the restored assistant version. A tool set to **Latest** continues to use its newest published version. See [How versioning works with assistants and tools](/assistants/versioning/versioning-with-assistants-and-tools). + +## Which version a call uses + +- **Inbound calls** use the assistant's current published version. You cannot select another version for an inbound call. +- **Outbound and web calls** use the current published version by default. To use a specific published version, pass `assistantVersion` with `assistantId` in the [create call request](/api-reference/calls/create). + +## Next steps + + + + Save, publish, and restore versions of your assistants and tools. + + + Choose the tool versions an assistant uses and learn how restoring an assistant affects them. + + diff --git a/fern/assistants/versioning/versioning-tools.mdx b/fern/assistants/versioning/versioning-tools.mdx new file mode 100644 index 000000000..3da2b2c0c --- /dev/null +++ b/fern/assistants/versioning/versioning-tools.mdx @@ -0,0 +1,90 @@ +--- +title: Versioning with tools +subtitle: Publish, view history, and restore versions of a tool +description: Publish tool changes, review version history, restore an earlier configuration to the draft, and select the specific tool version that an assistant uses. +slug: assistants/versioning/versioning-tools +--- + +## How tool versioning works + +[Tools](/tools) follow the [versioning lifecycle](/assistants/versioning). Edit the draft, then publish it to create a version. Published versions do not change. To reuse an earlier configuration, restore it to the draft and publish the draft as the next version. + +A tool's versions are independent of an assistant's versions. An assistant can use a specific tool version or the **Latest** version. See [How versioning works with assistants and tools](/assistants/versioning/versioning-with-assistants-and-tools). + +The tool header shows the selected version. A draft appears separately when the tool has unpublished changes. + +## Publish a new version + +Publishing turns your current draft into a new version and makes it the **current** version. + + + + Open the [Dashboard](https://dashboard.vapi.ai), select **Tools**, and select the tool you want to update. + + + Change the tool's configuration. Vapi saves your edits automatically as a draft. The changes do not affect live calls. + + + Select **Publish** to compare the draft with the current published version. In the diff, you can copy individual lines, wrap long lines, move between changes, or copy the complete diff. + + + Give the version a name. You can also add a short description so teammates understand what changed and why. + + + Select **Publish** to create the version and make it current. To publish with the default settings, select **Quick Publish**. To remove the draft changes, select **Discard Changes…**. + + + +## View version history + + + + Open the [Dashboard](https://dashboard.vapi.ai), select **Tools**, and select the tool whose history you want to review. + + + Select the version number in the tool header to see recent versions. The current published version is marked **Current**. + + + Select **View Full History**. Each version includes its version number, name, description, and publication time. + + + +From the version history you can: + +- Select **View changes** to compare a version with the previous version +- Select **Export** to download a version as JSON +- Select **Restore** to load a version into the draft + +## Restore a previous version + + + + Open the version history and select **Restore** for an earlier version. + + + Review the confirmation, then select **Restore**. Vapi loads the selected configuration into the editor as a draft and replaces the current draft changes. + + + Review the draft, then select **Publish** to create the next version and make it current. + + + + +Restoring a version replaces the tool's current draft changes. + + +Restoring a tool version does not change which version an assistant uses. The assistant continues to use the selected version or **Latest**. See [How versioning works with assistants and tools](/assistants/versioning/versioning-with-assistants-and-tools). + +## Next steps + + + + Save, publish, and restore versions of your assistants and tools. + + + Publish, view history, and restore versions of an assistant. + + + Choose the tool versions an assistant uses and learn how restoring an assistant affects them. + + diff --git a/fern/assistants/versioning/versioning-with-assistants-and-tools.mdx b/fern/assistants/versioning/versioning-with-assistants-and-tools.mdx new file mode 100644 index 000000000..c8d559eb8 --- /dev/null +++ b/fern/assistants/versioning/versioning-with-assistants-and-tools.mdx @@ -0,0 +1,66 @@ +--- +title: How versioning works with assistants and tools +subtitle: Choose the tool versions an assistant uses and understand how restores affect them +description: Select a specific or latest tool version for an assistant, and learn how restoring an assistant also restores the tool version selections saved with it. +slug: assistants/versioning/versioning-with-assistants-and-tools +--- + +## How version pinning works + +Assistants and tools are [versioned independently](/assistants/versioning), but an assistant configuration records which version of each tool to use. You can select a numbered version or **Current**, which appears as **Latest** when the menu is closed. When you publish the assistant, Vapi saves those selections in the assistant version. + +## Choose a tool version in the Dashboard + + + + Open the [Dashboard](https://dashboard.vapi.ai), select **Assistants**, and select the assistant that uses the tool. + + + Select **Tools**. + + + Under **Assign Tool Version**, open the version menu for the tool. Choose one of these options: + + - **Current**: Always use the tool's current version. The closed menu displays **Latest**. + - **Numbered version**: Pin the assistant to a specific version, such as **v3**. The assistant stays on that version until you change the selection and publish the assistant again. + + + Jamie assistant Tools tab with the Assign Tool Version menu open for a transfer call tool + + + + Select **Publish** and complete the publish flow to save the tool version selection in a new assistant version. + + + +## Use the latest tool version through the API + +When you [create](/api-reference/assistants/create) or [update](/api-reference/assistants/update) an assistant through the API, omit the tool version to use **Latest**. The assistant then uses the newest published version of that tool. + +## How restoring an assistant affects tools + +When you restore an assistant version, Vapi immediately creates a new current assistant version with its saved tool version selections. A specific tool version returns to the saved selection. A tool set to **Latest** continues to use its newest published version. + +For example: + +- At **v6**, the assistant uses **Tool A v4** and **Tool B v6**. +- The assistant's **v5** configuration used **Tool A v2** and **Tool B v4**. +- You restore assistant **v5**. Vapi creates assistant **v7**, makes it current, and restores the selections for Tool A v2 and Tool B v4. +- If Tool B was set to **Latest** in assistant v5, it continues to use the newest published Tool B version. + +## Next steps + + + + Save, publish, and restore versions of your assistants and tools. + + + Publish, view history, and restore versions of an assistant. + + + Publish, view history, and restore versions of a tool. + + diff --git a/fern/billing/manage-billing-and-credits.mdx b/fern/billing/manage-billing-and-credits.mdx new file mode 100644 index 000000000..9af800f02 --- /dev/null +++ b/fern/billing/manage-billing-and-credits.mdx @@ -0,0 +1,70 @@ +--- +title: "Manage pay-as-you-go billing and credits" +subtitle: "Add a payment method, buy credits, configure auto reload, and download billing records." +description: "Manage pay-as-you-go billing in the Vapi Dashboard: add a payment method, buy credits, configure auto reload, and download PDF statements and invoices." +slug: billing/manage-billing-and-credits +--- + +This guide shows you how to set up billing for a pay-as-you-go subscription. By the end, you can fund the subscription and configure automatic credit purchases. + +## Prerequisites + +- An **Admin** role in the organization. + +## Steps + + + + Sign in to the [Vapi Dashboard](https://dashboard.vapi.ai), select the organization you want to fund, open **Settings**, then select **Billing & Add-Ons**. + + + Billing & Add-Ons selected in the Dashboard Settings navigation + + + + + In **Payment method**, enter the billing email and card details. Select the checkmark beside each field to save it. + + To replace a saved card, select the pencil beside **Payment method**, enter the new card details, then select the checkmark. + + + Full Payment method block with the billing email blurred, card field, and auto reload controls + + + + + At the top of the Billing page, select **Buy credits**. In **Purchase Vapi credits**, enter at least `$10` in **Amount to purchase**, then select **Purchase**. + + Complete any verification requested by the card issuer. A successful purchase increases the credit balance and appears as **Finalized** in **Credit purchase history**. + + + Purchase Vapi credits dialog with the amount to purchase field + + + + + In **Payment method**, turn on **Enable auto reload**. Enter at least `$10` in **Amount to reload**, then enter the balance that should trigger the purchase in **When threshold reaches**. + + Select **Save changes**, review the confirmation, then select **Confirm**. If the current balance is at or below the threshold, saving the plan charges the payment method immediately. + + + Auto reload controls on the live Billing page + + + + + Confirm that the page shows the saved payment method, updated credit balance, and auto reload settings. Check **Credit purchase history** for a **Finalized** payment. + + + +## Download billing records + +Select **Download monthly statement** in **Credit purchase history** to create a statement for a selected month. + +To download an invoice for an eligible payment, select the payment, then select **Download invoice (PDF)**. Enter the requested invoice information and select **Confirm**. + +## Related + + + Resolve calls blocked by an insufficient credit balance or frozen subscription. + diff --git a/fern/billing/purchase-call-concurrency.mdx b/fern/billing/purchase-call-concurrency.mdx new file mode 100644 index 000000000..a10362860 --- /dev/null +++ b/fern/billing/purchase-call-concurrency.mdx @@ -0,0 +1,49 @@ +--- +title: "Purchase call concurrency" +subtitle: "Increase your organization's call concurrency from the Dashboard." +description: "Purchase call concurrency from Billing & Add-Ons to increase the number of simultaneous calls available to your Vapi organization." +slug: billing/purchase-call-concurrency +--- + +Purchase call concurrency when your organization needs to run more simultaneous calls than its plan includes. + +## How call lines affect concurrency + +Call concurrency is the number of Vapi calls that can be active at the same time. Each reserved call line adds one simultaneous call to your organization's included concurrency. + +All inbound and outbound calls share the organization's capacity. A campaign's **Max concurrency** setting limits that campaign, but it does not purchase or reserve additional call lines. + +## Prerequisites + +- An **Admin** role in the organization. +- Enough Vapi credits to cover the prorated charge shown before purchase. + +## Purchase call concurrency + + + + Sign in to the [Vapi Dashboard](https://dashboard.vapi.ai), select the organization you want to update, open **Settings**, then select **Billing & Add-Ons**. + + + + In **Add-ons**, find **Reserved concurrency (call lines)**. Enter the total number of add-on call lines you want the organization to have. + + This value represents purchased call lines, not the organization's total concurrency. For example, if the plan includes 10 calls and you enter `5`, the organization has 15 call lines after the purchase. + + + Reserved concurrency call-line field used to purchase call concurrency in Billing and Add-Ons + + + + + Review **Add-ons summary** and **Pricing preview**. The preview shows the new monthly charge and the prorated amount due for the remainder of the current billing period. + + + + Select **Purchase add-ons**, review the confirmation dialog, then select **Confirm**. The additional call lines become available after the purchase succeeds. + + + + Confirm that **Reserved concurrency (call lines)** shows the purchased amount. The organization's concurrency limit now includes those additional call lines. + + diff --git a/fern/call-forwarding.mdx b/fern/call-forwarding.mdx index 58e1c75d8..e607e841e 100644 --- a/fern/call-forwarding.mdx +++ b/fern/call-forwarding.mdx @@ -11,6 +11,13 @@ Vapi's call forwarding functionality allows you to redirect calls to different p - **`transferCall` Tool**: This tool enables call forwarding to predefined phone numbers with specific messages based on the destination. + +Looking for dynamic routing decided at runtime? Use a `transferCall` tool with an empty `destinations` array and either: +- Have the assistant supply a destination parameter (e.g., `phoneNumber`) directly; no webhook is sent. +- Or respond from your server to the `transfer-destination-request` webhook with a destination. +See: Dynamic call transfers. + + ### Parameters and Messages - **Destinations**: A list of phone numbers where the call can be forwarded. diff --git a/fern/calls/assistant-based-warm-transfer.mdx b/fern/calls/assistant-based-warm-transfer.mdx index 1e7d3ce33..fad473a79 100644 --- a/fern/calls/assistant-based-warm-transfer.mdx +++ b/fern/calls/assistant-based-warm-transfer.mdx @@ -1,323 +1,218 @@ --- -title: Assistant-based warm transfer -subtitle: Use AI assistants to facilitate call transfers +title: Configure assistant-based warm transfer +subtitle: Let an AI assistant introduce a caller before connecting a transfer. +description: Configure an assistant-based warm transfer in the Vapi Dashboard or API, including operator prompts, fallback behavior, summaries, custom audio, and testing. slug: calls/assistant-based-warm-transfer --- -## Overview - -Assistant-based warm transfer uses a dedicated AI assistant to handle the transfer process. You control how this assistant behaves through prompts and configuration. The assistant has access to the previous customer conversation and follows your instructions to decide whether to complete or cancel the transfer. - -**In this guide, you'll learn to:** -- Configure transfer assistants with custom prompts -- Control how the assistant interacts with operators -- Handle failed transfer scenarios - -## How it works - -When using assistant-based warm transfer: - -1. **Customer requests transfer** - The original assistant initiates the transfer -2. **Customer placed on hold** - Customer hears hold music while transfer is attempted -3. **Transfer assistant calls operator** - A dedicated assistant is placed on the call to the destination -4. **Assistant follows your prompts** - The transfer assistant has access to the previous conversation context and follows your configured behavior -5. **Transfer decision** - Based on the interaction, the assistant either: - - **Completes transfer** (`transferSuccessful`) - Merges the calls and exits - - **Cancels transfer** (`transferCancel`) - Returns the customer to the original assistant - -**Transfer cancellation occurs when:** -- `maxDurationSeconds` is reached -- Operator doesn't answer -- Voicemail is detected (based on your prompt configuration) -- Any condition you define in your prompts - -## Configuration - - -The `function.name` property identifies your transfer tool. Use this name when instructing your assistant to perform transfers in system prompts. - - - -```json title="Basic Configuration" -{ - "type": "transferCall", - "function": { - "name": "salesTransferAssistant" - }, - "destinations": [ - { - "type": "number", - "number": "+14155551234", - "transferPlan": { - "mode": "warm-transfer-experimental", - "transferAssistant": { - "firstMessage": "Hello, I have a customer on the line. Are you available to take this call?", - "maxDurationSeconds": 120, - "model": { - "provider": "openai", - "model": "gpt-4o", - "messages": [ - { - "role": "system", - "content": "You are a transfer assistant designed to facilitate call transfers between a customer and an operator. Your core responsibility is to talk to the operator and manage the transfer process efficiently. \n\n## Core Responsibility \n - Facilitate the transfer process by using transferSuccessful or transferCancel tools. Engage briefly with the operator as needed and then facilitate the transfer by calling the corresponding transfer tool. \n ## When to Respond\n- Answer questions about the transfer process or provide summaries when specifically asked by the operator\n- Respond to direct questions about the current transfer situation\n\\n ## Transfer Tools\n- Use transferSuccessful when the operator agrees to accept the call\n- Use transferCancel when the transfer cannot be completed\n\n- Only call the tool when you addressed all the operators questions" - } - ] - } - } - } - } - ], - "messages": [ - { - "type": "request-start", - "content": "I'll transfer you to our sales team. Please hold for a moment." - }, - { - "type": "request-failed", - "content": "I apologize, but I'm having trouble connecting your call. Is there anything else I can help you with?" - } - ] -} -``` - - -### Transfer assistant properties - - - The initial message spoken by the transfer assistant when the operator answers - - - - Maximum duration in seconds for the operator call. The transfer is automatically cancelled if this limit is reached. - - - - Assistant configuration including provider, model, and system messages that control the transfer assistant's behavior - - -## Built-in tools - -The transfer assistant has access to two built-in tools: - - -You can configure the transfer assistant to perform various tasks before making a decision, such as: -- Informing the operator about the customer's needs -- Asking the operator specific questions -- Following custom business logic you define in the prompts - - -### transferSuccessful - -Completes the transfer by: -- Merging the customer and operator calls -- Removing the transfer assistant from the call -- Connecting the parties directly - -### transferCancel - -Cancels the transfer by: -- Disconnecting from the operator -- Returning the customer to the original assistant -- Optionally playing a fallback message - -## Additional examples - -### Handling operator interactions - -The transfer assistant can be configured to handle various operator responses: - - -```json title="Detailed Transfer Configuration" -{ - "type": "transferCall", - "function": { - "name": "warmTransferWithContext" - }, - "destinations": [ - { - "type": "number", - "number": "+14155551234", - "transferPlan": { - "mode": "warm-transfer-experimental", - "transferAssistant": { - "firstMessage": "Hi, I have a customer on the line who needs help with their recent order. Are you available?", - "maxDurationSeconds": 90, - "model": { - "provider": "openai", - "model": "gpt-4o", - "messages": [ - { - "role": "system", - "content": "You are a transfer assistant. Your tasks:\n1. Confirm the operator is human and available\n2. Provide brief context about the customer's needs\n3. If they accept, call transferSuccessful\n4. If they decline or you detect voicemail, call transferCancel\n5. Keep the conversation under 30 seconds" - } - ] - } - } - } - } - ], - "messages": [ - { - "type": "request-start", - "content": "Transferring you to our specialist. Please hold." - }, - { - "type": "request-failed", - "content": "I couldn't reach our specialist. Please try again later.", - "endCallAfterSpokenEnabled": true - } - ] -} -``` - - -### Multiple departments - -Configure different transfer assistants for different departments: - - -```json title="Department-specific Transfers" -{ - "type": "transferCall", - "function": { - "name": "departmentTransferAssistant" - }, - "destinations": [ - { - "type": "number", - "number": "+1234567890", - "description": "Sales team transfer line", - "transferPlan": { - "mode": "warm-transfer-experimental", - "transferAssistant": { - "firstMessage": "Hey there, I have a potential customer interested in our enterprise plans. Are you available to pick up the call?", - "maxDurationSeconds": 60, - "model": { - "provider": "openai", - "model": "gpt-4o", - "messages": [ - { - "role": "system", - "content": "You are a transfer assistant designed to facilitate call transfers between a customer and an operator. Your core responsibility is to talk to the operator and manage the transfer process efficiently. \n\n## Core Responsibility \n - Facilitate the transfer process by using transferSuccessful or transferCancel tools. Engage briefly with the operator as needed and then facilitate the transfer by calling the corresponding transfer tool. \n ## When to Respond\n- Answer questions about the transfer process or provide summaries when specifically asked by the operator\n- Respond to direct questions about the current transfer situation\n\\n ## Transfer Tools\n- Use transferSuccessful when the operator agrees to accept the call\n- Use transferCancel when the transfer cannot be completed\n\n- Only call the tool when you addressed all the operators questions" - } - ], - "tools": [ +Assistant-based warm transfer places the customer on hold while a transfer assistant calls the destination. The transfer assistant can give the operator context, confirm that a person is ready, and then complete or cancel the transfer. + +Use this mode when the destination must accept the call or receive context before speaking with the customer. For a direct transfer without an operator conversation, use the [transfer call tool](/tools/transfer-call) with its default blind-transfer mode. + +## Prerequisites + +Before you configure the transfer, prepare: + +- A Vapi assistant that handles phone calls +- A destination phone number in E.164 format, for example, `+14155550100` +- A private Vapi API key for the curl method +- A publicly accessible MP3 or WAV file if you want custom hold or completion audio + +## How assistant-based warm transfer works + +When the original assistant invokes the transfer call tool: + +1. The customer hears the configured transfer message and is placed on hold. +2. Vapi calls the destination and starts the transfer assistant. +3. The transfer assistant speaks with the operator and uses the previous conversation as context by default. +4. The transfer assistant calls `transferSuccessful` to connect the parties or `transferCancel` to return the customer to the original assistant. +5. If the destination is busy, unreachable, or not human, the fallback plan determines what the customer hears and whether the call ends. + +The `transferSuccessful` and `transferCancel` tools are always available to the transfer assistant. You can customize them through the API, but you do not need to add them to a basic configuration. + +## Configure the warm transfer + +Create a reusable transfer call tool, configure a phone-number destination, and add the tool to the original assistant. + + + + + + In the Vapi Dashboard, open **Tools**, click **Create Tool**, and select **Transfer Call**. Enter a name and a description that state when the assistant should use the tool. + + + + Under **Destinations**, click **Add Destination**, then select **Phone Number**. Enter the destination in E.164 format and describe when the assistant should select it. + + + + Expand **Transfer Plan**. Under **Transfer Mode**, select **Warm Transfer - Experimental**. + + + + Enter the **Message to Operator**. Under **Fallback Plan**, set the message spoken to the customer when the transfer fails and choose whether to end the call. Under **Summary Plan**, choose whether to generate a conversation summary for the operator. + + + + Click **Save**. Open **Assistants**, select the original assistant, and add the tool from the assistant's **Tools** section. Update the system prompt with the conditions for starting the transfer, then save the assistant. + + + + The Dashboard exposes the transfer mode, operator message, fallback plan, and summary plan. Use the API to configure a custom transfer-assistant model, prompt, timeouts, voice, hold audio, or completion audio. + + + + + + Replace `YOUR_API_KEY`, then create the reusable tool with the [Create Tool endpoint](/api-reference/tools/create). + + ```bash + curl --request POST \ + --url https://api.vapi.ai/tool \ + --header 'Authorization: Bearer YOUR_API_KEY' \ + --header 'Content-Type: application/json' \ + --data '{ + "type": "transferCall", + "destinations": [ { - "type": "transferSuccessful", // built-in tool - "function": { - "name": "transferSuccessful", - "description": "Confirm the transfer when operator accepts" - }, - "messages": [ - { - "type": "request-start", - "content": "Great! I'll connect you to the customer now. One moment please." + "type": "number", + "number": "+14155550100", + "description": "Transfer to an account specialist after the customer agrees", + "transferPlan": { + "mode": "warm-transfer-experimental", + "transferAssistant": { + "firstMessage": "Hello, I have a customer who needs help with an account issue. Are you available to take the call?", + "firstMessageMode": "assistant-speaks-first", + "maxDurationSeconds": 120, + "silenceTimeoutSeconds": 30, + "model": { + "provider": "openai", + "model": "gpt-4o", + "messages": [ + { + "role": "system", + "content": "Confirm that a human operator is ready. Use transferSuccessful when the operator accepts the call. Use transferCancel for voicemail, no answer, or a declined transfer. Keep the conversation focused on the transfer." + } + ] + } }, - { - "type": "request-complete", - "content": "https://desert-horse-9859.twil.io/assets/call_complete_chime.mp3" + "holdAudioUrl": "https://example.com/audio/hold.mp3", + "transferCompleteAudioUrl": "https://example.com/audio/transfer-complete.mp3", + "fallbackPlan": { + "message": "I could not reach an account specialist. I can continue helping you.", + "endCallEnabled": false } - ] - }, + } + } + ], + "messages": [ { - "type": "transferCancel", // built-in tool - "function": { - "name": "transferCancel", - "description": "Cancel the transfer if operator declines or is unavailable" - }, - "messages": [ - { - "type": "request-complete", - "content": "I'll let the customer know about it." - } - ] + "type": "request-start", + "content": "I will call an account specialist now. Please hold." }, { - "type": "function", // custom tool - "function": { - "name": "getCustomerInfo", - "description": "Get detailed customer information" - }, - "server": { - "url": "https://vapi-webhook-listener-five.vercel.app/customer" - } + "type": "request-failed", + "content": "I could not start the transfer." } ] - } - } - } - }, - { - "type": "number", - "number": "+0987654321", - "description": "Technical Support team transfer line", - "transferPlan": { - "mode": "warm-transfer-experimental", - "transferAssistant": { - "firstMessage": "Hey there, I have a customer experiencing issues with API integration. Can you help?", - "maxDurationSeconds": 90, - "model": { - "provider": "openai", - "model": "gpt-4o" - } - } - } - } - ], - "messages": [ - { - "type": "request-start", - "content": "I'll transfer you to our team. Please hold for a moment." - }, - { - "type": "request-complete", - "content": "https://desert-horse-9859.twil.io/assets/soothing-sound.mp3" // played as hold music on the customer's side of the call - }, - { - "type": "request-failed", - "content": "Sorry, none of our account executives are available right now. Our team get back to you later." - } - ] -} -``` - - -## Best practices - - -**First message**: Keep it brief and state the purpose clearly. - - - -**Timeout duration**: Set `maxDurationSeconds` between 60-120 seconds. This limits how long the operator call can last before automatic cancellation. - - - -**System prompts**: Configure your prompts to handle voicemail detection, busy signals, and operator unavailability. - - -### System prompt configuration - -Configure your transfer assistant to: -- **Detect voicemail** - Recognize automated messages and call `transferCancel` -- **Verify human presence** - Confirm a person answered before proceeding -- **Provide context** - Explain the customer's situation based on your knowledge -- **Handle rejections** - Define behavior when operators decline -- **Manage timing** - Complete interactions before `maxDurationSeconds` - -## Limitations - - -- Requires `warm-transfer-experimental` mode -- Only works with Twilio phone numbers -- Calls are limited by `maxDurationSeconds` to prevent indefinite duration -- Built-in tools (`transferSuccessful`, `transferCancel`) are predefined and cannot be removed -- The transfer assistant has access to the previous conversation context - - -## Next steps - -Now that you've configured assistant-based warm transfers: -- **[Call forwarding](mdc:docs/call-forwarding):** Learn about other transfer modes and options -- **[Assistant configuration](mdc:docs/assistants):** Configure assistant models and prompts -- **[Custom tools](mdc:docs/tools/custom-tools):** Add custom tools to your assistants + }' + ``` + + The response contains the reusable tool's `id`. Save it as `TOOL_ID` for the next request. + + + + Replace `ASSISTANT_ID` and `TOOL_ID`, then update the assistant with the [Update Assistant endpoint](/api-reference/assistants/update). + + ```bash + curl --request PATCH \ + --url https://api.vapi.ai/assistant/ASSISTANT_ID \ + --header 'Authorization: Bearer YOUR_API_KEY' \ + --header 'Content-Type: application/json' \ + --data '{ + "model": { + "toolIds": ["TOOL_ID"] + } + }' + ``` + + If the assistant already has reusable tools, include their IDs in `toolIds` so this update does not remove them. + + + + + +## Configure transfer behavior + +Use these fields to control the transfer assistant and the two call legs. + +| Field | Controls | Default or constraint | +| --- | --- | --- | +| `transferAssistant.firstMessage` | What the transfer assistant says when the operator answers | If omitted, the assistant waits for the operator and generates a response | +| `transferAssistant.firstMessageMode` | Whether the transfer assistant speaks first or waits | `assistant-speaks-first` | +| `transferAssistant.maxDurationSeconds` | Maximum length of the transfer-assistant conversation | 120 seconds; allowed range is 10–43,200 seconds | +| `transferAssistant.silenceTimeoutSeconds` | Silence allowed before the transfer is canceled | 30 seconds; allowed range is 5–3,600 seconds | +| `transferAssistant.model` | Model and instructions used for the operator conversation | Required when you configure `transferAssistant` | +| `holdAudioUrl` | MP3 or WAV audio played to the customer while on hold | Default hold audio | +| `transferCompleteAudioUrl` | MP3 or WAV audio played to the destination after the introduction | No custom completion audio | +| `fallbackPlan` | Customer message and end-call behavior when the transfer fails | Default fallback behavior when omitted | +| `contextEngineeringPlan` | Conversation context provided to the transfer assistant | All previous messages | + +`firstMessageMode` also accepts `assistant-waits-for-user` and `assistant-speaks-first-with-model-generated-message`. Use the model-generated option when the introduction should adapt to the preceding conversation. + +## Prompt the transfer assistant + +Keep the transfer assistant's system message focused on the operator conversation. Define when to use each built-in tool: + +- Call `transferSuccessful` after a human operator confirms that they will take the call +- Call `transferCancel` for voicemail, a busy signal, no answer, or an operator who declines +- Answer questions about the transfer or give a brief customer summary +- Avoid unrelated conversation and complete the decision before `maxDurationSeconds` + +The transfer assistant receives the previous conversation by default. Set `contextEngineeringPlan.type` to `none` when the operator must not receive that context, or use `lastNMessages` to limit it. + +## Verify the warm transfer + +Place a test call and trigger the transfer. Confirm that: + +1. The customer hears the transfer message and hold audio. +2. The destination receives the call and hears the transfer assistant. +3. Accepting the call connects the customer and operator. +4. Declining the call or reaching voicemail returns the customer to the original assistant or ends the call according to `fallbackPlan`. + +In **Logs → Call Logs**, inspect the original call, destination call leg, transcript, and ended reason. An `assistant-forwarded-call` ended reason confirms that the transfer was initiated; it does not confirm that the destination answered. + +## Troubleshooting + +| Symptom | Likely cause | Resolution | +| --- | --- | --- | +| The customer is transferred without an operator conversation | The destination uses a blind or non-assistant warm-transfer mode | Set `transferPlan.mode` to `warm-transfer-experimental`. | +| The transfer assistant never speaks | `firstMessage` is omitted or `firstMessageMode` waits for the operator | Set `firstMessage` and use `assistant-speaks-first`, or let the operator speak first. | +| The transfer assistant talks but never connects the parties | The prompt does not require `transferSuccessful` | Tell the transfer assistant to call `transferSuccessful` immediately after the operator accepts. | +| Voicemail or a declined transfer connects anyway | The prompt does not define cancellation conditions | Require `transferCancel` for voicemail, busy signals, no answer, and declined transfers. | +| The customer hears the wrong audio | Hold audio was configured as a tool message | Put customer hold audio in `transferPlan.holdAudioUrl`. Use `transferCompleteAudioUrl` for audio played to the destination after the introduction. | +| The customer cannot continue after a failed transfer | `fallbackPlan.endCallEnabled` is `true` | Set it to `false` so the original assistant remains on the call. | +| The transfer ends during a long operator interaction | A duration or silence timeout is too short | Increase `maxDurationSeconds` or `silenceTimeoutSeconds` within the supported ranges. | + +Check **Logs → API Logs** for validation and transfer errors. If Vapi initiated the transfer but the destination never rings, inspect the telephony provider's call detail records and follow [Troubleshoot call forwarding drops](/calls/troubleshoot-call-forwarding-drops). + +## API reference + +The [Create Tool API reference](/api-reference/tools/create) documents the public transfer call destination and transfer-plan fields. This guide shows the additional transfer-assistant configuration used with `warm-transfer-experimental`. + +## Related guides + + + + Create a transfer call tool and configure its destinations. + + + Introduce the caller with a message, summary, or TwiML. + + + Choose a transfer destination at runtime. + + + Diagnose failed or incomplete transfers. + + diff --git a/fern/calls/call-concurrency.mdx b/fern/calls/call-concurrency.mdx new file mode 100644 index 000000000..0907fdec4 --- /dev/null +++ b/fern/calls/call-concurrency.mdx @@ -0,0 +1,157 @@ +--- +title: Understanding Call Concurrency +subtitle: Plan, monitor, and scale simultaneous Vapi calls +slug: calls/call-concurrency +description: Learn how concurrency slots work, how to stay within the default limit, and how to raise capacity for larger campaigns. +--- + +## Overview + +Call concurrency represents how many Vapi calls can be active at the same time. Each call occupies one slot, similar to using a finite set of phone lines. + +**In this guide, you'll learn to:** +- Understand the default concurrency allocation and when it is usually sufficient +- Keep outbound and inbound workloads within plan limits +- Increase reserved capacity directly from the Vapi Dashboard where add-ons are available +- Inspect concurrency data through API responses and analytics queries + +## What is concurrency? + +Every Vapi account includes **10 concurrent call slots** by default. When all slots are busy, new outbound dials or inbound connections wait until a slot becomes free. + + + + Rarely hit concurrency caps unless traffic surges (launches, seasonal spikes). + + + More likely to reach limits when running large calling batches. + + + +These limits ensure the underlying compute stays reliable for every customer. Higher concurrency requires reserving additional capacity, which Vapi provides through custom or add-on plans where capacity is available. + +## Managing concurrency + +### Outbound campaigns + +Batch long lead lists into smaller chunks (for example, 50–100 numbers) and run those batches sequentially. This keeps your peak concurrent calls near the default limit while still working through large sets quickly. + +### High-volume operations + +If you regularly exceed **50,000 minutes per month**, talk with Vapi about: + +- **Custom plans** that include higher baked-in concurrency +- **Add-on bundles in the US region** that let you purchase extra call lines only when you need them + + +Use billing reports to pair minute usage with concurrency spikes so you can upgrade before calls are blocked. + + +## Increase your concurrency limit + + +Vapi's EU support and self-serve growth are frozen until 2027. Existing EU customers can continue using their accounts, but Vapi is not offering new add-ons and does not guarantee feature parity with the US region. New self-serve customers should [create an account in the US region](https://dashboard.vapi.ai/register). If you require Vapi-hosted EU data residency, [contact Sales](https://vapi.ai/sales) about selective enterprise onboarding. + + +In the US region, you can raise or reserve more call lines without contacting support: + +1. Open the [Vapi Dashboard](https://dashboard.vapi.ai/settings/billing). +2. Navigate to **Settings → Billing**. +3. Find **Reserved Concurrency (Call Lines)**. +4. Increase the limit or purchase add-on concurrency lines. + +Changes apply immediately, so you can scale ahead of known traffic surges. + +## View concurrency in call responses + +When you create a call with `POST /call`, the response includes a `subscriptionLimits` object that shows the current state of your account. + +### Example request + +```bash +curl 'https://api.vapi.ai/call' \ + -H 'authorization: Bearer {VAPI-PRIVATE-TOKEN}' \ + -H 'content-type: application/json' \ + --data-raw '{ + "assistantId": "4a170597-a0c2-4657-8c32-cb93f080cead", + "customer": {"number": "+918936850777"}, + "phoneNumberId": "c6ea6cb0-0dfb-4a65-918f-6a33abb54b64" + }' +``` + +### Example response snippet + +```json +{ + "subscriptionLimits": { + "concurrencyBlocked": false, + "concurrencyLimit": 10, + "remainingConcurrentCalls": 9 + }, + "id": "019a9046-121e-766d-bd1f-84f3ccc309c1", + "status": "queued" +} +``` + +### Field reference + +- **`concurrencyBlocked`** — `true` if the call could not start because all slots were full. +- **`concurrencyLimit`** — Total concurrent call slots currently available to your org. +- **`remainingConcurrentCalls`** — How many slots were open at the time you created the call. + +Build monitoring around these values to alert when you approach the cap. + +## Track concurrency with the Analytics API + +Use the `/analytics` endpoint to review historical concurrency usage and spot patterns that justify more capacity. + +### Example request + +```bash +curl 'https://api.vapi.ai/analytics' \ + -H 'authorization: Bearer {VAPI-PRIVATE-TOKEN}' \ + -H 'content-type: application/json' \ + --data-raw '{ + "queries": [{ + "name": "Number of Concurrent Calls", + "table": "subscription", + "timeRange": { + "start": "2025-10-16T18:30:00.000Z", + "end": "2025-11-17T05:31:10.184Z", + "step": "day" + }, + "operations": [{ + "operation": "max", + "column": "concurrency", + "alias": "concurrency" + }] + }] + }' +``` + +### Example response + +```json +[{ + "name": "Number of Concurrent Calls", + "timeRange": { + "start": "2025-10-16T18:30:00.000Z", + "end": "2025-11-17T05:31:10.184Z", + "step": "day", + "timezone": "UTC" + }, + "result": [ + { "date": "2025-11-05T00:00:00.000Z", "concurrency": 0 }, + { "date": "2025-11-10T00:00:00.000Z", "concurrency": 1 }, + { "date": "2025-11-17T00:00:00.000Z", "concurrency": 1 } + ] +}] +``` + +Adjust the `timeRange.step` to inspect usage by hour, day, or week. Peaks that align with campaign launches, seasonality, or support events highlight when you should reserve additional call lines. + +## Next steps + +- **[Call queue management](/calls/call-queue-management):** Build a Twilio queue to buffer calls when you hit concurrency caps. +- **[Outbound campaign planning](/outbound-campaigns/overview):** Design outbound strategies that pair batching with analytics. +- **[Enterprise plans](/enterprise/plans):** Review larger plans that include higher default concurrency. diff --git a/fern/calls/call-dynamic-transfers.mdx b/fern/calls/call-dynamic-transfers.mdx index 81c256ac6..5743acf49 100644 --- a/fern/calls/call-dynamic-transfers.mdx +++ b/fern/calls/call-dynamic-transfers.mdx @@ -14,7 +14,8 @@ Dynamic call transfers enable intelligent routing by determining transfer destin * Integration with CRM systems, databases, and external APIs * Conditional routing logic for departments, specialists, or geographic regions * Context-aware transfers with conversation summaries -* Fallback handling for unavailable destinations +* Custom business logic execution before completing the transfer +* Programmatic transfer control via Vapi's Call Control API ## Prerequisites @@ -24,31 +25,67 @@ Dynamic call transfers enable intelligent routing by determining transfer destin ## How It Works -Dynamic transfers operate by leaving the destination unspecified initially, then using webhooks to determine the appropriate destination when needed. +Dynamic transfers with live call control use a server-controlled pattern that gives you maximum flexibility: -**Transfer flow:** -1. **Trigger** - Voice agent determines a transfer is needed based on conversation -2. **Webhook** - Vapi sends `transfer-destination-request` to your server with call context -3. **Decision** - Your server analyzes context and external data to determine routing -4. **Response** - Server returns destination details and transfer configuration -5. **Transfer** - Vapi executes the transfer to the determined destination +1. **User initiates transfer**: The user requests a transfer in natural language during the conversation +2. **Vapi triggers custom tool**: Vapi fires your custom tool to your HTTP server +3. **Server receives control URL**: The tool payload includes `message.call.monitor.controlUrl` for live call control +4. **Execute business logic**: Your server performs any necessary operations: + - Update CRM records with call summaries + - Extract and store conversation data + - Query databases for routing decisions + - Enrich destination systems with context +5. **Complete transfer**: Your server makes a POST request to the `controlUrl` with the transfer destination +6. **Call connected**: Vapi transfers the call to the specified SIP or PSTN destination -**Available context:** Your webhook receives conversation transcript, extracted variables, customer information, function parameters, and call metadata. +Available context: Your server receives the full conversation transcript, custom parameters, call metadata, and the control URL, allowing you to make informed routing decisions and execute the transfer programmatically. + + +Parameters for custom tools are fully customizable. You can name and structure them however you like to guide routing (for example `department`, `reason`, `urgency`, `customerId`, etc.). + + +Sequence diagram + +```mermaid +sequenceDiagram + participant Customer + participant Vapi + participant Server as HTTP Server + participant CRM as CRM (Optional) + participant Dest as SIP/PSTN Destination + + Customer->>Vapi: "Can you transfer me to support?" + + Vapi->>Server: Tool call: custom_transfer_call
({ "reason": "escalation" }) + + opt Business Logic + Server->>CRM: Update customer record + CRM-->>Server: Confirm updated + end + + Server->>Vapi: POST {controlUrl}
(transfer destination) + + Vapi->>Dest: Transfer call + Dest-->>Customer: Connected to destination +``` --- ## Quick Implementation Guide - + + Create a custom tool that will receive the transfer request and provide you with the control URL to execute the transfer. + - Navigate to **Tools** in your dashboard - Click **Create Tool** - - Select **Transfer Call** as the tool type - - **Important**: Leave the destinations array empty - this creates a dynamic transfer tool - - Set function name: `dynamicTransfer` - - Add description explaining when this tool should be used + - Select **Custom** as the tool type + - Set function name: `transfer_call` + - Add a description: "Transfer the call to the appropriate department or agent" + - Define custom parameters based on your routing needs (e.g., `department`, `reason`, `urgency`, `customerId`) + - Set your server URL to receive the tool call ```typescript @@ -56,30 +93,38 @@ Dynamic transfers operate by leaving the destination unspecified initially, then const vapi = new VapiClient({ token: process.env.VAPI_API_KEY }); - const dynamicTool = await vapi.tools.create({ - type: "transferCall", - // Empty destinations array makes this dynamic - destinations: [], + const transferTool = await vapi.tools.create({ + type: "function", + async: true, function: { - name: "dynamicTransfer", - description: "Transfer call to appropriate destination based on customer needs", + name: "transfer_call", + description: "Transfer the call to the appropriate department or agent based on customer needs", parameters: { type: "object", properties: { + department: { + type: "string", + description: "Department to transfer to (e.g., 'support', 'sales', 'billing')" + }, reason: { type: "string", - description: "Reason for transfer" + description: "Reason for the transfer" }, urgency: { type: "string", - enum: ["low", "medium", "high", "critical"] + enum: ["low", "medium", "high", "critical"], + description: "Urgency level of the transfer" } - } + }, + required: ["department", "reason"] } + }, + server: { + url: "https://your-server.com/webhook" } }); - console.log(`Dynamic transfer tool created: ${dynamicTool.id}`); + console.log(`Transfer tool created: ${transferTool.id}`); ``` @@ -87,40 +132,49 @@ Dynamic transfers operate by leaving the destination unspecified initially, then import requests import os - def create_dynamic_transfer_tool(): + def create_transfer_tool(): url = "https://api.vapi.ai/tool" headers = { "Authorization": f"Bearer {os.getenv('VAPI_API_KEY')}", "Content-Type": "application/json" } - - data = { - "type": "transferCall", - "destinations": [], # Empty for dynamic routing + + tool_config = { + "type": "function", + "async": True, "function": { - "name": "dynamicTransfer", - "description": "Transfer call to appropriate destination based on customer needs", + "name": "transfer_call", + "description": "Transfer the call to the appropriate department or agent based on customer needs", "parameters": { "type": "object", "properties": { + "department": { + "type": "string", + "description": "Department to transfer to (e.g., 'support', 'sales', 'billing')" + }, "reason": { "type": "string", - "description": "Reason for transfer" + "description": "Reason for the transfer" }, "urgency": { "type": "string", - "enum": ["low", "medium", "high", "critical"] + "enum": ["low", "medium", "high", "critical"], + "description": "Urgency level of the transfer" } - } + }, + "required": ["department", "reason"] } + }, + "server": { + "url": "https://your-server.com/webhook" } } - - response = requests.post(url, headers=headers, json=data) + + response = requests.post(url, headers=headers, json=tool_config) return response.json() - tool = create_dynamic_transfer_tool() - print(f"Dynamic transfer tool created: {tool['id']}") + tool = create_transfer_tool() + print(f"Transfer tool created: {tool['id']}") ``` @@ -129,18 +183,33 @@ Dynamic transfers operate by leaving the destination unspecified initially, then -H "Authorization: Bearer $VAPI_API_KEY" \ -H "Content-Type: application/json" \ -d '{ - "type": "transferCall", - "destinations": [], + "type": "function", + "async": true, "function": { - "name": "dynamicTransfer", - "description": "Transfer call to appropriate destination based on customer needs", + "name": "transfer_call", + "description": "Transfer the call to the appropriate department or agent based on customer needs", "parameters": { "type": "object", "properties": { - "reason": {"type": "string", "description": "Reason for transfer"}, - "urgency": {"type": "string", "enum": ["low", "medium", "high", "critical"]} - } + "department": { + "type": "string", + "description": "Department to transfer to (e.g., support, sales, billing)" + }, + "reason": { + "type": "string", + "description": "Reason for the transfer" + }, + "urgency": { + "type": "string", + "enum": ["low", "medium", "high", "critical"], + "description": "Urgency level of the transfer" + } + }, + "required": ["department", "reason"] } + }, + "server": { + "url": "https://your-server.com/webhook" } }' ``` @@ -153,9 +222,8 @@ Dynamic transfers operate by leaving the destination unspecified initially, then - Navigate to **Assistants** - Create a new assistant or edit an existing one - - Add your dynamic transfer tool to the assistant - - Enable the **transfer-destination-request** server event - - Set your server URL to handle the webhook + - Add your custom transfer tool to the assistant + - Configure the system prompt to guide when transfers should occur ```typescript @@ -168,23 +236,23 @@ Dynamic transfers operate by leaving the destination unspecified initially, then messages: [ { role: "system", - content: "You help customers and transfer them when needed using the dynamicTransfer tool. Assess the customer's needs and transfer to the appropriate department." + content: "You help customers and can transfer them to the appropriate department when needed. Use the transfer_call tool when a customer requests to speak with someone or when you determine their issue requires specialist assistance. Always gather the reason for transfer before initiating it." } ], - toolIds: ["YOUR_DYNAMIC_TOOL_ID"] + toolIds: ["YOUR_TRANSFER_TOOL_ID"] }, voice: { provider: "11labs", voiceId: "burt" - }, - serverUrl: "https://your-server.com/webhook", - serverUrlSecret: process.env.WEBHOOK_SECRET + } }); + + console.log(`Assistant created: ${assistant.id}`); ``` ```python - def create_assistant_with_dynamic_transfer(tool_id): + def create_assistant_with_transfer(tool_id): url = "https://api.vapi.ai/assistant" headers = { "Authorization": f"Bearer {os.getenv('VAPI_API_KEY')}", @@ -199,17 +267,18 @@ Dynamic transfers operate by leaving the destination unspecified initially, then "model": "gpt-4o", "messages": [{ "role": "system", - "content": "You help customers and transfer them when needed using the dynamicTransfer tool. Assess the customer's needs and transfer to the appropriate department." + "content": "You help customers and can transfer them to the appropriate department when needed. Use the transfer_call tool when a customer requests to speak with someone or when you determine their issue requires specialist assistance. Always gather the reason for transfer before initiating it." }], "toolIds": [tool_id] }, - "voice": {"provider": "11labs", "voiceId": "burt"}, - "serverUrl": "https://your-server.com/webhook", - "serverUrlSecret": os.getenv("WEBHOOK_SECRET") + "voice": {"provider": "11labs", "voiceId": "burt"} } response = requests.post(url, headers=headers, json=data) return response.json() + + assistant = create_assistant_with_transfer("YOUR_TRANSFER_TOOL_ID") + print(f"Assistant created: {assistant['id']}") ``` @@ -225,78 +294,84 @@ Dynamic transfers operate by leaving the destination unspecified initially, then "model": "gpt-4o", "messages": [{ "role": "system", - "content": "You help customers and transfer them when needed using the dynamicTransfer tool." + "content": "You help customers and can transfer them to the appropriate department when needed. Use the transfer_call tool when a customer requests to speak with someone or when you determine their issue requires specialist assistance." }], - "toolIds": ["YOUR_DYNAMIC_TOOL_ID"] + "toolIds": ["YOUR_TRANSFER_TOOL_ID"] }, - "serverUrl": "https://your-server.com/webhook" + "voice": {"provider": "11labs", "voiceId": "burt"} }' ``` - + + Your server will receive the tool call with `message.call.monitor.controlUrl` and use it to execute the transfer via Live Call Control. + ```typescript import express from 'express'; - import crypto from 'crypto'; + import axios from 'axios'; const app = express(); app.use(express.json()); - function verifyWebhookSignature(payload: string, signature: string) { - const expectedSignature = crypto - .createHmac('sha256', process.env.WEBHOOK_SECRET!) - .update(payload) - .digest('hex'); - return crypto.timingSafeEqual( - Buffer.from(signature), - Buffer.from(expectedSignature) - ); - } - - app.post('/webhook', (req, res) => { + app.post('/webhook', async (req, res) => { try { - const signature = req.headers['x-vapi-signature'] as string; - const payload = JSON.stringify(req.body); - - if (!verifyWebhookSignature(payload, signature)) { - return res.status(401).json({ error: 'Invalid signature' }); - } + const { message } = req.body; - const request = req.body; + // Extract control URL from the call monitor + const controlUrl = message?.call?.monitor?.controlUrl; + + // Extract tool call from toolWithToolCallList + const toolWithToolCall = message?.toolWithToolCallList?.[0]; + const toolCall = toolWithToolCall?.toolCall; - if (request.type !== 'transfer-destination-request') { - return res.status(200).json({ received: true }); + if (!controlUrl || !toolCall) { + return res.status(400).json({ error: 'Missing required data' }); } - // Simple routing logic - customize for your needs - const { functionCall, customer } = request; - const urgency = functionCall.parameters?.urgency || 'medium'; + // Extract parameters from the tool call + const { department, reason, urgency } = toolCall.function.arguments; + // Execute business logic (optional) + console.log(`Transfer request: ${department} - ${reason} (${urgency})`); + + // Determine destination based on department let destination; - if (urgency === 'critical') { + if (department === 'support') { + destination = { + type: "number", + number: "+1234567890" + }; + } else if (department === 'sales') { destination = { type: "number", - number: "+1-555-EMERGENCY", - message: "Connecting you to our emergency team." + number: "+1987654321" }; } else { destination = { - type: "number", - number: "+1-555-SUPPORT", - message: "Transferring you to our support team." + type: "number", + number: "+1555555555" }; } - res.json({ destination }); - } catch (error) { - console.error('Webhook error:', error); - res.status(500).json({ - error: 'Transfer routing failed. Please try again.' + // Execute transfer via Live Call Control + await axios.post(controlUrl, { + type: "transfer", + destination: destination, + content: `Transferring you to ${department} now.` + }, { + headers: { 'Content-Type': 'application/json' } }); + + // Respond to Vapi (optional acknowledgment) + res.json({ success: true }); + + } catch (error) { + console.error('Transfer error:', error); + res.status(500).json({ error: 'Transfer failed' }); } }); @@ -308,70 +383,96 @@ Dynamic transfers operate by leaving the destination unspecified initially, then ```python import os - import hmac - import hashlib + import httpx from fastapi import FastAPI, HTTPException, Request app = FastAPI() - def verify_webhook_signature(payload: bytes, signature: str) -> bool: - webhook_secret = os.getenv('WEBHOOK_SECRET', '').encode() - expected_signature = hmac.new( - webhook_secret, payload, hashlib.sha256 - ).hexdigest() - return hmac.compare_digest(signature, expected_signature) - @app.post("/webhook") async def handle_webhook(request: Request): try: - body = await request.body() - signature = request.headers.get('x-vapi-signature', '') + body = await request.json() + message = body.get('message', {}) - if not verify_webhook_signature(body, signature): - raise HTTPException(status_code=401, detail="Invalid signature") + # Extract control URL from the call monitor + control_url = message.get('call', {}).get('monitor', {}).get('controlUrl') - request_data = await request.json() + # Extract tool call from toolWithToolCallList + tool_with_tool_call = message.get('toolWithToolCallList', [{}])[0] + tool_call = tool_with_tool_call.get('toolCall', {}) - if request_data.get('type') != 'transfer-destination-request': - return {"received": True} + if not control_url or not tool_call: + raise HTTPException(status_code=400, detail="Missing required data") - # Simple routing logic - customize for your needs - function_call = request_data.get('functionCall', {}) - urgency = function_call.get('parameters', {}).get('urgency', 'medium') + # Extract parameters from the tool call + arguments = tool_call.get('function', {}).get('arguments', {}) + department = arguments.get('department') + reason = arguments.get('reason') + urgency = arguments.get('urgency', 'medium') - if urgency == 'critical': + print(f"Transfer request: {department} - {reason} ({urgency})") + + # Determine destination based on department + if department == 'support': + destination = { + "type": "number", + "number": "+1234567890" + } + elif department == 'sales': destination = { "type": "number", - "number": "+1-555-EMERGENCY", - "message": "Connecting you to our emergency team." + "number": "+1987654321" } else: destination = { "type": "number", - "number": "+1-555-SUPPORT", - "message": "Transferring you to our support team." + "number": "+1555555555" } - return {"destination": destination} + # Execute transfer via Live Call Control + async with httpx.AsyncClient() as client: + await client.post( + control_url, + json={ + "type": "transfer", + "destination": destination, + "content": f"Transferring you to {department} now." + }, + headers={"Content-Type": "application/json"} + ) + + return {"success": True} except Exception as error: - print(f"Webhook error: {error}") - raise HTTPException( - status_code=500, - detail="Transfer routing failed. Please try again." - ) + print(f"Transfer error: {error}") + raise HTTPException(status_code=500, detail="Transfer failed") ``` + + + **SIP transfers:** To transfer to a SIP endpoint, use `"type": "sip"` with `"sipUri"` instead: + + ```json + { + "type": "transfer", + "destination": { + "type": "sip", + "sipUri": "sip:+1234567890@sip.telnyx.com" + }, + "content": "Transferring your call now." + } + ``` + - Create a phone number and assign your assistant - - Call the number and test different transfer scenarios - - Monitor your webhook server logs to see the routing decisions - - Verify transfers are working to the correct destinations + - Call the number and request a transfer to different departments + - Monitor your webhook server logs to see the tool calls and control URL + - Verify transfers are executing to the correct destinations ```typescript @@ -385,7 +486,8 @@ Dynamic transfers operate by leaving the destination unspecified initially, then console.log(`Test call created: ${testCall.id}`); - // Monitor webhook server logs to see transfer requests + // During the call, say "I need to speak with support" + // Monitor webhook server logs to see the transfer execution ``` @@ -405,6 +507,9 @@ Dynamic transfers operate by leaving the destination unspecified initially, then response = requests.post(url, headers=headers, json=data) call = response.json() print(f"Test call created: {call['id']}") + + # During the call, say "I need to speak with support" + # Monitor webhook server logs to see the transfer execution return call ``` @@ -414,26 +519,14 @@ Dynamic transfers operate by leaving the destination unspecified initially, then --- -## Implementation Approaches - -**Assistant-based implementation** uses transfer-type tools with conditions interpreted by the assistant through system prompts. The assistant determines when and where to route calls based on clearly defined tool purposes and routing logic in the prompt. Best for quick setup and simpler routing scenarios. - -**Workflow-based implementation** uses conditional logic based on outputs from any workflow node - tools, API requests, conversation variables, or other data sources. Conditions evaluate node outputs to determine routing paths within visual workflows. Best for complex business logic, structured decision trees, and team-friendly configuration. - -
- -
**Assistant-based routing** Route customers to appropriate support tiers based on conversation analysis and customer data
- -
- -
- **Workflow-based routing** + + **Squad-based routing** Direct tenant calls to the right department with automated verification @@ -465,8 +558,15 @@ Dynamic transfers operate by leaving the destination unspecified initially, then **Security considerations:** Always verify webhook signatures to ensure requests come from Vapi. Never log sensitive customer data, implement proper access controls, and follow privacy regulations like GDPR and CCPA when handling customer information in routing decisions.
+## Troubleshooting + +- **Tool call not received**: Verify your server URL is correctly configured in the custom tool and is publicly accessible. Check your server logs for incoming requests. +- **Transfer not executing**: Make sure that you are sending a valid destination object (type number or sip). See API reference [here](https://docs.vapi.ai/api-reference/tools/create#request.body.TransferCallTool.destinations). +- **Invalid destination format**: For phone numbers, use `"type": "number"` with E.164 format. For SIP, use `"type": "sip"` with a valid SIP URI. +- **Transfer fails silently**: Check your server logs for errors in the axios/httpx request. + ## Related Documentation -* **[Call Forwarding](/call-forwarding)** - Static transfer options and transfer plans +* **[Transfer call tool](/tools/transfer-call)** - Static transfer options and transfer plans * **[Webhooks](/server-url)** - Webhook security and event handling patterns * **[Custom Tools](/tools/custom-tools)** - Build custom tools for advanced routing logic diff --git a/fern/calls/call-ended-reason.mdx b/fern/calls/call-ended-reason.mdx index d9f9b081f..69acb687e 100644 --- a/fern/calls/call-ended-reason.mdx +++ b/fern/calls/call-ended-reason.mdx @@ -4,88 +4,219 @@ subtitle: All possible call ended reason codes and what they mean. slug: calls/call-ended-reason --- -This guide will discuss all possible `endedReason` codes for a call. +Every call in Vapi ends with an `endedReason` code that tells you exactly why it ended. You can find this value in the **"Ended Reason"** column of your [call logs](https://dashboard.vapi.ai/calls), or under the `endedReason` field on the [Call object](/api-reference/calls/get). For the full list of possible `endedReason` values, see the [API reference](/api-reference/calls/list#response.body.endedReason). -You can find these under the **"Ended Reason"** section of your [call logs](https://dashboard.vapi.ai/calls) (or under the `endedReason` field on the [Call Object](/api-reference/calls/get-call)). - -#### Assistant-Related - -- `assistant-ended-call`: The assistant intentionally ended the call based on the user's response. -- `assistant-ended-call-after-message-spoken`: The assistant intentionally ended the call after speaking a pre-defined message. -- `assistant-ended-call-with-hangup-task`: The assistant ended the call using a hangup task. -- `assistant-error`: This general error occurs within the assistant's logic or processing due to bugs, misconfigurations, or unexpected inputs. -- `assistant-forwarded-call`: The assistant successfully transferred the call to another number or service. -- `assistant-join-timed-out`: The assistant failed to join the call within the expected timeframe. -- `assistant-not-found`: The specified assistant cannot be located or accessed, possibly due to an incorrect assistant ID or configuration issue. -- `assistant-not-valid`: The assistant ID provided is not valid or recognized by the system. -- `assistant-not-provided`: No assistant ID was specified in the request, causing the system to fail. -- `assistant-request-failed`: The request to the assistant failed to complete successfully. -- `assistant-request-returned-error`: Communicating with the assistant resulted in an error, possibly due to network issues or problems with the assistant itself. -- `assistant-request-returned-forwarding-phone-number`: The assistant triggered a call forwarding action, ending the current call. -- `assistant-request-returned-invalid-assistant`: The assistant returned an invalid response or failed to fulfill the request properly. -- `assistant-request-returned-no-assistant`: The assistant didn't provide any response or action to the request. -- `assistant-request-returned-unspeakable-error`: The assistant returned an error that cannot be spoken to the user. -- `assistant-said-end-call-phrase`: The assistant recognized a phrase or keyword triggering call termination. - -#### Pipeline and LLM - -These relate to issues within the AI processing pipeline or the Large Language Models (LLMs) used for understanding and generating text: - -- `call.in-progress.error-vapifault-*`: Various error codes indicate specific failures within the processing pipeline, such as function execution, LLM responses, or external service integration. Examples include OpenAI, Azure OpenAI, Together AI, and several other LLMs or voice providers. -- `call.in-progress.error-providerfault-*`: Similar to `call.in-progress.error-vapifault-*`. However, these error codes are surfaced when Vapi receives an error that has occured on the provider's side. Examples include internal server errors, or service unavailability. -- `pipeline-error-*`: Similar to `call.in-progress.error-vapifault-*`. However, these error codes are surfaced when you are using your own provider keys. -- `pipeline-no-available-llm-model`: No suitable LLM was available to process the request. Previously `pipeline-no-available-model`. -- `call.in-progress.error-pipeline-no-available-llm-model`: No suitable LLM was available to process the request during the call. - -#### Phone Calls and Connectivity - -- `customer-busy`: The customer's line was busy. -- `customer-ended-call`: The customer (end human user) ended the call for both inbound and outbound calls. -- `customer-did-not-answer`: The customer didn't answer the call. If you're looking to build a use case where you need the bot to talk to automated IVRs, set `assistant.voicemailDetectionEnabled=false`. -- `customer-did-not-give-microphone-permission`: The user didn't grant the necessary microphone access for the call. -- `call.in-progress.error-assistant-did-not-receive-customer-audio`: Similar to `customer-did-not-give-microphone-permission`, but more generalized to situations where no customer audio was received. -- `phone-call-provider-closed-websocket`: The connection with the call provider was unexpectedly closed. -- `phone-call-provider-bypass-enabled-but-no-call-received`: The phone call provider bypass was enabled but no call was received. -- `twilio-failed-to-connect-call`: The Twilio service, responsible for managing calls, failed to establish a connection. -- `twilio-reported-customer-misdialed`: Twilio reported that the customer dialed an invalid or incomplete number. -- `vonage-disconnected`: The call was disconnected by Vonage, another call management service. -- `vonage-failed-to-connect-call`: Vonage failed to establish the call connection. -- `vonage-rejected`: The call was rejected by Vonage due to an issue or configuration problem. -- `vonage-completed`: The call was completed successfully by Vonage. -- `call.in-progress.error-sip-telephony-provider-failed-to-connect-call`: The SIP telephony provider failed to establish the call connection. - -#### Call Start Errors - -- `call-start-error-neither-assistant-nor-server-set`: Neither an assistant nor server was configured for the call. -- `call.start.error-get-org`: Error retrieving organization information during call start. -- `call.start.error-get-subscription`: Error retrieving subscription information during call start. -- `call.start.error-get-assistant`: Error retrieving assistant information during call start. -- `call.start.error-get-phone-number`: Error retrieving phone number information during call start. -- `call.start.error-get-customer`: Error retrieving customer information during call start. -- `call.start.error-get-resources-validation`: Error validating resources during call start. -- `call.start.error-vapi-number-international`: Error with international Vapi number during call start. -- `call.start.error-vapi-number-outbound-daily-limit`: Outbound daily limit reached for Vapi number. -- `call.start.error-get-transport`: Error retrieving transport information during call start. - -#### Call Forwarding and Hooks - -- `call.forwarding.operator-busy`: The operator was busy during call forwarding. -- `call.ringing.hook-executed-say`: A say hook was executed during the ringing phase. -- `call.ringing.hook-executed-transfer`: A transfer hook was executed during the ringing phase. - -#### Other Reasons - -- `database-error`: A database error occurred during the call. -- `exceeded-max-duration`: The call reached its maximum allowed duration and was automatically terminated. -- `manually-canceled`: The call was manually canceled. -- `silence-timed-out`: The call was ended due to prolonged silence, indicating inactivity. -- `voicemail`: The call was diverted to voicemail. -- `worker-shutdown`: The worker handling the call was shut down. - -#### Unknown - -- `unknown-error`: An unexpected error occurred, and the cause is unknown. For this, please [contact support](/support) with your `call_id` and account email address, & we will investigate. +## Quick diagnosis + +Start here if a call failed and you want to quickly understand what happened: + +| The caller experienced... | Look for these errors | Likely cause | +|---|---|---| +| Phone never rang | `call.start.error-*`, `assistant-not-found`, `*-transport-never-connected` | Account/billing issue, bad configuration, or Vapi infrastructure error | +| Phone rang but no answer | `customer-did-not-answer`, `customer-busy`, SIP 408/480 | Normal behavior — callee was unavailable | +| Call dropped mid-conversation | `*-worker-died`, `phone-call-provider-closed-websocket`, `worker-shutdown` | Network issue or Vapi infrastructure error (usually transient) | +| Assistant went silent or unresponsive | `*-llm-failed`, `*-voice-failed`, `*-transcriber-failed`, `*-429-*`, `*-500-*` | Provider outage or credential/quota issue — configure fallback providers for the 3 core services (TTS, LLM, STT) | +| Call worked normally, then ended | `assistant-ended-call`, `customer-ended-call`, `silence-timed-out`, `exceeded-max-duration` | Expected behavior — adjust timeout settings if calls end too early | +| Transfer failed | `*-transfer-failed`, `*-warm-transfer-*`, SIP 403/503 | Bad transfer destination or SIP configuration | + +For a detailed symptom-based walkthrough, see [Troubleshoot call errors](/calls/troubleshoot-call-errors). + +## Understanding error prefixes + +Many error codes include a prefix that indicates who is responsible for the failure: + +| Prefix | Meaning | What to do | +|---|---|---| +| `call.in-progress.error-vapifault-*` | Vapi infrastructure or platform credential failure. You are typically **not charged** for these calls. | Contact [Vapi support](/support) if persistent. | +| `call.in-progress.error-providerfault-*` | A third-party provider (OpenAI, Deepgram, etc.) returned a server error. Outside Vapi's control. | Check the provider's status page. Consider configuring a fallback provider. | +| `pipeline-error-*` | Legacy error format. When using your own provider keys (BYOK), these typically indicate credential or quota issues on your account with that provider. When using Vapi's platform keys, treat as a `vapifault`. | Verify your API key, billing status, and quota with the provider. | + +## Call start errors + +These occur before the call connects, during resource setup. + +### Account and billing + +- `call.start.error-subscription-frozen` — Your subscription is frozen due to a failed payment. Update your payment method in the [dashboard](https://dashboard.vapi.ai/). +- `call.start.error-subscription-insufficient-credits` — Not enough credits to start the call. Add credits or enable auto-reload. +- `call.start.error-subscription-wallet-does-not-exist` — No billing wallet found for the subscription. Contact [support](/support). +- `call.start.error-subscription-upgrade-failed` — An automatic subscription upgrade attempt failed. +- `call.start.error-subscription-concurrency-limit-reached` — You've hit the maximum number of simultaneous calls for your plan. Upgrade your plan or wait for an active call to end. +- `call.start.error-fraud-check-failed` — The call was blocked by Vapi's fraud detection system. +- `call.start.error-enterprise-feature-not-available-recording-consent` — Recording consent requires an enterprise plan. + +### Resource resolution + +- `call-start-error-neither-assistant-nor-server-set` — Neither an assistant nor a server URL was configured for the call. +- `call.start.error-get-org` — Error retrieving your organization during call start. Verify your API key. +- `call.start.error-get-subscription` — Error retrieving subscription information during call start. +- `call.start.error-get-assistant` — Error retrieving the assistant. Verify the assistant ID exists. +- `call.start.error-get-phone-number` — Error retrieving the phone number. Verify the number is imported and active. +- `call.start.error-get-customer` — Error retrieving customer information. +- `call.start.error-get-resources-validation` — The assistant, tools, or other resources failed validation. +- `call.start.error-get-transport` — Error setting up the call transport (Twilio, Vonage, etc.). +- `call.start.error-vapifault-database-error` — Internal database error during call setup. Retry or contact [support](/support). + +### Phone number limits + +- `call.start.error-vapi-number-international` — International calling is not supported on this Vapi number. +- `call.start.error-vapi-number-outbound-daily-limit` — The daily outbound call limit for this Vapi number has been reached. + +### Assistant resolution (via server URL) + +- `assistant-not-found` — The specified assistant ID does not exist. +- `assistant-not-valid` — The assistant configuration is invalid. +- `assistant-request-failed` — The request to your server URL to fetch an assistant failed. +- `assistant-request-returned-error` — Your server URL returned an error response. +- `assistant-request-returned-unspeakable-error` — Your server URL returned an error that cannot be spoken to the user. +- `assistant-request-returned-invalid-assistant` — Your server URL returned a response that is not a valid assistant configuration. +- `assistant-request-returned-no-assistant` — Your server URL returned an empty response with no assistant. +- `assistant-request-returned-forwarding-phone-number` — Your server URL returned a phone number for forwarding instead of an assistant. +- `scheduled-call-deleted` — A scheduled call was deleted before it could execute. + +## Assistant actions + +These indicate the assistant intentionally ended the call — not errors. + +- `assistant-ended-call` — The assistant ended the call (via an end-call tool or function). +- `assistant-ended-call-after-message-spoken` — The assistant ended the call after speaking its final message. +- `assistant-ended-call-with-hangup-task` — The assistant ended the call using a hangup task. +- `assistant-said-end-call-phrase` — The assistant said a phrase configured to trigger call termination. +- `assistant-forwarded-call` — The assistant transferred the call to another number or service. +- `assistant-join-timed-out` — The assistant failed to join the call within the expected timeframe. + +## Customer actions + +- `customer-ended-call` — The customer hung up. +- `customer-busy` — The customer's line was busy (outbound calls). +- `customer-did-not-answer` — The customer did not answer (outbound calls). +- `customer-did-not-give-microphone-permission` — The user denied microphone access (web calls). +- `call.in-progress.error-assistant-did-not-receive-customer-audio` — No audio was received from the customer. This can indicate a network issue, mic problem, or the customer disconnected silently. +- `customer-ended-call-before-warm-transfer` — The customer hung up before a warm transfer completed. +- `customer-ended-call-after-warm-transfer-attempt` — The customer hung up after a warm transfer was attempted. +- `customer-ended-call-during-transfer` — The customer hung up during a transfer. + +## Timeouts + +- `exceeded-max-duration` — The call reached `maxDurationSeconds` and was automatically terminated. +- `silence-timed-out` — No speech was detected for the configured silence timeout duration. + +## Pipeline errors: LLM + +Each LLM provider has error codes that follow a consistent pattern. The status code in the error name tells you what went wrong: + +| Status code in error | Meaning | What to do | +|---|---|---| +| `400-bad-request-validation-failed` | Invalid request (bad model name, malformed messages, etc.) | Check your assistant's model configuration. | +| `401-unauthorized` / `401-incorrect-api-key` | Invalid API key. | Verify your API key for this provider. | +| `403-model-access-denied` | Your API key doesn't have access to the requested model. | Check model permissions in your provider account. | +| `429-exceeded-quota` / `429-rate-limit-reached` | Rate limit or quota exceeded. | Upgrade your plan with the provider or reduce call volume. | +| `500-server-error` | Provider internal server error. | Retry. Check the provider's status page. | +| `503-server-overloaded-error` | Provider temporarily overloaded. | Retry after a brief wait. | +| `llm-failed` | Generic LLM failure. | Check call logs for details. | + +**Supported providers:** OpenAI, Azure OpenAI, Anthropic, Anthropic Bedrock, Anthropic Vertex, Google, Groq, xAI, Mistral, Together AI, Perplexity AI, DeepInfra, DeepSeek, Cerebras, Inflection AI, Anyscale, OpenRouter, Runpod, Baseten, Custom LLM. + +Additional model errors: + +- `pipeline-no-available-llm-model` / `call.in-progress.error-pipeline-no-available-llm-model` — No suitable LLM model was available. Check your model configuration. +- `call.in-progress.error-pipeline-ws-model-connection-failed` — Failed to connect to a custom LLM WebSocket endpoint. + +## Pipeline errors: voice (TTS) + +Each voice provider has specific error codes. Common patterns: + +- `*-voice-failed` — Generic voice synthesis failure for that provider. +- `*-voice-not-found` / `*-invalid-voice` — The configured voice ID does not exist or is invalid. +- `*-quota-exceeded` / `*-out-of-credits` — Voice provider credits exhausted. +- `*-unauthorized-access` / `*-invalid-api-key` — Voice provider credential issue. +- `*-socket-hang-up` / `*-500-server-error` / `*-503-server-error` — Voice provider infrastructure issue. + +**Supported providers:** ElevenLabs, Cartesia, Deepgram, PlayHT, Azure, OpenAI, Rime AI, Smallest AI, Neuphonic, Hume, Sesame, Inworld, Minimax, WellSaid, Custom Voice. + +## Pipeline errors: transcriber (STT) + +Common transcriber error patterns: + +- `*-transcriber-failed` — Generic transcriber failure. +- `*-returning-400-*` — Bad request (invalid model/language combination, invalid config, etc.). +- `*-returning-401-*` — Invalid transcriber credentials. +- `*-returning-403-*` — Model access denied on the transcriber. +- `*-returning-500-*` / `*-returning-502-*` — Transcriber provider server error. + +**Supported providers:** Deepgram, AssemblyAI, Gladia, Speechmatics, Talkscriber, Azure Speech, Google, OpenAI, Soniox, ElevenLabs, Custom Transcriber. + +## Transfer errors + +- `call.in-progress.error-transfer-failed` — A call transfer attempt failed. +- `call.in-progress.error-warm-transfer-max-duration` — The warm transfer exceeded its maximum duration. +- `call.in-progress.error-warm-transfer-assistant-cancelled` — The transfer assistant cancelled the warm transfer. +- `call.in-progress.error-warm-transfer-silence-timeout` — Silence timeout during a warm transfer. +- `call.in-progress.error-warm-transfer-microphone-timeout` — Microphone timeout during a warm transfer. + +For step-by-step transfer debugging, see [Debug forwarding drops](/phone-calling/in-call-control/transfer-calls/debug-forwarding-drops). + +## Transport and connectivity + +- `phone-call-provider-closed-websocket` — The call provider's WebSocket connection closed unexpectedly. The caller experiences an abrupt call drop. +- `phone-call-provider-bypass-enabled-but-no-call-received` — Phone call provider bypass was enabled but no call arrived. +- `call.in-progress.error-vapifault-transport-never-connected` — The transport never connected. Vapi infrastructure issue. +- `call.in-progress.error-providerfault-transport-never-connected` — The transport provider failed to connect. Provider-side issue. +- `call.in-progress.error-vapifault-transport-connected-but-call-not-active` — Transport connected but the call was no longer active. +- `call.in-progress.error-vapifault-call-started-but-connection-to-transport-missing` — Call started but the transport connection was lost. +- `call.in-progress.error-vapifault-worker-not-available` — No call worker was available to process the call. +- `call.in-progress.error-vapifault-worker-died` — The call worker process crashed during the call. +- `call.in-progress.error-vapifault-chat-pipeline-failed-to-start` — The chat pipeline failed to initialize. + +### Twilio + +- `twilio-failed-to-connect-call` — Twilio failed to establish the call. +- `twilio-reported-customer-misdialed` — Twilio reported the customer dialed an invalid number. +- `call.in-progress.twilio-completed-call` — Twilio reported the call as completed on their side. + +### Vonage + +- `vonage-disconnected` — Call disconnected by Vonage. +- `vonage-failed-to-connect-call` — Vonage failed to connect the call. +- `vonage-rejected` — Call rejected by Vonage. +- `vonage-completed` — Call completed by Vonage. + +### SIP + +- `call.in-progress.error-sip-inbound-call-failed-to-connect` — Inbound SIP call failed to connect. +- `call.in-progress.error-sip-outbound-call-failed-to-connect` — Outbound SIP call failed to connect. +- `call.in-progress.error-providerfault-outbound-sip-403-forbidden` — SIP 403: call forbidden by the SIP provider. +- `call.in-progress.error-providerfault-outbound-sip-407-proxy-authentication-required` — SIP 407: proxy authentication required. +- `call.in-progress.error-providerfault-outbound-sip-408-request-timeout` — SIP 408: request timed out. +- `call.in-progress.error-providerfault-outbound-sip-480-temporarily-unavailable` — SIP 480: destination temporarily unavailable. +- `call.in-progress.error-providerfault-outbound-sip-503-service-unavailable` — SIP 503: service unavailable. +- `call.ringing.error-sip-inbound-call-failed-to-connect` — SIP inbound call failed during ringing. +- `call.ringing.sip-inbound-caller-hungup-before-call-connect` — SIP caller hung up before the call connected. +- `call.in-progress.sip-completed-call` — SIP provider reported the call as completed. + +For SIP trunk setup issues, see [Troubleshoot SIP trunk credential errors](/advanced/sip/troubleshoot-sip-trunk-credential-errors). + +## Call hooks + +- `call.ringing.hook-executed-say` — A say hook executed during ringing ended the call. +- `call.ringing.hook-executed-transfer` — A transfer hook executed during ringing ended the call. +- `call.ending.hook-executed-say` — A say hook executed during the ending phase. +- `call.ending.hook-executed-transfer` — A transfer hook executed during the ending phase. +- `call.forwarding.operator-busy` — The operator was busy during call forwarding. + +## Other reasons + +- `manually-canceled` — The call was manually canceled via the API or dashboard. +- `voicemail` — The call was diverted to or detected as voicemail. +- `worker-shutdown` — The call worker was shut down (e.g., during a deployment). The call should be retried automatically. +- `call-deleted` — The call record was deleted. + +## Next steps + +- **[Troubleshoot call errors](/calls/troubleshoot-call-errors):** Step-by-step diagnosis guide organized by what the caller experienced. +- **[Debugging voice agents](/debugging):** General debugging workflow using dashboard tools, logs, and test suites. +- **[How to report issues](/issue-reporting):** Include your `call_id` and account email when contacting support. diff --git a/fern/calls/call-features.mdx b/fern/calls/call-features.mdx index 7bc202d07..c24e6dc5e 100644 --- a/fern/calls/call-features.mdx +++ b/fern/calls/call-features.mdx @@ -129,6 +129,46 @@ curl -X POST 'https://aws-us-west-2-production1-phone-call-websocket.vapi.ai/742 }' ``` +You can also transfer to a SIP URI: + +```bash +curl -X POST 'https://aws-us-west-2-production1-phone-call-websocket.vapi.ai/7420f27a-30fd-4f49-a995-5549ae7cc00d/control' +-H 'content-type: application/json' +--data-raw '{ + "type": "transfer", + "destination": { + "type": "sip", + "sipUri": "sip:+transferPhoneNumber@sip.telnyx.com" + }, + "content": "Testing transfer call." +}' +``` + +### 6. Handoff Call +Handoff the call to a different assistant. + +```bash +curl -X POST 'https://aws-us-west-2-production1-phone-call-websocket.vapi.ai/7420f27a-30fd-4f49-a995-5549ae7cc00d/control' +-H 'content-type: application/json' +--data-raw '{ + "type": "handoff", + "destination": { + "type": "assistant", + "contextEngineeringPlan": "none", + "assistant": { + "name": "new_assistant", + "voice": { + "provider": "vapi", + "version": 2, + "voiceId": "Elliot" + }, + } + }, + "content": "Handing off your call now" +}' +``` + + ## Call Listen Feature The `listenUrl` allows you to connect to a WebSocket and stream the audio data in real-time. You can either process the audio directly or save the binary data to analyze or replay later. diff --git a/fern/calls/call-outbound.mdx b/fern/calls/call-outbound.mdx index da2b2154a..beec06add 100644 --- a/fern/calls/call-outbound.mdx +++ b/fern/calls/call-outbound.mdx @@ -12,7 +12,7 @@ Vapi's outbound calling API lets you programmatically initiate single or batch c - **Vapi Account**: Access to the Vapi Dashboard for configuration. - **Configured Assistant**: Either a saved assistant or a transient assistant. -- **Phone Number**: Either an imported phone number from one of the supported providers or a free Vapi number. (Note: You cannot make international calls with a free Vapi number). +- **Phone Number**: Either an imported phone number from one of the supported providers. (Note: You cannot make outbound or international calls with a free Vapi number). - **Customer's Phone Number**: The phone number that you want to call. ## Outbound Calls @@ -20,7 +20,7 @@ Vapi's outbound calling API lets you programmatically initiate single or batch c You can place an outbound call from one of your phone numbers using the [`/call`](/api-reference/calls/create-phone-call) endpoint. 1. **Specify an Assistant:** you must specify either a transient assistant in the `assistant` field or reuse a saved assistant in the `assistantId` field. -2. **Get a Phone Number:** provide the `phoneNumberId` of the imported number or free Vapi number you wish to call from. +2. **Get a Phone Number:** provide the `phoneNumberId` of the imported number you wish to call from. 3. **Provide a Destination:** Finally, pass the customer's phone number or SIP URI in [`customer`](/api-reference/calls/create#request.body.customer). Provide your authorization token and now we're ready to issue the API call! @@ -35,6 +35,25 @@ Provide your authorization token and now we're ready to issue the API call! } ``` +## Outbound calls with versioning + +By default, an outbound call placed with a saved `assistantId` uses the assistant's **current published version**. + +To pin the call to a specific published version instead, add `assistantVersion` (a version label like `v3`) alongside the `assistantId`. Version pinning works only with a saved `assistantId`; it is rejected with a transient `assistant`. + +```jsx +{ + "assistantId": "assistant-id", + "assistantVersion": "v3", + "phoneNumberId": "phone-number-id", + "customer": { + "number": "+11231231234" + } +} +``` + +For the full versioning model, including publishing, restoring, and pinning tool versions, see [Versioning](/assistants/versioning). + ## Scheduling Outbound Calls To schedule a call for the future, use the [`schedulePlan`](/api-reference/calls/create#request.body.schedulePlan) parameter and pass a future ISO date-time string to `earliestAt`. This will be the earliest time Vapi will attempt to trigger the outbound call. You may also provider `latestAt`, which will be the latest time Vapi will attempt to trigger the call. diff --git a/fern/calls/call-queue-management.mdx b/fern/calls/call-queue-management.mdx new file mode 100644 index 000000000..6eb03a5a3 --- /dev/null +++ b/fern/calls/call-queue-management.mdx @@ -0,0 +1,711 @@ +--- +title: Call queue management with Twilio +subtitle: Handle high-volume calls with Twilio queues when hitting Vapi concurrency limits +slug: calls/call-queue-management +description: Build a call queue system using Twilio to handle large volumes of calls while respecting Vapi concurrency limits, ensuring no calls are dropped. +--- + +## Overview + +When your application receives more simultaneous calls than your Vapi concurrency limit allows, calls can be rejected. A call queue system using Twilio queues solves this by holding excess calls in a queue and processing them as capacity becomes available. + +**In this guide, you'll learn to:** +- Set up Twilio call queues for high-volume scenarios +- Implement concurrency tracking to respect Vapi limits +- Build a queue processing system with JavaScript +- Handle call dequeuing and Vapi integration seamlessly + + +This approach is ideal for call centers, customer support lines, or any application expecting call volumes that exceed your Vapi concurrency limit. + + +## Prerequisites + +Before implementing call queue management, ensure you have: + +- **Vapi Account**: Access to the [Vapi Dashboard](https://dashboard.vapi.ai/) with a [Vapi API key](/security-and-privacy/api-keys) +- **Twilio Account**: Active Twilio account with Account SID and Auth Token +- **Twilio CLI**: Install from [twil.io/cli](https://twil.io/cli) for queue management +- **Phone Number**: Twilio phone number configured for incoming calls +- **Assistant**: Configured Vapi assistant ID for handling calls +- **Server Environment**: Node.js server capable of receiving webhooks +- **Redis Instance**: Redis server for persistent state management (local, cloud, or serverless-compatible) + + +You'll need to know your Vapi account's concurrency limit. Check your plan details in the [Vapi Dashboard](https://dashboard.vapi.ai/settings/billing) under billing settings. + + + +For production deployments, especially in serverless environments, Redis ensures your call counters persist across server restarts and function invocations. + + +## How it works + +The queue management system operates in three phases: + + + + Incoming calls are automatically placed in a Twilio queue when received + + + Server monitors active Vapi calls against your concurrency limit + + + When capacity is available, calls are dequeued and connected to Vapi + + + +**Call Flow:** + +1. **Incoming call** → Twilio receives call and executes webhook +2. **Queue placement** → Call is placed in Twilio queue with hold music +3. **Automatic processing** → Server processes queue immediately when capacity changes +4. **Capacity check** → Server verifies if Vapi concurrency limit allows new calls using Redis +5. **Dequeue & connect** → Available calls are dequeued and connected to Vapi assistants +6. **Persistent tracking** → Redis tracks active calls across server restarts and serverless invocations + +--- + +## Implementation Guide + + + + First, create a Twilio queue using the Twilio CLI to hold incoming calls. + + ```bash + twilio api:core:queues:create \ + --friendly-name customer-support + ``` + + **Expected Response:** + ```json + { + "account_sid": "ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "average_wait_time": 0, + "current_size": 0, + "date_created": "2024-01-15T18:39:09.000Z", + "date_updated": "2024-01-15T18:39:09.000Z", + "friendly_name": "customer-support", + "max_size": 100, + "sid": "QUaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "uri": "/2010-04-01/Accounts/ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Queues/QUaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.json" + } + ``` + + + Save the queue `sid` (e.g., `QUaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`) - you'll need this for queue operations. + + + + + Configure your Twilio phone number to send incoming calls to your queue endpoint. + + 1. Go to [Twilio Console > Phone Numbers](https://console.twilio.com/us1/develop/phone-numbers/manage/incoming) + 2. Select your phone number + 3. Set **A call comes in** webhook to: `https://your-server.com/incoming` + 4. Set HTTP method to `POST` + 5. Save configuration + + + + Configure Redis for persistent call counter storage. Choose the option that best fits your deployment: + + + + **Install Redis locally:** + ```bash + # macOS (using Homebrew) + brew install redis + brew services start redis + + # Ubuntu/Debian + sudo apt update + sudo apt install redis-server + sudo systemctl start redis-server + + # Docker + docker run -d -p 6379:6379 redis:alpine + ``` + + **Test connection:** + ```bash + redis-cli ping + # Should return: PONG + ``` + + + + **Popular Redis cloud providers:** + + - **[Redis Cloud](https://redis.com/redis-enterprise-cloud/)**: Free tier available + - **[AWS ElastiCache](https://aws.amazon.com/elasticache/)**: Managed Redis on AWS + - **[Google Cloud Memorystore](https://cloud.google.com/memorystore)**: Managed Redis on GCP + - **[Azure Cache for Redis](https://azure.microsoft.com/services/cache/)**: Managed Redis on Azure + + Get your connection URL from your provider's dashboard. + + + + **[Upstash Redis](https://upstash.com/)** is optimized for serverless environments: + + 1. Create free account at [console.upstash.com](https://console.upstash.com) + 2. Create new Redis database + 3. Copy the REST URL for serverless compatibility + 4. Use connection pooling for better performance + + **Upstash offers:** + - Pay-per-request pricing + - Global edge locations + - Built-in connection pooling + + + + + + Create your Node.js server with the required dependencies and environment variables. + + **Install Dependencies:** + ```bash + npm install express twilio axios dotenv redis + ``` + + **Environment Variables (.env):** + ```bash + # Vapi Configuration + VAPI_API_KEY=your_vapi_api_key_here + VAPI_PHONE_NUMBER_ID=your_phone_number_id + VAPI_ASSISTANT_ID=your_assistant_id + + # Twilio Configuration + TWILIO_ACCOUNT_SID=your_twilio_account_sid + TWILIO_AUTH_TOKEN=your_twilio_auth_token + TWILIO_QUEUE_SID=QUaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + + # Redis Configuration (for persistent state) + REDIS_URL=redis://localhost:6379 + # For Redis Cloud: REDIS_URL=rediss://username:password@host:port + # For Upstash (serverless): REDIS_URL=rediss://default:password@host:port + + # Server Configuration + PORT=3000 + MAX_CONCURRENCY=5 + ``` + + + + Create the main server file with queue handling, concurrency tracking, and Vapi integration. + + ```javascript title="server.js" + const express = require('express'); + const twilio = require('twilio'); + const axios = require('axios'); + const redis = require('redis'); + require('dotenv').config(); + + const app = express(); + const twilioClient = twilio(process.env.TWILIO_ACCOUNT_SID, process.env.TWILIO_AUTH_TOKEN); + + // Redis client for persistent state management + const redisClient = redis.createClient({ + url: process.env.REDIS_URL || 'redis://localhost:6379' + }); + + const MAX_CONCURRENCY = parseInt(process.env.MAX_CONCURRENCY) || 5; + const REDIS_KEYS = { + ACTIVE_CALLS: 'vapi:queue:active_calls', + CALLS_IN_QUEUE: 'vapi:queue:calls_in_queue' + }; + + // Middleware + app.use(express.json()); + app.use(express.urlencoded({ extended: true })); + + // Initialize Redis connection + async function initializeRedis() { + try { + await redisClient.connect(); + console.log('Connected to Redis'); + + // Initialize counters if they don't exist + const activeCalls = await redisClient.get(REDIS_KEYS.ACTIVE_CALLS); + const callsInQueue = await redisClient.get(REDIS_KEYS.CALLS_IN_QUEUE); + + if (activeCalls === null) { + await redisClient.set(REDIS_KEYS.ACTIVE_CALLS, '0'); + } + if (callsInQueue === null) { + await redisClient.set(REDIS_KEYS.CALLS_IN_QUEUE, '0'); + } + } catch (error) { + console.error('Redis connection failed:', error); + process.exit(1); + } + } + + // Helper functions for Redis operations + async function getActiveCalls() { + const count = await redisClient.get(REDIS_KEYS.ACTIVE_CALLS); + return parseInt(count) || 0; + } + + async function getCallsInQueue() { + const count = await redisClient.get(REDIS_KEYS.CALLS_IN_QUEUE); + return parseInt(count) || 0; + } + + async function incrementActiveCalls() { + return await redisClient.incr(REDIS_KEYS.ACTIVE_CALLS); + } + + async function decrementActiveCalls() { + const current = await getActiveCalls(); + if (current > 0) { + return await redisClient.decr(REDIS_KEYS.ACTIVE_CALLS); + } + return current; + } + + async function incrementCallsInQueue() { + return await redisClient.incr(REDIS_KEYS.CALLS_IN_QUEUE); + } + + async function decrementCallsInQueue() { + const current = await getCallsInQueue(); + if (current > 0) { + return await redisClient.decr(REDIS_KEYS.CALLS_IN_QUEUE); + } + return current; + } + + async function syncCallsInQueue() { + await redisClient.set(REDIS_KEYS.CALLS_IN_QUEUE, '0'); + } + + // Incoming call handler - adds calls to queue + app.post('/incoming', async (req, res) => { + try { + const twiml = ` + + customer-support + `; + + res.set('Content-Type', 'application/xml'); + res.send(twiml); + + // Increment queue counter in Redis + const queueCount = await incrementCallsInQueue(); + console.log(`Call ${req.body.CallSid} added to queue. Calls in queue: ${queueCount}`); + + // Immediately check if we can process this call + setImmediate(() => processQueue()); + + } catch (error) { + console.error('Error handling incoming call:', error); + res.status(500).send('Error processing call'); + } + }); + + async function processQueue() { + try { + const activeCalls = await getActiveCalls(); + const callsInQueue = await getCallsInQueue(); + + // Check if we have capacity for more calls + if (activeCalls >= MAX_CONCURRENCY) { + return; + } + + // Check if there are calls in queue + if (callsInQueue === 0) { + return; + } + + // Get next call from queue + const members = await twilioClient.queues(process.env.TWILIO_QUEUE_SID) + .members + .list({ limit: 1 }); + + if (members.length === 0) { + // No calls in queue - sync our counter + await syncCallsInQueue(); + return; + } + + const member = members[0]; + console.log(`Processing queued call: ${member.callSid}`); + + // Get Vapi TwiML for this call + const twiml = await initiateVapiCall(member.callSid, member.phoneNumber); + + if (twiml) { + // Update call with Vapi TwiML + await twilioClient.calls(member.callSid).update({ twiml }); + + // Update counters in Redis + const newActiveCalls = await incrementActiveCalls(); + const newQueueCount = await decrementCallsInQueue(); + + console.log(`Call connected to Vapi. Active calls: ${newActiveCalls}/${MAX_CONCURRENCY}, Queue: ${newQueueCount}`); + + // Check if we can process more calls immediately + if (newActiveCalls < MAX_CONCURRENCY && newQueueCount > 0) { + setImmediate(() => processQueue()); + } + } else { + console.error(`Failed to get TwiML for call ${member.callSid}`); + } + } catch (error) { + console.error('Error processing queue:', error); + } + } + + // Generate Vapi TwiML for a call + async function initiateVapiCall(callSid, customerNumber) { + const payload = { + phoneNumberId: process.env.VAPI_PHONE_NUMBER_ID, + phoneCallProviderBypassEnabled: true, + customer: { number: customerNumber }, + assistantId: process.env.VAPI_ASSISTANT_ID, + }; + + const headers = { + 'Authorization': `Bearer ${process.env.VAPI_API_KEY}`, + 'Content-Type': 'application/json', + }; + + try { + const response = await axios.post('https://api.vapi.ai/call', payload, { headers }); + + if (response.data && response.data.phoneCallProviderDetails) { + return response.data.phoneCallProviderDetails.twiml; + } else { + throw new Error('Invalid response structure from Vapi'); + } + } catch (error) { + console.error(`Error initiating Vapi call for ${callSid}:`, error.message); + return null; + } + } + + // Webhook for call completion - triggers immediate queue processing + app.post('/call-ended', async (req, res) => { + try { + // Handle Vapi end-of-call-report webhook + const message = req.body.message; + + if (message && message.type === 'end-of-call-report') { + const callId = message.call?.id; + + const newActiveCalls = await decrementActiveCalls(); + console.log(`Vapi call ${callId} ended. Active calls: ${newActiveCalls}/${MAX_CONCURRENCY}`); + + // Immediately process queue when capacity becomes available + setImmediate(() => processQueue()); + } + + res.status(200).send('OK'); + } catch (error) { + console.error('Error handling Vapi webhook:', error); + res.status(500).send('Error'); + } + }); + + // Manual queue processing endpoint (for testing/monitoring) + app.post('/process-queue', async (req, res) => { + try { + await processQueue(); + const activeCalls = await getActiveCalls(); + const callsInQueue = await getCallsInQueue(); + + res.json({ + message: 'Queue processing triggered', + activeCalls, + callsInQueue, + maxConcurrency: MAX_CONCURRENCY + }); + } catch (error) { + console.error('Error in manual queue processing:', error); + res.status(500).json({ error: 'Failed to process queue' }); + } + }); + + // Health check endpoint + app.get('/health', async (req, res) => { + try { + const activeCalls = await getActiveCalls(); + const callsInQueue = await getCallsInQueue(); + + res.json({ + status: 'healthy', + activeCalls, + callsInQueue, + maxConcurrency: MAX_CONCURRENCY, + availableCapacity: MAX_CONCURRENCY - activeCalls, + redis: redisClient.isOpen ? 'connected' : 'disconnected' + }); + } catch (error) { + console.error('Error in health check:', error); + res.status(500).json({ + status: 'error', + error: error.message, + redis: redisClient.isOpen ? 'connected' : 'disconnected' + }); + } + }); + + // Graceful shutdown + process.on('SIGINT', async () => { + console.log('Shutting down gracefully...'); + await redisClient.quit(); + process.exit(0); + }); + + process.on('SIGTERM', async () => { + console.log('Shutting down gracefully...'); + await redisClient.quit(); + process.exit(0); + }); + + // Start server + async function startServer() { + await initializeRedis(); + + const PORT = process.env.PORT || 3000; + app.listen(PORT, () => { + console.log(`Queue management server running on port ${PORT}`); + console.log(`Max concurrency: ${MAX_CONCURRENCY}`); + console.log('Using callback-driven queue processing (no timers)'); + }); + } + + startServer().catch(console.error); + + module.exports = app; + ``` + + + + Configure your Vapi assistant to send end-of-call-report webhooks for accurate concurrency tracking. + + **Assistant Configuration:** + You need to configure your assistant with proper webhook settings to receive call status updates. + + ```javascript title="assistant-configuration.js" + const assistantConfig = { + name: "Queue Management Assistant", + // ... other assistant configuration + + // Configure server URL for webhooks + server: { + url: "https://your-server.com", + timeoutSeconds: 20 + }, + + // Configure which messages to send to your server + serverMessages: ["end-of-call-report", "status-update"] + }; + ``` + + + The webhook will be sent to your server URL with the message type `end-of-call-report` when calls end. This allows you to decrement your active call counter accurately. See the [Assistant API reference](https://docs.vapi.ai/api-reference/assistants/create#request.body.serverMessages) for all available server message types. + + + **Webhook Payload Example:** + Your `/call-ended` endpoint will receive a webhook with this structure: + + ```json title="end-of-call-report-payload.json" + { + "message": { + "type": "end-of-call-report", + "call": { + "id": "73a6da0f-c455-4bb6-bf4a-5f0634871430", + "status": "ended", + "endedReason": "assistant-ended-call" + } + } + } + ``` + + + + Deploy your server and test the complete queue management flow. + + **Start Your Server:** + ```bash + node server.js + ``` + + **Test Scenarios:** + 1. **Single call**: Call your Twilio number - should connect immediately + 2. **Multiple calls**: Make several simultaneous calls to test queuing + 3. **Capacity limit**: Make more calls than your `MAX_CONCURRENCY` setting + 4. **Queue processing**: Check that calls are processed as others end + + **Monitor Queue Status:** + ```bash + # Check server health and capacity + curl https://your-server.com/health + + # Manually trigger queue processing + curl -X POST https://your-server.com/process-queue + ``` + + + +## Callback-Driven Queue Processing + +The system uses **event-driven queue processing** that responds immediately to capacity changes, eliminating the need for timers and preventing memory leaks: + +### How It Works + +- **Event-driven**: Queue processing is triggered by actual events (call start, call end) +- **Redis persistence**: Call counters are stored in Redis, surviving server restarts and serverless deployments +- **Immediate processing**: Uses `setImmediate()` to process queue as soon as capacity becomes available +- **No timers**: Eliminates memory leak risks from long-running intervals +- **Recursive processing**: Automatically processes multiple queued calls when capacity allows + +### Key Improvements + + + + Queue processing happens immediately when calls end or arrive + + + Redis persistence works across serverless function invocations + + + No timers means no memory leaks from long-running processes + + + Counters survive server restarts and deployments + + + +### Architecture Benefits + +- **Event-driven triggers**: Processing occurs on actual state changes, not arbitrary intervals +- **Persistent state**: Redis ensures counters are never lost, even in serverless environments +- **Efficient resource usage**: No CPU cycles wasted on empty queue checks +- **Immediate capacity utilization**: New calls are processed instantly when space becomes available +- **Graceful degradation**: Redis connection failures are handled with proper error logging + +### Processing Triggers + +Queue processing is automatically triggered when: + +1. **New call arrives** → `setImmediate(() => processQueue())` after adding to queue +2. **Call ends** → `setImmediate(() => processQueue())` after decrementing active count +3. **Successful processing** → Recursively processes more calls if capacity and queue allow + + +Redis is required for this implementation. Ensure your Redis instance is properly configured and accessible from your deployment environment. + + +## Troubleshooting + + + + **Common causes:** + - Redis server not running or unreachable + - Incorrect `REDIS_URL` configuration + - Network connectivity issues in production + + **Solutions:** + - Test Redis connection: `redis-cli ping` (should return PONG) + - Verify `REDIS_URL` format matches your provider + - Check firewall rules and security groups + - Monitor Redis logs for authentication errors + + **Health check endpoint shows Redis status:** + ```bash + curl https://your-server.com/health + # Check "redis" field in response + ``` + + + + **Common causes:** + - Server not receiving call-ended webhooks (check webhook URLs) + - Redis counter desync (rare, but possible) + - Vapi API errors (check API key and assistant ID) + + **Solutions:** + - Verify webhook URLs are publicly accessible + - Check Redis counters: `redis-cli get vapi:queue:active_calls` + - Reset counters manually if needed: `redis-cli set vapi:queue:active_calls 0` + - Test Vapi API calls independently + + **Debug Redis state:** + ```bash + # Check current counter values + redis-cli mget vapi:queue:active_calls vapi:queue:calls_in_queue + ``` + + + + **Check these items:** + - `MAX_CONCURRENCY` setting is appropriate for your Vapi plan + - Redis counters are accurate (compare with actual Twilio queue) + - No errors in Vapi TwiML generation + + **Debug steps:** + - Call `/process-queue` endpoint manually + - Check `/health` endpoint for current capacity and Redis status + - Review server logs for Redis connection errors + - Verify queue processing triggers are firing + + + + **Serverless-specific considerations:** + - Use connection pooling for Redis (Upstash recommended) + - Cold starts may cause initial Redis connection delays + - Function timeout limits may interrupt long-running operations + + **Solutions:** + - Configure appropriate function timeout (30+ seconds) + - Use Redis providers optimized for serverless (Upstash) + - Implement connection retry logic + - Monitor function execution logs for timeout errors + + + + **Potential issues:** + - Invalid phone number format (use E.164 format) + - Incorrect Vapi configuration (phone number ID, assistant ID) + - Network timeouts during TwiML generation + - Redis operations timing out + + **Solutions:** + - Validate all phone numbers before processing + - Add timeout handling to API calls and Redis operations + - Implement retry logic for failed Vapi requests + - Monitor Redis response times + + + + **Production considerations:** + - Redis connection pooling for high-traffic scenarios + - Monitor Redis memory usage and eviction policies + - Consider Redis clustering for extreme scale + - Implement circuit breakers for external API calls + + **Monitoring recommendations:** + - Track Redis connection health + - Monitor queue processing latency + - Alert on Redis counter anomalies + - Log all state transitions for debugging + + + +## Next steps + +Now that you have a production-ready call queue system with Redis persistence and callback-driven processing: + +- **[Advanced Call Features](/calls/call-features):** Explore call recording, analysis, and advanced routing options +- **[Monitoring & Analytics](/assistants/call-analysis):** Set up comprehensive call analytics and performance monitoring +- **[Scaling Considerations](/calls/call-concurrency):** Plan, monitor, and scale simultaneous calls for high-volume deployments +- **[Assistant Optimization](/assistants/personalization):** Enhance your assistants with personalization and dynamic variables + + +Consider implementing health checks, metrics collection, and alerting around your Redis counters and queue processing latency for production monitoring. + diff --git a/fern/calls/customer-join-timeout.mdx b/fern/calls/customer-join-timeout.mdx index 486b7b862..4866366fa 100644 --- a/fern/calls/customer-join-timeout.mdx +++ b/fern/calls/customer-join-timeout.mdx @@ -1,5 +1,5 @@ --- -title: Customer join timeout +title: Customer Join Timeout subtitle: Configure web call join timeout for better success rates slug: calls/customer-join-timeout description: Set maximum time for users to join web calls before automatic termination @@ -7,7 +7,7 @@ description: Set maximum time for users to join web calls before automatic termi ## Overview -**Customer join timeout** sets the maximum time users have to join a web call before it's automatically terminated. This parameter helps you optimize call success rates by accounting for real-world connection challenges. +**Customer Join Timeout** sets the maximum time users have to join a web call before it's automatically terminated. This parameter helps you optimize call success rates by accounting for real-world connection challenges. **You'll learn to:** @@ -269,7 +269,7 @@ A user attempting to join needs: Start with 30-60 seconds and adjust based on your success rate analytics. -### "Meeting has ended" message +### Meeting has ended message This message appears when a call ends naturally and is **informational only**—not an error. diff --git a/fern/calls/troubleshoot-call-errors.mdx b/fern/calls/troubleshoot-call-errors.mdx new file mode 100644 index 000000000..bdbba3efd --- /dev/null +++ b/fern/calls/troubleshoot-call-errors.mdx @@ -0,0 +1,273 @@ +--- +title: Troubleshoot call errors +subtitle: Learn to diagnose failed calls based on what the caller experienced. +slug: calls/troubleshoot-call-errors +--- + +## Overview + +When a call fails, the fastest path to a fix is identifying **what the caller experienced**. This guide organizes errors by symptom so you can jump to the right section and resolve the issue. + +**In this guide, you'll learn to:** + +- Match caller-reported symptoms to specific error codes +- Understand the fault classification system (`vapifault` vs `providerfault`) +- Take the right corrective action for each error category + + +This guide explains errors by symptom. For a complete reference of every `endedReason` code, see [Call end reasons](/calls/call-ended-reason). + + +## Start here: identify the symptom + + + + Call failed immediately — no ring on the customer's end + + + Phone rang but was never picked up, or line was busy + + + Caller was talking, then the line went dead abruptly + + + Call connected but the assistant stopped speaking or responding + + + Assistant attempted a transfer but it didn't go through + + + Call worked as expected — someone or something decided it should end + + + +## Phone never rang + +**What the caller experiences:** Nothing. The phone never rings. For web calls, the connection fails immediately. + +**What you see in the dashboard:** The call object is created with status `ended` almost immediately. Duration is zero or near-zero. No transcript. + + + + These are the most common cause of calls failing before they start. + + | Error code | Meaning | Fix | + |---|---|---| + | `call.start.error-subscription-frozen` | Payment failed, subscription frozen | Update payment method in [dashboard](https://dashboard.vapi.ai/) | + | `call.start.error-subscription-insufficient-credits` | Not enough credits | Add credits or enable auto-reload | + | `call.start.error-subscription-concurrency-limit-reached` | Too many simultaneous calls | Upgrade plan or wait for active calls to end | + | `call.start.error-fraud-check-failed` | Blocked by fraud detection | Contact [support](/support) | + | `call.start.error-subscription-wallet-does-not-exist` | No billing wallet found | Contact [support](/support) | + + + + The call couldn't start because something is missing or misconfigured. + + | Error code | Meaning | Fix | + |---|---|---| + | `assistant-not-found` | Assistant ID doesn't exist | Verify the assistant ID in your [dashboard](https://dashboard.vapi.ai/) | + | `assistant-not-valid` | Assistant configuration is invalid | Check required fields on the assistant | + | `call-start-error-neither-assistant-nor-server-set` | No assistant or server URL configured | Set an `assistantId` or `serverUrl` on the call | + | `call.start.error-get-assistant` | Error fetching the assistant | Verify the assistant ID exists and your API key is correct | + | `call.start.error-get-phone-number` | Error fetching the phone number | Verify the number is imported and active | + | `call.start.error-get-resources-validation` | Resources failed validation | Check assistant, tools, and provider configurations | + | `call.start.error-vapi-number-international` | International calling not supported | Use a number that supports international calling | + | `call.start.error-vapi-number-outbound-daily-limit` | Daily outbound limit reached | Wait until the limit resets or use a different number | + + + + If you use a server URL to dynamically provide an assistant, these errors mean your server didn't respond correctly. + + | Error code | Meaning | Fix | + |---|---|---| + | `assistant-request-failed` | Request to your server URL failed | Check your server is running and reachable | + | `assistant-request-returned-error` | Server returned an error response | Check your server logs for the error | + | `assistant-request-returned-invalid-assistant` | Server returned invalid assistant config | Validate the response matches the [assistant schema](/api-reference/assistants/create) | + | `assistant-request-returned-no-assistant` | Server returned an empty response | Ensure your server returns an assistant object | + | `assistant-request-returned-unspeakable-error` | Server returned a non-speakable error | Return a user-friendly error message | + + + + These indicate a problem on Vapi's side. You are typically not charged. + + | Error code | Meaning | Fix | + |---|---|---| + | `call.in-progress.error-vapifault-transport-never-connected` | Transport never connected | Retry. Contact [support](/support) if persistent. | + | `call.in-progress.error-vapifault-worker-not-available` | No call worker available | Retry. This is a transient capacity issue. | + | `call.start.error-vapifault-database-error` | Internal database error | Retry. Contact [support](/support) if persistent. | + | `call.start.error-get-org` | Error fetching organization | Verify your API key is correct | + + + +## Phone rang but nobody answered + +**What the caller experiences:** The phone rings but nobody picks up, or they hear a busy signal. + +**What you see in the dashboard:** Short duration, no transcript, no messages. + +| Error code | Meaning | What to do | +|---|---|---| +| `customer-did-not-answer` | Callee didn't pick up (outbound) | Normal behavior. For IVR use cases, check your voicemail detection settings. | +| `customer-busy` | Line was busy (outbound) | Normal behavior. Retry later. | +| `customer-did-not-give-microphone-permission` | User denied mic access (web calls) | Ensure your UI requests microphone permissions before starting the call. | +| `call.ringing.sip-inbound-caller-hungup-before-call-connect` | SIP caller hung up during ringing | Normal behavior — caller abandoned before pickup. | + + +For outbound calls where you expect to reach an IVR or automated system, configure your [voicemail detection](/calls/voicemail-detection) settings to prevent the call from ending prematurely. + + +## Call dropped mid-conversation + +**What the caller experiences:** They're in the middle of a conversation and the call suddenly cuts off with no warning. The assistant stops speaking and the line goes dead. + +**What you see in the dashboard:** Partial transcript, `messages` array that ends abruptly, non-zero duration. + + + + These are on Vapi's side. You are typically not charged. Most are transient. + + | Error code | Meaning | + |---|---| + | `call.in-progress.error-vapifault-worker-died` | The Vapi process handling the call crashed | + | `call.in-progress.error-vapifault-transport-connected-but-call-not-active` | Transport connected but call was no longer active | + | `call.in-progress.error-vapifault-call-started-but-connection-to-transport-missing` | Transport connection was lost after call started | + | `worker-shutdown` | A Vapi deployment occurred while the call was active | + + **What to do:** These are transient issues. If `worker-died` errors are frequent, contact [support](/support) with the affected `call_id` values. + + + + The telephony provider (Twilio, Vonage, or your SIP trunk) dropped the connection. + + | Error code | Meaning | + |---|---| + | `phone-call-provider-closed-websocket` | Audio WebSocket between Vapi and the provider broke | + | `call.in-progress.error-providerfault-transport-never-connected` | Provider failed to maintain the connection | + | `call.in-progress.twilio-completed-call` | Twilio ended the call from their side | + | `call.in-progress.sip-completed-call` | SIP provider ended the call from their side | + | `vonage-disconnected` | Vonage disconnected the call | + + **What to do:** Check your telephony provider's dashboard for connection logs. For SIP trunks, verify your network connectivity to Vapi's SBC. + + + +## Assistant went silent or unresponsive + +**What the caller experiences:** The call is connected and the line is open, but the assistant either doesn't speak, speaks with extreme delay, responds once then stops, or produces garbled audio. The call eventually times out or the caller hangs up in frustration. + +**What you see in the dashboard:** Partial messages, the `endedReason` points to a specific pipeline component failure. + + +If you've configured **fallback providers**, some transcriber and voice errors will trigger a provider swap instead of ending the call. The caller might hear a brief 1-2 second pause while the fallback initializes, then the conversation continues normally. + + + + + The AI model that generates responses is unreachable or returning errors. + + | Status code pattern | Meaning | Fix | + |---|---|---| + | `*-401-*` / `*-incorrect-api-key` | Invalid API key | Verify your API key for this provider | + | `*-403-*` / `*-model-access-denied` | Model access denied | Check model permissions in your provider account | + | `*-429-*` / `*-exceeded-quota` | Rate limit or quota hit | Upgrade your plan with the provider or reduce volume | + | `*-500-*` / `*-server-error` | Provider internal error | Retry. Check the provider's [status page](https://status.openai.com/) | + | `*-503-*` / `*-server-overloaded` | Provider overloaded | Retry after a brief wait | + | `*-llm-failed` | Generic LLM failure | Check call logs for the detailed error message | + | `pipeline-no-available-llm-model` | No LLM model available | Check your model configuration | + + + + The text-to-speech service can't produce audio. The assistant "thinks" but can't speak. + + | Pattern | Meaning | Fix | + |---|---|---| + | `*-voice-failed` | Generic synthesis failure | Check call logs. May be a transient provider issue. | + | `*-voice-not-found` / `*-invalid-voice` | Voice ID doesn't exist | Verify the voice ID in your provider account | + | `*-quota-exceeded` / `*-out-of-credits` | Voice provider credits exhausted | Add credits to your voice provider account | + | `*-unauthorized-access` / `*-invalid-api-key` | Bad voice provider credentials | Verify your API key for this provider | + | `*-500-*` / `*-503-*` | Provider infrastructure issue | Retry. Check the provider's status page. | + + + + The speech-to-text service can't hear the caller. The assistant can speak but can't understand input. + + | Pattern | Meaning | Fix | + |---|---|---| + | `*-transcriber-failed` | Generic transcriber failure | Check call logs for details | + | `*-returning-400-*` | Bad request (invalid model/language) | Check your transcriber model and language configuration | + | `*-returning-401-*` | Invalid transcriber credentials | Verify your API key for this provider | + | `*-returning-403-*` | Model access denied | Check model permissions in your provider account | + | `*-returning-500-*` / `*-returning-502-*` | Provider server error | Retry. Check the provider's status page. | + + + + +To prevent provider outages from killing your calls, configure fallback providers for your transcriber, voice, and model. Non-fatal errors will trigger a provider swap instead of ending the call. + + +## Transfer failed + +**What the caller experiences:** The assistant says it's transferring the call, but the transfer doesn't go through. The caller may hear silence, get disconnected, or return to the original assistant (for warm transfers). + +**What you see in the dashboard:** Transcript shows the transfer attempt, followed by the error. + + + + | Error code | Meaning | Fix | + |---|---|---| + | `call.in-progress.error-transfer-failed` | Transfer attempt failed | Verify the destination number is correct and reachable | + | `call.in-progress.error-warm-transfer-max-duration` | Warm transfer exceeded max duration | Increase the warm transfer timeout or check if the destination is answering | + | `call.in-progress.error-warm-transfer-assistant-cancelled` | Transfer assistant cancelled | Check the transfer assistant's configuration | + | `call.in-progress.error-warm-transfer-silence-timeout` | Silence during warm transfer | Verify the transfer destination is responding with audio | + | `call.in-progress.error-warm-transfer-microphone-timeout` | Mic timeout during warm transfer | Check audio connectivity to the transfer destination | + + + + | Error code | Meaning | Fix | + |---|---|---| + | `*-outbound-sip-403-forbidden` | SIP provider rejected the call | Check your SIP trunk credentials and allowed destinations | + | `*-outbound-sip-407-proxy-authentication-required` | SIP auth required | Configure proxy authentication on your SIP trunk | + | `*-outbound-sip-408-request-timeout` | SIP request timed out | Check network connectivity to the SIP destination | + | `*-outbound-sip-480-temporarily-unavailable` | SIP destination unavailable | Verify the destination is online and accepting calls | + | `*-outbound-sip-503-service-unavailable` | SIP service unavailable | Check the SIP provider's service status | + + + + | Error code | Meaning | Fix | + |---|---|---| + | `twilio-failed-to-connect-call` | Twilio couldn't connect the transfer | Check the destination number format and Twilio geo permissions | + | `vonage-failed-to-connect-call` | Vonage couldn't connect the transfer | Check the destination number and Vonage configuration | + | `vonage-rejected` | Vonage rejected the transfer | Check Vonage configuration and allowed destinations | + + + +For response-class guidance and checks across Vapi, your SIP provider, and your SIP infrastructure, see [Troubleshoot SIP response codes](/advanced/sip/troubleshoot-sip-response-codes). + +For a detailed transfer debugging walkthrough, see [Debug forwarding drops](/phone-calling/in-call-control/transfer-calls/debug-forwarding-drops). + +## Call ended normally + +These are not errors — they indicate the call ended as expected. + +| Error code | Meaning | Adjust if needed | +|---|---|---| +| `assistant-ended-call` | Assistant ended the call via a tool or function | Expected behavior | +| `assistant-ended-call-after-message-spoken` | Assistant spoke its final message and ended | Expected behavior | +| `assistant-ended-call-with-hangup-task` | Assistant used a hangup task | Expected behavior | +| `assistant-said-end-call-phrase` | Assistant said a configured end-call phrase | Check your end-call phrases if calls end too early | +| `assistant-forwarded-call` | Assistant transferred the call | Expected behavior | +| `customer-ended-call` | Customer hung up | Expected behavior | +| `exceeded-max-duration` | Hit `maxDurationSeconds` | Increase `maxDurationSeconds` if calls are being cut short | +| `silence-timed-out` | Silence timeout | Increase `silenceTimeoutSeconds` if the timeout is too aggressive | +| `voicemail` | Call went to voicemail | Configure [voicemail detection](/calls/voicemail-detection) settings | +| `manually-canceled` | Canceled via API or dashboard | Expected behavior | +| `vonage-completed` | Vonage reported call completed | Expected behavior | + +## Next steps + +- **[Call end reasons](/calls/call-ended-reason):** Complete reference of every `endedReason` code. +- **[Debugging voice agents](/debugging):** General debugging workflow using dashboard tools, logs, and test suites. +- **[Debug forwarding drops](/phone-calling/in-call-control/transfer-calls/debug-forwarding-drops):** Deep dive into transfer failures. +- **[Troubleshoot SIP trunk errors](/advanced/sip/troubleshoot-sip-trunk-credential-errors):** Resolve SIP credential validation failures. +- **[Troubleshoot SIP response codes](/advanced/sip/troubleshoot-sip-response-codes):** Identify where a SIP request failed and what to check next. +- **[How to report issues](/issue-reporting):** Include your `call_id` and account email when contacting support. diff --git a/fern/calls/troubleshoot-call-forwarding-drops.mdx b/fern/calls/troubleshoot-call-forwarding-drops.mdx index cade8d0bc..c0c606f38 100644 --- a/fern/calls/troubleshoot-call-forwarding-drops.mdx +++ b/fern/calls/troubleshoot-call-forwarding-drops.mdx @@ -300,3 +300,18 @@ Now that you can debug call forwarding drops: - **Monitor call patterns:** Set up alerts for calls with unexpected `endedReason` values - **Test systematically:** Verify transfers work across different destination types before production - **Review SIP setup:** Ensure your SIP configuration follows our [advanced SIP guide](https://docs.vapi.ai/advanced/sip/sip-trunk) + + + + Create a transfer call tool and configure its destinations. + + + Connect a caller immediately or add a summary to a SIP header. + + + Introduce a caller with a message, summary, or TwiML. + + + Look up transfer-related ended reasons and error codes. + + diff --git a/fern/calls/voicemail-detection.mdx b/fern/calls/voicemail-detection.mdx index f8f7fff66..4f681ba2d 100644 --- a/fern/calls/voicemail-detection.mdx +++ b/fern/calls/voicemail-detection.mdx @@ -45,16 +45,39 @@ All three providers — **Vapi, Google, and OpenAI** — support **interruption ## **How to Configure It** -On the **Assistants tab**, you'll find the Voicemail Detection section: + + + Open the [Dashboard](https://dashboard.vapi.ai/assistants). Select **Assistants**, then select the assistant you want to configure. + -![Vapi Voicemail Detection Configuration](/static/images/advanced-tab/vapi-voicemail-detection.png) + + Select the **Advanced** tab, then locate **Voicemail Detection**. + -You can choose your preferred detection provider: -- **Vapi (default)** -- **Google** -- **OpenAI** -- **Twilio** -- **Tool-based (beta)** + + Under **Voicemail Detection Provider**, choose **Off**, **Vapi (Recommended)**, **Google**, **OpenAI**, or **Twilio**. + + + + For **Vapi (Recommended)**, **Google**, or **OpenAI**, set **Initial Detection Delay**, **Detection Retry Interval**, **Max Detection Retries**, and **Max Voicemail Message Wait**. **Twilio** does not expose additional tuning controls in the Dashboard. + + + + Locate **Messaging**, then enter the message the assistant should leave in **Voicemail Message**. + + + + Select **publish** in the unsaved-changes message to apply the update. + + + + + + + + + + ## **Advanced Configuration Options** @@ -123,7 +146,8 @@ This configuration optimizes for fast detection and professional voicemail deliv "name": "Sales Outreach Assistant", "voice": { "provider": "vapi", - "voiceId": "Paige" + "version": 2, + "voiceId": "Elliot" }, "model": { "model": "gpt-4o", @@ -183,7 +207,8 @@ const salesAssistant = await vapi.assistants.create({ voice: { speed: 0.9, provider: "vapi", - voiceId: "Paige" + version: 2, + voiceId: "Elliot" }, model: { model: "gpt-4o", @@ -224,7 +249,8 @@ sales_assistant = client.assistants.create( name="Sales Outreach Assistant", voice={ "provider": "vapi", - "voiceId": "Paige" + "version": 2, + "voiceId": "Elliot" }, model={ "model": "gpt-4o", @@ -267,6 +293,7 @@ Optimized for high-accuracy detection and detailed voicemail messages: "name": "Customer Support Assistant", "voice": { "provider": "vapi", + "version": 2, "voiceId": "Elliot" }, "model": { @@ -306,6 +333,7 @@ const supportAssistant = await vapi.assistants.create({ name: "Customer Support Assistant", voice: { provider: "vapi", + version: 2, voiceId: "Elliot" }, model: { @@ -342,7 +370,8 @@ Balanced configuration for appointment confirmations with fallback voicemail: "name": "Appointment Reminder Assistant", "voice": { "provider": "vapi", - "voiceId": "Rohan" + "version": 2, + "voiceId": "Elliot" }, "model": { "model": "gpt-4o", diff --git a/fern/calls/websocket-transport.mdx b/fern/calls/websocket-transport.mdx index c3accb0dc..7ac27279a 100644 --- a/fern/calls/websocket-transport.mdx +++ b/fern/calls/websocket-transport.mdx @@ -4,8 +4,6 @@ description: Stream audio directly via WebSockets for real-time, bidirectional c slug: calls/websocket-transport --- -# WebSocket Transport - Vapi's WebSocket transport enables real-time, bidirectional audio communication directly between your application and Vapi's AI assistants. Unlike traditional phone or web calls, this transport method lets you stream raw audio data instantly with minimal latency. ## Key Benefits @@ -20,6 +18,8 @@ Vapi's WebSocket transport enables real-time, bidirectional audio communication To initiate a call using WebSocket transport: +### PCM Format (16-bit, default) + ```bash curl 'https://api.vapi.ai/call' \ -H 'authorization: Bearer YOUR_API_KEY' \ @@ -37,6 +37,25 @@ curl 'https://api.vapi.ai/call' \ }' ``` +### Mu-Law Format + +```bash +curl 'https://api.vapi.ai/call' \ + -H 'authorization: Bearer YOUR_API_KEY' \ + -H 'content-type: application/json' \ + --data-raw '{ + "assistantId": "YOUR_ASSISTANT_ID", + "transport": { + "provider": "vapi.websocket", + "audioFormat": { + "format": "mulaw", + "container": "raw", + "sampleRate": 8000 + } + } + }' +``` + ### Sample API Response ```json @@ -63,13 +82,25 @@ When creating a WebSocket call, the audio format can be customized: | Parameter | Description | Default | |-------------|-------------------------|---------------------| | `format` | Audio encoding format | `pcm_s16le` (16-bit PCM) | -| `container` | Audio container format | `raw` (Raw PCM) | -| `sampleRate`| Sample rate in Hz | `16000` (16kHz) | +| `container` | Audio container format | `raw` (Raw audio) | +| `sampleRate`| Sample rate in Hz | `16000` for PCM, `8000` for Mu-Law | + +### Supported Audio Formats + +Vapi supports the following audio formats: + +- **`pcm_s16le`**: 16-bit PCM, signed little-endian (default) +- **`mulaw`**: Mu-Law encoded audio (ITU-T G.711 standard) -Currently, Vapi supports only raw PCM (`pcm_s16le` with `raw` container). Additional formats may be supported in future updates. +Both formats use the `raw` container format for direct audio streaming. + +### Format Selection Guidelines + +- **PCM (`pcm_s16le`)**: Higher quality audio, larger bandwidth usage. Ideal for high-quality applications. +- **Mu-Law (`mulaw`)**: Lower bandwidth, telephony-standard encoding. Ideal for telephony integrations and bandwidth-constrained environments. -Vapi automatically converts sample rates as needed. You can stream audio at 8kHz, 44.1kHz, etc., and Vapi will handle conversions seamlessly. +Vapi automatically converts sample rates as needed. You can stream audio at 8kHz, 44.1kHz, etc., and Vapi will handle conversions seamlessly. The system also handles format conversions internally when needed. ## Connecting to the WebSocket @@ -88,9 +119,16 @@ socket.onerror = (error) => console.error("WebSocket error:", error); The WebSocket supports two types of messages: -- **Binary audio data** (PCM, 16-bit signed little-endian) +- **Binary audio data** (format depends on your configuration: PCM or Mu-Law) - **Text-based JSON control messages** +### Audio Data Format + +The binary audio data format depends on your `audioFormat` configuration: + +- **PCM (`pcm_s16le`)**: 16-bit signed little-endian samples +- **Mu-Law (`mulaw`)**: 8-bit Mu-Law encoded samples (ITU-T G.711) + ### Sending Audio Data ```javascript @@ -158,10 +196,12 @@ function hangupCall() { ## Ending the Call -To gracefully end the WebSocket call: +The recommended way to end a call is using [Live Call Control](/calls/call-features#end-call) which provides more control and proper cleanup. + +Alternatively, you can end the WebSocket call directly: ```javascript -sendControlMessage({ type: "hangup" }); +sendControlMessage({ type: "end-call" }); socket.close(); ``` diff --git a/fern/changelog/2025-02-27.mdx b/fern/changelog/2025-02-27.mdx index d8cf366b1..27a6b6c50 100644 --- a/fern/changelog/2025-02-27.mdx +++ b/fern/changelog/2025-02-27.mdx @@ -7,7 +7,7 @@ Configuration options: { "keypadInputPlan": { "enabled": true, // Default: false - "delimiters": "#", // Options: "#", "*", or "" (empty string) + "delimiters": ["#"], // Options: ["#"], ["*"], [""] "timeoutSeconds": 2 // Range: 0.5-10 seconds, Default: 2 } } diff --git a/fern/changelog/2025-08-28.mdx b/fern/changelog/2025-08-28.mdx new file mode 100644 index 000000000..6aeaa9540 --- /dev/null +++ b/fern/changelog/2025-08-28.mdx @@ -0,0 +1 @@ +1. **End AI call transfers after set timeout period**: You can now configure [AI-managed transfers](https://docs.vapi.ai/call-forwarding#7-assistant-based-warm-transfer-experimental) with a [Transfer Assistant](https://api.vapi.ai/api#:~:text=TransferAssistant) to automatically end the call after a specified period of silence with `silenceTimeoutSeconds` (default 30 seconds). This helps prevent idle calls from lingering and saves costs. diff --git a/fern/changelog/2025-08-29.mdx b/fern/changelog/2025-08-29.mdx new file mode 100644 index 000000000..8341591a7 --- /dev/null +++ b/fern/changelog/2025-08-29.mdx @@ -0,0 +1,5 @@ +1. **Per-Artifact Storage Routing in [Artifact Plans](https://api.vapi.ai/api#:~:text=ArtifactPlan)**: You can now override artifact storage behavior per assistant/call for SIP packet capture (PCAP), logging, and call recording artifacts: + +- `Assistant.artifactPlan.pcapUseCustomStorageEnabled` (default true): Use custom storage for SIP packet capture, which are stored in `Assistant.artifactPlan.pcapUrl`. +- `Assistant.artifactPlan.loggingUseCustomStorageEnabled` (default true): Determines whether to use your custom storage (S3 or GCP) for call logs when storage credentials are configured; set to false to store logs on Vapi's storage for this assistant, even if custom storage is set globally. +- `Assistant.artifactPlan.recordingUseCustomStorageEnabled` (default true): Determines whether to use your custom storage (S3 or GCP) for call recordings when storage credentials are configured; set to false to store recordings on Vapi's storage for this assistant, even if custom storage is set globally. diff --git a/fern/changelog/2025-08-30.mdx b/fern/changelog/2025-08-30.mdx new file mode 100644 index 000000000..5fac2a92d --- /dev/null +++ b/fern/changelog/2025-08-30.mdx @@ -0,0 +1,17 @@ +# Enhanced Authentication & Custom Credentials + +1. **Custom Credential System**: You can now create and manage custom authentication credentials using the new [`CustomCredential`](https://api.vapi.ai/api#:~:text=CustomCredential) system. This powerful new feature supports multiple authentication methods: + - **OAuth2 RFC 6749**: Full OAuth2 implementation for secure third-party integrations + - **HMAC Signing**: Cryptographic message authentication for enhanced security + - **Bearer Token**: Simple token-based authentication for API access + +2. **Bearer Authentication Plans**: Implement secure token-based authentication with [`BearerAuthenticationPlan`](https://api.vapi.ai/api#:~:text=BearerAuthenticationPlan). Key features include: + - `token`: Your secure bearer token value + - `headerName`: Custom header name (defaults to 'Authorization') + - `bearerPrefixEnabled`: Toggle 'Bearer ' prefix inclusion (defaults to true) + +3. **Enhanced Webhook Credentials**: Webhook integrations now support advanced authentication through [`WebhookCredential.authenticationPlan`](https://api.vapi.ai/api#:~:text=WebhookCredential.authenticationPlan), enabling secure webhook communications with OAuth2, HMAC, or Bearer authentication. + +4. **Server Authentication**: Secure your server endpoints with credential-based authentication using [`Server.credentialId`](https://api.vapi.ai/api#:~:text=Server.credentialId) to link your custom credentials to webhook destinations. + +5. **Tool Authentication Integration**: API request tools can now use custom credentials for secure external API calls via [`ApiRequestTool.credentialId`](https://api.vapi.ai/api#:~:text=ApiRequestTool.credentialId), eliminating the need to embed sensitive authentication details directly in tool configurations. diff --git a/fern/changelog/2025-09-02.mdx b/fern/changelog/2025-09-02.mdx new file mode 100644 index 000000000..9ebf516cf --- /dev/null +++ b/fern/changelog/2025-09-02.mdx @@ -0,0 +1,36 @@ +# Recording Consent & Compliance Management + +1. **Recording Consent Plans**: Ensure legal compliance with call recording regulations using the new [`CompliancePlan.recordingConsentPlan`](https://api.vapi.ai/api#:~:text=CompliancePlan.recordingConsentPlan). This feature helps you meet GDPR, CCPA, and other privacy regulations by properly obtaining user consent before recording calls. + +2. **Verbal Consent Collection**: Implement active consent collection with [`RecordingConsentPlanVerbal`](https://api.vapi.ai/api#:~:text=RecordingConsentPlanVerbal) where users explicitly agree or decline recording: + - `message`: Custom consent message (e.g., "This call may be recorded for quality purposes. Say 'I agree' to consent.") + - `voice`: Optional dedicated voice for consent messages for better user experience + - `declineTool`: Execute specific tools when users decline consent + - `declineToolId`: Reference existing tools for decline handling + +3. **Stay-on-Line Consent**: Use passive consent collection with [`RecordingConsentPlanStayOnLine`](https://api.vapi.ai/api#:~:text=RecordingConsentPlanStayOnLine) where staying on the call implies consent: + - `message`: Informational message about recording (e.g., "For quality purposes, this call may be recorded. Please hang up if you do not consent.") + - `waitSeconds`: Configurable wait time (1-6 seconds) before proceeding + - `voice`: Optional separate voice for consent announcements + +4. **Recording Consent Tracking**: Monitor consent status throughout the call lifecycle with [`Call.compliance.recordingConsent`](https://api.vapi.ai/api#:~:text=Call.compliance.recordingConsent): + - `type`: The type of consent obtained + - `grantedAt`: Timestamp when consent was granted (null if not granted) + +5. **Enhanced End-of-Call Reports**: Recording consent information is now included in [`ServerMessageEndOfCallReport.compliance`](https://api.vapi.ai/api#:~:text=ServerMessageEndOfCallReport.compliance), providing complete compliance audit trails for your records. + +## Compliance Features + + + Meet GDPR, CCPA, and other privacy regulations with built-in consent management and audit trails. + + + Choose between verbal consent requiring explicit agreement or stay-on-line consent with implied agreement. + + + Customize consent messages to match your brand voice and legal requirements with up to 1000 characters. + + + Complete compliance records with timestamps and consent status in call artifacts and end-of-call reports. + + \ No newline at end of file diff --git a/fern/changelog/2025-09-05.mdx b/fern/changelog/2025-09-05.mdx new file mode 100644 index 000000000..3fca7b352 --- /dev/null +++ b/fern/changelog/2025-09-05.mdx @@ -0,0 +1,47 @@ +# Evaluation System Foundation + +1. **Evaluation Framework**: You can now systematically test your Vapi voice assistants with the new [`Eval`](https://api.vapi.ai/api#:~:text=Eval) system. Create comprehensive test scenarios to validate assistant behavior, conversation flow, and tool usage through mock conversations. + +2. **Mock Conversation Builder**: Design test conversations using [`Eval.messages`](https://api.vapi.ai/api#:~:text=Eval.messages) with support for multiple message types: + - [`ChatEvalUserMessageMock`](https://api.vapi.ai/api#:~:text=ChatEvalUserMessageMock): Simulate user inputs and questions + - [`ChatEvalSystemMessageMock`](https://api.vapi.ai/api#:~:text=ChatEvalSystemMessageMock): Inject system messages mid-conversation + - [`ChatEvalToolResponseMessageMock`](https://api.vapi.ai/api#:~:text=ChatEvalToolResponseMessageMock): Mock tool responses for consistent testing + - [`ChatEvalAssistantMessageEvaluation`](https://api.vapi.ai/api#:~:text=ChatEvalAssistantMessageEvaluation): Define evaluation checkpoints + +3. **Evaluation Types**: Currently focused on `chat.mockConversation` type evaluations, with the framework designed to support additional evaluation methods in future releases. + +4. **Evaluation Management**: Organize your tests with [`CreateEvalDTO`](https://api.vapi.ai/api#:~:text=CreateEvalDTO) and [`UpdateEvalDTO`](https://api.vapi.ai/api#:~:text=UpdateEvalDTO): + - `name`: Descriptive names up to 80 characters (e.g., "Customer Support Flow Validation") + - `description`: Detailed descriptions up to 500 characters explaining the test purpose + - `messages`: The complete mock conversation flow + +5. **Evaluation Endpoints**: Access your evaluations through the new [`/eval`](https://api.vapi.ai/api#:~:text=/eval) endpoint family: + - `GET /eval`: List all evaluations with pagination support + - `POST /eval`: Create new evaluations + - `GET /eval/{id}`: Retrieve specific evaluation details + - `PUT /eval/{id}`: Update existing evaluations + +6. **Judge Plan Architecture**: Define how assistant responses are validated using [`AssistantMessageJudgePlan`](https://api.vapi.ai/api#:~:text=AssistantMessageJudgePlan) with three evaluation methods: + - **Exact Match**: [`AssistantMessageJudgePlanExact`](https://api.vapi.ai/api#:~:text=AssistantMessageJudgePlanExact) for precise content and tool call validation + - **Regex Pattern**: [`AssistantMessageJudgePlanRegex`](https://api.vapi.ai/api#:~:text=AssistantMessageJudgePlanRegex) for flexible pattern-based evaluation + - **AI Judge**: [`AssistantMessageJudgePlanAI`](https://api.vapi.ai/api#:~:text=AssistantMessageJudgePlanAI) for intelligent evaluation using LLM-as-a-judge + + + This is the foundation release for the evaluation system. Evaluation execution and results processing will be available in upcoming releases. Start designing your test scenarios now to be ready for full evaluation capabilities. + + +## Testing Capabilities + + + Create realistic test scenarios with user messages, system prompts, and expected assistant responses for comprehensive flow validation. + + + Validate that your assistant calls the right tools with correct parameters using ChatEvalAssistantMessageMockToolCall. + + + Choose from exact matching, regex patterns, or AI-powered evaluation to suit different testing needs and complexity levels. + + + Organize tests with descriptive names and detailed documentation to maintain clear testing workflows across your team. + + \ No newline at end of file diff --git a/fern/changelog/2025-09-08.mdx b/fern/changelog/2025-09-08.mdx new file mode 100644 index 000000000..5b2441c95 --- /dev/null +++ b/fern/changelog/2025-09-08.mdx @@ -0,0 +1,44 @@ +# Enhanced Transcription Features & Speech Processing + +1. **Gladia Transcription Enhancements**: Improve transcription accuracy and performance with new [`GladiaTranscriber`](https://api.vapi.ai/api#:~:text=GladiaTranscriber) features: + - `region`: Choose between `us-west` and `eu-west` for optimal latency and data residency compliance + - `receivePartialTranscripts`: Enable low-latency streaming transcription for real-time conversation flow + - Enhanced language detection with support for both single and multiple language modes + +2. **Advanced Deepgram Controls**: Fine-tune speech recognition with enhanced [`DeepgramTranscriber`](https://api.vapi.ai/api#:~:text=DeepgramTranscriber) settings: + - `eotThreshold`: End-of-turn detection threshold for precise conversation boundaries (e.g., 0.7) + - `eotTimeoutMs`: Maximum wait time for end-of-turn detection in milliseconds (e.g., 5000ms) + - `eagerEotThreshold`: Early end-of-turn detection for responsive conversations (e.g., 0.3) + +3. **AssemblyAI Keyterms Enhancement**: Boost recognition accuracy for critical terms with [`AssemblyAITranscriber.keytermsPrompt`](https://api.vapi.ai/api#:~:text=AssemblyAITranscriber.keytermsPrompt): + - Support for up to 100 keyterms, each up to 50 characters + - Improved recognition for specific words and phrases + - Additional cost: $0.04/hour when enabled + +4. **Speechmatics Custom Vocabulary**: Enhance recognition accuracy with [`SpeechmaticsCustomVocabularyItem`](https://api.vapi.ai/api#:~:text=SpeechmaticsCustomVocabularyItem): + - `content`: The word or phrase to add (e.g., "Speechmatics") + - `soundsLike`: Alternative phonetic representations (e.g., ["speech mattix"]) for better pronunciation handling + +5. **Word-Level Confidence**: Access detailed transcription confidence data with [`CustomLLMModel.wordLevelConfidenceEnabled`](https://api.vapi.ai/api#:~:text=CustomLLMModel.wordLevelConfidenceEnabled), providing word-by-word accuracy metrics for quality assessment and debugging. + +6. **Enhanced Message Metadata**: Store transcription confidence and other metadata in [`UserMessage.metadata`](https://api.vapi.ai/api#:~:text=UserMessage.metadata), enabling detailed analysis of transcription quality and user speech patterns. + + + `AssemblyAITranscriber.wordFinalizationMaxWaitTime` is now deprecated. Use the new smart endpointing plans for better speech timing control. The deprecated property will be removed in a future release. + + +## Transcription Improvements + + + Choose optimal transcription regions with Gladia's us-west and eu-west options for reduced latency and compliance. + + + Enable partial transcripts for immediate response processing, reducing perceived latency in conversations. + + + Fine-tune end-of-turn detection with configurable thresholds and timeouts for natural conversation flow. + + + Improve accuracy for domain-specific terms, company names, and technical jargon with enhanced vocabulary support. + + \ No newline at end of file diff --git a/fern/changelog/2025-09-11.mdx b/fern/changelog/2025-09-11.mdx new file mode 100644 index 000000000..4a631ec9c --- /dev/null +++ b/fern/changelog/2025-09-11.mdx @@ -0,0 +1,37 @@ +# Voice Enhancements & Minimax Improvements + +1. **Minimax Voice Language Support**: Enhance multilingual conversations with [`MinimaxVoice.languageBoost`](https://api.vapi.ai/api#:~:text=MinimaxVoice.languageBoost). Support for 40+ languages including: + - `Chinese` and `Chinese,Yue` for Mandarin and Cantonese + - `English`, `Spanish`, `French`, `German`, `Japanese`, `Korean` + - Regional variants and specialized languages like `Arabic`, `Hindi`, `Thai` + - `auto` mode for automatic language detection + +2. **Text Normalization**: Improve number reading and formatting with [`MinimaxVoice.textNormalizationEnabled`](https://api.vapi.ai/api#:~:text=MinimaxVoice.textNormalizationEnabled). When enabled, spoken numbers, dates, and formatted text are properly pronounced for natural-sounding conversations. + +3. **Enhanced Voice Caching**: Voice responses are now cached by default with [`MinimaxVoice.cachingEnabled`](https://api.vapi.ai/api#:~:text=MinimaxVoice.cachingEnabled) set to `true`, reducing latency for repeated phrases and improving overall conversation performance. + +4. **Fallback Voice Configuration**: Ensure conversation continuity with [`FallbackMinimaxVoice`](https://api.vapi.ai/api#:~:text=FallbackMinimaxVoice) featuring the same language boost and text normalization capabilities as the primary voice configuration. + +5. **Speaker Labeling**: Track multiple speakers in conversations with [`BotMessage.speakerLabel`](https://api.vapi.ai/api#:~:text=BotMessage.speakerLabel), providing stable speaker identification (e.g., "Speaker 1") for better conversation analysis and diarization. + +6. **Voice Region Support**: Choose optimal performance regions with Minimax's `worldwide` (default) or `china` regional settings for better latency and compliance with local regulations. + + + Language boost settings help the text-to-speech model better understand context and pronunciation for specific languages, resulting in more natural and accurate voice synthesis. + + +## Voice Quality Features + + + Support for 40+ languages with automatic detection and language-specific optimizations for natural pronunciation. + + + Intelligent normalization of numbers, dates, and formatted text for natural-sounding speech synthesis. + + + Voice caching reduces latency for common phrases, while regional settings optimize for local performance. + + + Speaker labeling and diarization support for multi-participant conversation analysis and management. + + \ No newline at end of file diff --git a/fern/changelog/2025-09-14.mdx b/fern/changelog/2025-09-14.mdx new file mode 100644 index 000000000..2248b3303 --- /dev/null +++ b/fern/changelog/2025-09-14.mdx @@ -0,0 +1,35 @@ +# Squad Management & Session Enhancement + +1. **Squad-Based Sessions**: Organize your assistants into collaborative teams with [`Session.squad`](https://api.vapi.ai/api#:~:text=Session.squad) and [`Session.squadId`](https://api.vapi.ai/api#:~:text=Session.squadId). Sessions can now be associated with squads for team-based conversation management and coordinated assistant behavior. + +2. **Squad Chat Integration**: Enable squad-based chat conversations using [`Chat.squad`](https://api.vapi.ai/api#:~:text=Chat.squad) and [`Chat.squadId`](https://api.vapi.ai/api#:~:text=Chat.squadId). This allows multiple assistants to participate in or be aware of chat contexts for more sophisticated conversation handling. + +3. **Enhanced Session Creation**: Create squad-enabled sessions with [`CreateSessionDTO.squad`](https://api.vapi.ai/api#:~:text=CreateSessionDTO.squad) and [`CreateSessionDTO.squadId`](https://api.vapi.ai/api#:~:text=CreateSessionDTO.squadId), enabling persistent conversation contexts across multiple assistants and interaction types. + +4. **Chat Management by Squad**: Filter and organize chats by squad membership using [`GetChatPaginatedDTO.squadId`](https://api.vapi.ai/api#:~:text=GetChatPaginatedDTO.squadId) for better conversation management and team-based analytics. + +5. **Session Management by Squad**: Query sessions by squad association with [`GetSessionPaginatedDTO.squadId`](https://api.vapi.ai/api#:~:text=GetSessionPaginatedDTO.squadId), providing team-based session organization and management capabilities. + +6. **Full Message History**: Control conversation context retention with [`ArtifactPlan.fullMessageHistoryEnabled`](https://api.vapi.ai/api#:~:text=ArtifactPlan.fullMessageHistoryEnabled). When enabled, artifacts contain complete message history even after handoff context engineering, preserving full conversation flow for analysis. + +7. **Transfer Records**: Track warm transfer details with [`Artifact.transfers`](https://api.vapi.ai/api#:~:text=Artifact.transfers), providing comprehensive records of transfer destinations, transcripts, and status information for multi-assistant conversations. + + + Squad management enables sophisticated multi-assistant workflows where different specialists can handle different parts of a conversation while maintaining shared context and coordination. + + +## Team Collaboration Features + + + Enable multiple assistants to work together within squads for specialized conversation handling and seamless handoffs. + + + Maintain conversation context across squad members and session boundaries for continuous conversation experiences. + + + Filter conversations, sessions, and analytics by squad membership for team-based performance insights and management. + + + Track all transfers and handoffs with detailed records including destinations, transcripts, and status information. + + \ No newline at end of file diff --git a/fern/changelog/2025-09-17.mdx b/fern/changelog/2025-09-17.mdx new file mode 100644 index 000000000..f9a8b4d90 --- /dev/null +++ b/fern/changelog/2025-09-17.mdx @@ -0,0 +1,36 @@ +# API Versioning & Infrastructure Updates + +1. **API Version 2 Introduction**: Access enhanced functionality through new versioned endpoints while maintaining full backward compatibility: + - [`/v2/call`](https://api.vapi.ai/api#:~:text=/v2/call): Enhanced call management with new features and improved response formats + - [`/v2/phone-number`](https://api.vapi.ai/api#:~:text=/v2/phone-number): Advanced phone number management with extended capabilities + +2. **Enhanced Pagination**: Improved pagination controls across all endpoints with [`PaginationMeta`](https://api.vapi.ai/api#:~:text=PaginationMeta) enhancements: + - `createdAtGe` and `createdAtLe`: Date range filtering for creation timestamps + - Better sorting and filtering options for large datasets + - Enhanced metadata for pagination state management + +3. **Workflow Message Configuration**: Customize voicemail handling in workflows with [`CreateWorkflowDTO.voicemailMessage`](https://api.vapi.ai/api#:~:text=CreateWorkflowDTO.voicemailMessage) and [`CreateWorkflowDTO.voicemailDetection`](https://api.vapi.ai/api#:~:text=CreateWorkflowDTO.voicemailDetection) for comprehensive call flow management. + +4. **Credential Integration**: Seamless credential management across all workflow and assistant configurations with enhanced [`credentials.items.discriminator.mapping.custom-credential`](https://api.vapi.ai/api#:~:text=credentials.items.discriminator.mapping.custom-credential) support. + +5. **Transport Infrastructure**: Foundation for advanced communication channels with improved transport configuration and management capabilities. + + + Version 2 endpoints provide enhanced features while v1 endpoints remain fully functional. Migrate to v2 when you need access to new capabilities or improved performance characteristics. + + +## Infrastructure Improvements + + + Existing v1 endpoints continue to work unchanged, ensuring smooth transitions and zero downtime for existing integrations. + + + Improved date range filtering and pagination controls for better data management and API performance. + + + Enhanced workflow configuration with better voicemail handling and credential management throughout the call flow. + + + Foundation for advanced features and capabilities that will be built on the v2 API structure. + + \ No newline at end of file diff --git a/fern/changelog/2025-09-20.mdx b/fern/changelog/2025-09-20.mdx new file mode 100644 index 000000000..6064b183a --- /dev/null +++ b/fern/changelog/2025-09-20.mdx @@ -0,0 +1,41 @@ +# Chat Transport & SMS Integration + +1. **Twilio SMS Transport**: Send chat responses directly via SMS using [`TwilioSMSChatTransport`](https://api.vapi.ai/api#:~:text=TwilioSMSChatTransport) in [`CreateChatDTO.transport`](https://api.vapi.ai/api#:~:text=CreateChatDTO.transport). This enables programmatic SMS conversations with your voice assistants, bridging the gap between voice and text communication. + +2. **SMS Session Management**: Create new sessions automatically when using SMS transport by providing: + - `customer`: Customer information for SMS delivery + - `phoneNumberId`: SMS-enabled phone number from your organization + - Automatic session creation when both fields are provided + +3. **LLM-Generated vs Direct SMS**: Control message processing with [`TwilioSMSChatTransport.useLLMGeneratedMessageForOutbound`](https://api.vapi.ai/api#:~:text=TwilioSMSChatTransport.useLLMGeneratedMessageForOutbound): + - `true` (default): Input processed by assistant for intelligent responses + - `false`: Direct message forwarding without LLM processing for notifications and alerts + +4. **Enhanced Chat Creation**: [`CreateChatDTO`](https://api.vapi.ai/api#:~:text=CreateChatDTO) now supports sophisticated session management: + - `transport`: SMS delivery configuration + - `sessionId`: Use existing session data + - Mutual exclusivity between `sessionId` and transport fields for clear session boundaries + +5. **OpenAI Responses Integration**: Streamlined chat processing with [`OpenAIResponsesRequest`](https://api.vapi.ai/api#:~:text=OpenAIResponsesRequest) supporting the same transport and squad integration features for consistent API experience. + +6. **Cross-Platform Continuity**: Seamlessly transition between voice calls and SMS conversations within the same session, maintaining context and conversation history across communication channels. + + + SMS transport requires SMS-enabled phone numbers in your organization. The phone number must support SMS functionality and belong to your account for successful message delivery. + + +## SMS Communication Features + + + Send and receive SMS messages through your voice assistant, enabling text-based interactions alongside voice conversations. + + + Choose between AI-processed responses and direct message forwarding based on your use case requirements. + + + Maintain conversation context across SMS and voice interactions within unified sessions for seamless user experiences. + + + Automatic session creation and management when using transport fields, simplifying SMS conversation setup. + + \ No newline at end of file diff --git a/fern/changelog/2025-09-23.mdx b/fern/changelog/2025-09-23.mdx new file mode 100644 index 000000000..f2479defe --- /dev/null +++ b/fern/changelog/2025-09-23.mdx @@ -0,0 +1,43 @@ +# Advanced Analytics & Variable Grouping + +1. **Variable Value Analytics**: Gain deeper insights into your assistant performance with [`AnalyticsQuery.groupByVariableValue`](https://api.vapi.ai/api#:~:text=AnalyticsQuery.groupByVariableValue). Group analytics data by specific variable values extracted during calls for granular performance analysis. + +2. **Enhanced Grouping Options**: Use [`VariableValueGroupBy`](https://api.vapi.ai/api#:~:text=VariableValueGroupBy) to specify custom grouping criteria: + - `key`: The variable value key to group by (up to 100 characters) + - Combine with existing grouping options like `assistantId`, `endedReason`, and `status` + +3. **Multi-Dimensional Analysis**: Create complex analytics queries by combining traditional grouping fields with variable values: + - Group by assistant performance AND custom business metrics + - Analyze conversation outcomes by extracted data points + - Track success rates across different variable value segments + +4. **Advanced Query Capabilities**: Enhanced [`AnalyticsQuery`](https://api.vapi.ai/api#:~:text=AnalyticsQuery) functionality enables sophisticated data analysis: + - Multiple grouping dimensions for comprehensive insights + - Variable-based segmentation for business intelligence + - Custom metric tracking through extracted call variables + +5. **Business Intelligence Integration**: Connect your call data to business outcomes by grouping analytics on: + - Customer satisfaction scores extracted from calls + - Product interest levels determined during conversations + - Lead qualification status gathered through assistant interactions + - Custom KPIs specific to your business logic + + + Variable values are extracted during calls using tool response schemas and aliases. Set up variable extraction in your tools to enable powerful analytics grouping based on conversation outcomes. + + +## Analytics Enhancements + + + Group analytics by any variable extracted during calls, enabling business-specific performance insights and KPI tracking. + + + Combine traditional call metrics with custom variable grouping for comprehensive conversation analysis. + + + Connect call performance to business outcomes through variable-based analytics and custom grouping options. + + + Create detailed reports by grouping on extracted conversation data like satisfaction scores, intent categories, or custom business metrics. + + \ No newline at end of file diff --git a/fern/changelog/2025-09-26.mdx b/fern/changelog/2025-09-26.mdx new file mode 100644 index 000000000..706f757f6 --- /dev/null +++ b/fern/changelog/2025-09-26.mdx @@ -0,0 +1,39 @@ +# Voicemail Detection & Handling Improvements + +1. **Enhanced Beep Detection**: Improve voicemail detection accuracy with [`CreateVoicemailToolDTO.beepDetectionEnabled`](https://api.vapi.ai/api#:~:text=CreateVoicemailToolDTO.beepDetectionEnabled) specifically for Twilio-based calls. This feature detects the characteristic beep sound that indicates voicemail recording has started. + +2. **Workflow Voicemail Integration**: Configure comprehensive voicemail handling in workflows with enhanced message and detection capabilities: + - [`Workflow.voicemailMessage`](https://api.vapi.ai/api#:~:text=Workflow.voicemailMessage): Custom messages for voicemail scenarios (up to 1000 characters) + - [`Workflow.voicemailDetection`](https://api.vapi.ai/api#:~:text=Workflow.voicemailDetection): Configurable detection methods for different providers + +3. **Assistant Voicemail Enhancement**: Improved voicemail handling in assistant configurations with [`Assistant.voicemailMessage`](https://api.vapi.ai/api#:~:text=Assistant.voicemailMessage) and [`Assistant.voicemailDetection`](https://api.vapi.ai/api#:~:text=Assistant.voicemailDetection) for consistent behavior across all conversation types. + +4. **Multiple Detection Methods**: Choose from various voicemail detection providers: + - **Google**: [`GoogleVoicemailDetectionPlan`](https://api.vapi.ai/api#:~:text=GoogleVoicemailDetectionPlan) for AI-powered detection + - **OpenAI**: [`OpenAIVoicemailDetectionPlan`](https://api.vapi.ai/api#:~:text=OpenAIVoicemailDetectionPlan) for intelligent voicemail recognition + - **Twilio**: [`TwilioVoicemailDetectionPlan`](https://api.vapi.ai/api#:~:text=TwilioVoicemailDetectionPlan) for carrier-level detection + - **Vapi**: [`VapiVoicemailDetectionPlan`](https://api.vapi.ai/api#:~:text=VapiVoicemailDetectionPlan) for integrated detection + +5. **Beep Detection for Call Flows**: The new beep detection capability works specifically with Twilio transport, providing reliable voicemail identification when traditional detection methods may not be sufficient. + +6. **Voicemail Tool Configuration**: Enhanced tool rejection and messaging capabilities ensure appropriate handling when voicemail is detected, with configurable responses based on your business requirements. + + + Beep detection is currently available only for Twilio-based calls. If you're using other providers, consider combining multiple detection methods for better accuracy. + + +## Voicemail Management Features + + + Support for Google, OpenAI, Twilio, and Vapi detection methods, allowing you to choose the best option for your use case. + + + Advanced audio analysis to detect voicemail beeps on Twilio calls for more reliable voicemail identification. + + + Configure personalized voicemail messages up to 1000 characters for better user experience and brand consistency. + + + Comprehensive voicemail handling throughout workflow nodes with consistent configuration across conversation flows. + + \ No newline at end of file diff --git a/fern/changelog/2025-09-28.mdx b/fern/changelog/2025-09-28.mdx new file mode 100644 index 000000000..0d6c91e31 --- /dev/null +++ b/fern/changelog/2025-09-28.mdx @@ -0,0 +1,49 @@ +# Evaluation Execution & Results Processing + +1. **Evaluation Execution Engine**: Run comprehensive assistant evaluations with [`EvalRun`](https://api.vapi.ai/api#:~:text=EvalRun) and [`CreateEvalRunDTO`](https://api.vapi.ai/api#:~:text=CreateEvalRunDTO). Execute your mock conversations against live assistants and squads to validate performance and behavior in controlled environments. + +2. **Multiple Evaluation Models**: Choose from various AI models for LLM-as-a-judge evaluation: + - [`EvalOpenAIModel`](https://api.vapi.ai/api#:~:text=EvalOpenAIModel): GPT models including GPT-4.1, o1-mini, o3, and regional variants + - [`EvalAnthropicModel`](https://api.vapi.ai/api#:~:text=EvalAnthropicModel): Claude models with optional thinking features for complex evaluations + - [`EvalGoogleModel`](https://api.vapi.ai/api#:~:text=EvalGoogleModel): Gemini models from 1.0 Pro to 2.5 Pro for diverse evaluation needs + - [`EvalGroqModel`](https://api.vapi.ai/api#:~:text=EvalGroqModel): High-speed inference models including Llama and custom options + - [`EvalCustomModel`](https://api.vapi.ai/api#:~:text=EvalCustomModel): Your own evaluation models with custom endpoints + +3. **Evaluation Results**: Comprehensive result tracking with [`EvalRunResult`](https://api.vapi.ai/api#:~:text=EvalRunResult): + - `status`: Pass/fail evaluation outcomes + - `messages`: Complete conversation transcript from the evaluation + - `startedAt` and `endedAt`: Precise timing information for performance analysis + +4. **Target Flexibility**: Run evaluations against different targets: + - [`EvalRunTargetAssistant`](https://api.vapi.ai/api#:~:text=EvalRunTargetAssistant): Test individual assistants with optional overrides + - [`EvalRunTargetSquad`](https://api.vapi.ai/api#:~:text=EvalRunTargetSquad): Evaluate entire squad performance and coordination + +5. **Evaluation Status Tracking**: Monitor evaluation progress with detailed status information: + - `running`: Evaluation in progress + - `ended`: Evaluation completed + - `queued`: Evaluation waiting to start + - Detailed `endedReason` including success, error, timeout, and cancellation states + +6. **Judge Configuration**: Optimize evaluation accuracy with model-specific settings: + - `maxTokens`: Recommended 50-10000 tokens (1 token for simple pass/fail responses) + - `temperature`: 0-0.3 recommended for LLM-as-a-judge to reduce hallucinations + + + For LLM-as-a-judge evaluations, the judge model must respond with exactly \"pass\" or \"fail\". Design your evaluation prompts to ensure clear, deterministic responses. + + +## Evaluation Capabilities + + + Choose from OpenAI, Anthropic, Google, Groq, or custom models for evaluation, matching your quality and performance requirements. + + + Detailed pass/fail results with complete conversation transcripts and timing information for thorough analysis. + + + Test individual assistants or entire squads with optional configuration overrides for comprehensive validation. + + + Real-time evaluation status tracking with detailed reason codes for failures, timeouts, and cancellations. + + \ No newline at end of file diff --git a/fern/changelog/2025-09-29.mdx b/fern/changelog/2025-09-29.mdx new file mode 100644 index 000000000..8de49ca2d --- /dev/null +++ b/fern/changelog/2025-09-29.mdx @@ -0,0 +1,66 @@ +# Breaking Changes & API Cleanup + +1. **Legacy Endpoint Removal**: The following deprecated endpoints have been removed as part of our API modernization effort: + - `/logs` - Use call artifacts and monitoring instead + - `/workflow/{id}` - Access workflows through the main workflow endpoints + - `/test-suite` and related paths - Replaced by the new evaluation system + - `/knowledge-base` and related paths - Integrated into model configurations + +2. **Knowledge Base Architecture Change**: The `knowledgeBaseId` property has been removed from all model configurations. This affects: + - [`XaiModel`](https://api.vapi.ai/api#:~:text=XaiModel), [`GroqModel`](https://api.vapi.ai/api#:~:text=GroqModel), [`GoogleModel`](https://api.vapi.ai/api#:~:text=GoogleModel) + - [`OpenAIModel`](https://api.vapi.ai/api#:~:text=OpenAIModel), [`AnthropicModel`](https://api.vapi.ai/api#:~:text=AnthropicModel), [`CustomLLMModel`](https://api.vapi.ai/api#:~:text=CustomLLMModel) + - All other model provider configurations + +3. **Transcriber Property Deprecation**: [`AssemblyAITranscriber.wordFinalizationMaxWaitTime`](https://api.vapi.ai/api#:~:text=AssemblyAITranscriber.wordFinalizationMaxWaitTime) and [`FallbackAssemblyAITranscriber.wordFinalizationMaxWaitTime`](https://api.vapi.ai/api#:~:text=FallbackAssemblyAITranscriber.wordFinalizationMaxWaitTime) are now deprecated: + - Use smart endpointing plans for better speech timing control + - More precise conversation flow management + - Enhanced end-of-turn detection capabilities + +4. **Schema Path Cleanup**: Removed numerous unused schema paths from model configurations to simplify the API structure and improve performance. This cleanup affects internal schema references but doesn't impact your existing integrations. + +5. **New v2 API**: We are introducing a new API version v2. These changes are part of our ongoing effort to: + - Simplify the API structure for better developer experience + - Remove redundant and deprecated functionality + - Complete the transition to new evaluation and compliance systems + - Improve API performance and maintainability + +For details on the new features that replace these deprecated endpoints, see our recent changelog entries: +- [Enhanced Authentication & Custom Credentials (Aug 30)](./2025-08-30.mdx) +- [Recording Consent & Compliance Management (Sep 2)](./2025-09-02.mdx) +- [Evaluation System Foundation (Sep 5)](./2025-09-05.mdx) +- [Evaluation Execution & Results Processing (Sep 28)](./2025-09-28.mdx) + + + If you're currently using any of the removed endpoints or properties, you must migrate to the new alternatives before this release. Contact support if you need assistance with migration strategies. + + +## Migration Guide + + + Replace /logs endpoint usage with call artifacts, monitoring plans, and end-of-call reports for comprehensive logging. + + + Migrate from test-suite endpoints to the new evaluation system with mock conversations and comprehensive result tracking. + + + Update model configurations to use the integrated knowledge base system instead of separate knowledgeBaseId references. + + + Replace deprecated transcriber timing properties with smart endpointing plans for better conversation flow control. + + + +## Removed Endpoints +The following endpoints are no longer available: +- `GET /logs` - Use call artifacts instead +- `GET /workflow/{id}` - Use main workflow endpoints +- `GET /test-suite`, `POST /test-suite` - Use [evaluation endpoints](./2025-09-05.mdx) +- `GET /test-suite/{id}`, `PUT /test-suite/{id}`, `DELETE /test-suite/{id}` - Use [evaluation management](./2025-09-28.mdx) +- `POST /test-suite/{testSuiteId}/run` - Use [evaluation runs](./2025-09-28.mdx) +- `GET /knowledge-base`, `POST /knowledge-base` - Integrated into model configurations +- All related nested endpoints and operations + +**See Also:** +- [Authentication System Updates (Aug 30)](./2025-08-30.mdx) - For credential management migration +- [Recording Consent Features (Sep 2)](./2025-09-02.mdx) - For compliance system details +- [Enhanced Transcription (Sep 8)](./2025-09-08.mdx) - For AssemblyAI timing alternatives \ No newline at end of file diff --git a/fern/changelog/2026-03-31.mdx b/fern/changelog/2026-03-31.mdx new file mode 100644 index 000000000..8a94351de --- /dev/null +++ b/fern/changelog/2026-03-31.mdx @@ -0,0 +1,79 @@ +# What's New: October 2025 – March 2026 + +Here's a summary of major items shipped from October 2025 through March 2026. + +--- + +## Platform + +1. **Squads v2**: Visual builder to simplify sophisticated multi-assistant orchestration with seamless handoffs between specialized agents. + +2. **Composer (Alpha)**: Intelligent assistant inside the dashboard that allows you to describe what you need through plain text prompts to help build, adjust, and debug voice agents. + +3. **Simulations (Alpha)**: Voice agent testing feature to build confidence through enabling systematic, AI-powered testing in specific scenarios with evaluation of outcomes. + +4. **Monitoring & Issues**: Automated call quality monitoring with trigger-based issue detection, alerting, and resolution suggestions. + +5. **HIPAA with Data Retention**: New compliance mode with private storage and in-dashboard toggle/purchase flow — available for additional cost. + +6. **Zero Data Retention**: Compliance mode that keeps context data during call as needed to execute tasks and retains no data afterwards. + +7. **Consolidated Logs**: Unified log viewing into a single page. + +8. **Vapi Voices**: 12 new ultra-realistic voices released, optimized for latency and cost with adjustable speed controls exposed. 8 legacy voices deprecated. + +--- + +## New Models & Provider Support + +### Transcriber Models (Speech-to-Text) + +1. **Deepgram Nova-3 Languages**: Added Hebrew, Urdu, Tagalog, and Arabic bilingual support. + +2. **Cartesia Transcriber**: ink-whisper. + +3. **Soniox**: stt-rt-v4. + +### Intelligence Models (LLM) + +1. **GPT-5 Family**: OpenAI's latest intelligence models, including GPT-5, 5-Mini, 5-Nano, 5.1, 5.2, 5.4, 5.4-Mini, 5.4-Nano. + +2. **Claude 4.5–4.6**: Anthropic's latest intelligence models Sonnet 4.5, Opus 4.5, Opus 4.6, Sonnet 4.6. + +3. **Gemini 3 Flash**: Google's latest intelligence models. + +4. **Grok 4 Fast**: Reasoning and non-reasoning variants. + +5. **GPT Realtime Mini**: OpenAI's lightweight realtime model. + +### Voice Models (Text-to-Speech) + +1. **Cartesia**: sonic-3, sonic-3-2026-01-12, sonic-3-2025-10-27. + +2. **WellSaid**: Caruso (new), legacy. + +3. **Inworld**: inworld-tts-1 (REST, original), inworld-tts-1.5-max (WebSocket, \$10/M chars), inworld-tts-1.5-mini (WebSocket, \$5/M chars). + +4. **ElevenLabs Scribe v2**: Latest version of ElevenLabs speech-to-text. + +--- + +## Developer Tools & API + +1. **Structured Outputs Improvements**: Updates to our AI-powered analysis and data extraction tool, including transient structured outputs, audio-based extraction, and regex extraction. + +2. **SIP Request Tool + DTMF over SIP INFO**: Send SIP requests and DTMF tones via SIP INFO messages during calls. + +3. **Variable Passing Between Tool Calls**: Pass output variables from one tool call as input to subsequent tool calls. + +4. **Encrypted Tool Arguments**: Encrypt sensitive tool arguments to protect data in transit. + +5. **Low Confidence Speech Hook**: Hook that triggers when the transcriber returns low-confidence speech results. + +6. **Time Elapsed Hook**: Hook that triggers at specified time intervals during a call. + +7. **assistant.speechStarted Event**: New event fired when the assistant begins speaking. + +8. **MCP Improvements**: Bearer auth, $ref dereferencing, child tool messages/discovery. + +9. **Warm Transfer Improvements**: SIP support, caller ID, context engineering, variable filling. diff --git a/fern/changelog/2026-04-13.mdx b/fern/changelog/2026-04-13.mdx new file mode 100644 index 000000000..16ad57ef3 --- /dev/null +++ b/fern/changelog/2026-04-13.mdx @@ -0,0 +1,6 @@ +# What's New: Week of April 13, 2026 + +1. **Monitoring — GA**: Automated call quality monitoring is now generally available. Detect issues with trigger-based rules, get alerts when something goes wrong, and surface resolution suggestions — all from the dashboard. + + - [Monitoring quickstart](https://docs.vapi.ai/observability/monitoring-quickstart) + - [Announcement blog post](https://blog.vapi.ai/monitoring) diff --git a/fern/changelog/2026-04-20.mdx b/fern/changelog/2026-04-20.mdx new file mode 100644 index 000000000..196e76921 --- /dev/null +++ b/fern/changelog/2026-04-20.mdx @@ -0,0 +1,14 @@ +# What's New: Week of April 20, 2026 + +1. **Logs UX Refresh**: New filter layout plus a round of UX improvements — improved date picker, active row is clearly highlighted across all log views when the flyout is opened, log tables are fully keyboard-accessible, sortable `cost` and `duration` columns, pagination, and more. + +2. **Squads `contextEngineeringPlan` Handoff Type — `previousAssistantMessages`**: Forwards only the conversation history from *before* the current assistant's session. The current assistant's own messages and tool calls are excluded entirely from the handoff payload. See the updated [handoff context configuration docs](https://docs.vapi.ai/security-and-privacy/pci#handoff-context-configuration). + +3. **`assistant.speechStarted` Event — Live Captions & Word-Level Timing (GA)**: A new opt-in message fires as the assistant begins speaking each segment, carrying the full turn text, `turn`, `source` (`model` / `force-say` / `custom-voice`), and optional timing: + - Per-word alignment on **ElevenLabs** + - Cursor-based word-progress on **Minimax** (set `voice.subtitleType: "word"`, with correct CJK handling) + - Text-only fallback on all other providers + + Subscribe by adding `"assistant.speechStarted"` to your assistant's `clientMessages` and/or `serverMessages` — now **GA with no feature flag**. Use it for live captions, karaoke-style highlighting, or any UI that needs to stay in sync with assistant audio. Fully backward-compatible; no existing messages changed. + +4. **Autofallbacks on Transcribers**: Let Vapi pick the best transcriber to fall back to if your primary one fails — even mid-call. Opt in by setting `assistant.transcriber.fallbackPlan.autoFallback.enabled` to `true`. See the updated [transcriber fallback plan docs](https://docs.vapi.ai/customization/transcriber-fallback-plan). diff --git a/fern/changelog/2026-04-27.mdx b/fern/changelog/2026-04-27.mdx new file mode 100644 index 000000000..03a1b3231 --- /dev/null +++ b/fern/changelog/2026-04-27.mdx @@ -0,0 +1,3 @@ +# What's New: Week of April 27, 2026 + +1. **Deepgram Flux — Multilingual Support**: Full support for Deepgram's multilingual Flux model. Multilingual agents can now leverage the same smart turn-taking that powers the English Flux transcriber, making cross-lingual conversations feel more fluid and natural. diff --git a/fern/changelog/2026-05-04.mdx b/fern/changelog/2026-05-04.mdx new file mode 100644 index 000000000..ab51f4ba2 --- /dev/null +++ b/fern/changelog/2026-05-04.mdx @@ -0,0 +1,3 @@ +# What's New: Week of May 4, 2026 + +1. **Soniox — General Availability**: The Soniox transcriber is now rolled out to all customers. Configure it on any assistant via `assistant.transcriber` (provider: `soniox`) for low-latency, multilingual real-time speech-to-text. diff --git a/fern/changelog/2026-05-11.mdx b/fern/changelog/2026-05-11.mdx new file mode 100644 index 000000000..c400a881f --- /dev/null +++ b/fern/changelog/2026-05-11.mdx @@ -0,0 +1,4 @@ +# What's New: Week of May 11, 2026 + +1. **New Assistant Builder Experience**: An updated, streamlined assistant configuration experience, now available to all users. + - UI optimizations for the Phone Numbers page were also made to align its look and interactions with the new experience. diff --git a/fern/changelog/2026-05-18.mdx b/fern/changelog/2026-05-18.mdx new file mode 100644 index 000000000..5af2cafdb --- /dev/null +++ b/fern/changelog/2026-05-18.mdx @@ -0,0 +1,5 @@ +# What's New: Week of May 18, 2026 + +1. **Responsive UI Polish**: A round of UI adjustments to make the app work better across viewport sizes. + +2. **New Composer-Based Onboarding Flow**: A new onboarding experience built on top of the Assistant Builder and powered by Composer is rolling out to select users as part of a phased release. diff --git a/fern/changelog/2026-05-25.mdx b/fern/changelog/2026-05-25.mdx new file mode 100644 index 000000000..38f56ea61 --- /dev/null +++ b/fern/changelog/2026-05-25.mdx @@ -0,0 +1,3 @@ +# What's New: Week of May 25, 2026 + +1. **Dashboard Performance**: Front-end infrastructure improvements for faster page loads and a snappier feel across the dashboard. diff --git a/fern/changelog/2026-06-01.mdx b/fern/changelog/2026-06-01.mdx new file mode 100644 index 000000000..b9374cc0b --- /dev/null +++ b/fern/changelog/2026-06-01.mdx @@ -0,0 +1,12 @@ +# What's New: Week of June 1, 2026 + +1. **xAI Speech-to-Text and Text-to-Speech**: xAI is now available as a transcriber (STT) and voice (TTS) provider for assistants. + +2. **Upgraded Vapi Voices**: A new text-to-speech model powering [Vapi Voices](https://docs.vapi.ai/providers/voice/vapi-voices) makes them sound more authentic, human, and consistent — at ~50% lower cost. + - Existing deployments don't change automatically — opt in by setting `version: 2` on the voice configuration via the API or Dashboard. See [Vapi Voices](https://docs.vapi.ai/providers/voice/vapi-voices) for supported voices and audio samples. + +3. **Pronunciation Dictionaries in the Dashboard**: The Assistants view now supports creating new [pronunciation dictionaries](https://docs.vapi.ai/assistants/pronunciation-dictionaries) directly from the dashboard. + +4. **Phone Number Fixes**: Improvements to phone number creation and listing. + - The Phone Numbers list no longer breaks on rows with no number or SIP URI. + - Creating a phone number now validates its Vapi identifier up front. diff --git a/fern/changelog/2026-06-15.mdx b/fern/changelog/2026-06-15.mdx new file mode 100644 index 000000000..91bef9e15 --- /dev/null +++ b/fern/changelog/2026-06-15.mdx @@ -0,0 +1,17 @@ +# What's New: Week of June 15, 2026 + +1. **Claude Haiku (Global)**: Now available as a model through [Amazon Bedrock](https://docs.vapi.ai/providers/model/anthropic-bedrock) for assistants. + +2. **Pronunciation Dictionary Management in Voice Config**: [Pronunciation dictionaries](https://docs.vapi.ai/assistants/pronunciation-dictionaries) configured via the API can now be viewed and managed directly in an assistant's voice settings in the dashboard. + - Stale dictionary references are flagged when a voice changes to a model that cannot apply them. + +3. **Rotating Tool Messages**: You can now configure multiple [message variants](https://docs.vapi.ai/tools/custom-tools) for a tool, and the assistant picks one at random so longer calls feel less repetitive. + +4. **Dynamic Variables in Test Calls**: A dialog lets you set [dynamic variable](https://docs.vapi.ai/assistants/dynamic-variables) values before starting a test call from the dashboard. + +5. **Concurrency and Rate Limits in Organization Settings**: Your [call concurrency](https://docs.vapi.ai/calls/call-concurrency) cap and API request rate limit now appear as read-only fields in Organization Settings. + +6. **Fixes and Improvements**: + - Cartesia voice overrides in squads now apply correctly instead of falling back to a hard-coded default. + - Duplicate tools sharing the same `function.name` are de-duplicated during model streaming, preventing duplicate tool calls. + - The call concurrency chart in analytics now renders correctly. diff --git a/fern/changelog/2026-06-22.mdx b/fern/changelog/2026-06-22.mdx new file mode 100644 index 000000000..e190610fd --- /dev/null +++ b/fern/changelog/2026-06-22.mdx @@ -0,0 +1,9 @@ +# What's New: Week of June 22, 2026 + +1. **Gemini 3.5 Flash and 3.1 Flash-Lite**: Google's [Gemini 3.5 Flash and 3.1 Flash-Lite](https://docs.vapi.ai/providers/model/gemini) models are now available for assistants. + +2. **Soniox stt-rt-v5**: A new `stt-rt-v5` real-time speech-to-text model is available for the Soniox transcriber. + +3. **Discord Login Removed**: Discord is no longer offered as a login or signup option. + +4. **Variable Values in Handoff Webhooks**: After an assistant handoff, webhook payloads now include the assistant's configured `variableValues`. diff --git a/fern/changelog/2026-06-29.mdx b/fern/changelog/2026-06-29.mdx new file mode 100644 index 000000000..75cf4c5c3 --- /dev/null +++ b/fern/changelog/2026-06-29.mdx @@ -0,0 +1,12 @@ +# What's New: Week of June 29, 2026 + +1. **OpenAI Realtime v2**: OpenAI's latest [Realtime v2](https://docs.vapi.ai/openai-realtime) model is now available for assistants. + +2. **AI-Generated Tool Failure and Completion Messages**: You can now set `role: 'system'` on request-failed [tool messages](https://docs.vapi.ai/tools/custom-tools), and the dashboard has a new UI for configuring AI-generated messages when tools fail or complete. This gives assistants more natural responses when tools hit errors. + +3. **Call Logs Improvements**: + - Significant latency improvements across both the dashboard and the `/calls` API endpoints. + - The call detail flyout now shows which assistant or squad handled the call, includes a link to the assistant or squad, and indicates which phone number was used. + - In squad or handoff calls, transcript messages now show which assistant said what, making it easier to trace conversation flow. + +4. **MCP Child Tools in Dashboard**: When you connect an [MCP server](https://docs.vapi.ai/sdk/mcp-server), the dashboard tool form now lists all child tools it discovers, so you can see exactly what capabilities your MCP server exposes. diff --git a/fern/changelog/2026-07-13.mdx b/fern/changelog/2026-07-13.mdx new file mode 100644 index 000000000..28285ae50 --- /dev/null +++ b/fern/changelog/2026-07-13.mdx @@ -0,0 +1,9 @@ +# What's New: Week of July 13, 2026 + +1. **Playback Speed for Recordings**: Call recording players now include a playback-speed control. + +2. **Download Every Recording Type**: You can now download every recording a call produced: mono, stereo, separate assistant and customer tracks, video, and packet capture. + +3. **VAD Transitions in Call Logs**: The call log now surfaces voice-activity-detection transitions with a per-phase latency breakdown. + +4. **HIPAA Compliance**: xAI is now HIPAA-compliant across its model, voice, and transcriber. diff --git a/fern/changelog/2026-07-20.mdx b/fern/changelog/2026-07-20.mdx new file mode 100644 index 000000000..056f1c369 --- /dev/null +++ b/fern/changelog/2026-07-20.mdx @@ -0,0 +1,7 @@ +# What's New: Week of July 20, 2026 + +1. **Model Intelligence**: You can now set your assistant's transcriber, llm, and voice models in one click with a [Model Preset](/assistants/model-intelligence/presets) (choose between Balanced, High Intelligence, Ultra Fast, or Cost Saver), and see the latency, cost, and quality metrics for your chosen models so you can compare options and optimize with data. + +2. **Recording Download URLs in the End of Call Report**: The end of call report now includes short-lived presigned download URLs for your [call recordings and logs](/assistants/retrieve-call-artifacts), so you can download them directly. + +3. **End of Call Reports with Zero Data Retention**: End of call reports are now reliably delivered for transient assistants running under Zero Data Retention. diff --git a/fern/changelog/2026-07-27.mdx b/fern/changelog/2026-07-27.mdx new file mode 100644 index 000000000..276bb563a --- /dev/null +++ b/fern/changelog/2026-07-27.mdx @@ -0,0 +1,15 @@ +# What's New: Week of July 27, 2026 + +## New Models + +1. **Anthropic Claude Sonnet 5**: Anthropic's Claude Sonnet 5 is now available as a model for assistants. + +2. **OpenAI GPT-5.5 "Instant"**: OpenAI's [GPT-5.5](/providers/model/openai) (`gpt-5.5` and `chat-latest`) is now available as a model for assistants. + +3. **OpenAI GPT-5.6 Models**: OpenAI's [GPT-5.6](/providers/model/openai) models (`sol`, `terra`, and `luna`) are now available for assistants. + +4. **Inworld TTS-2**: Inworld's [TTS-2](/providers/voice/inworld) voice is now available for assistants. + +## SIP Call Transfers + +1. **SIP Warm Transfer Audio**: Warm [call transfers](/call-forwarding) on SIP calls now play hold audio to the operator and a completion sound (`transferCompleteAudioUrl`) when the transfer connects. diff --git a/fern/changelog/2026-08-03.mdx b/fern/changelog/2026-08-03.mdx new file mode 100644 index 000000000..91302ff94 --- /dev/null +++ b/fern/changelog/2026-08-03.mdx @@ -0,0 +1,5 @@ +# What's New: Week of August 3, 2026 + +1. **Conditional Structured Outputs**: You can now add conditions to a [structured output](/assistants/structured-outputs) so it only generates when the condition is met, and any skipped outputs are surfaced in the assistant preview, call logs, and sessions. + +2. **Deepgram Aura-2 German Voices**: New German voices are now available for [Deepgram's Aura-2](/providers/voice/deepgram) voice. diff --git a/fern/changelog/2026-08-10.mdx b/fern/changelog/2026-08-10.mdx new file mode 100644 index 000000000..b34ce4760 --- /dev/null +++ b/fern/changelog/2026-08-10.mdx @@ -0,0 +1,14 @@ +# What's New: Week of August 10, 2026 + +1. **Simulations**: You can now build [simulation](/observability/simulations-overview) suites and run them against your assistants or squads to test and evaluate their behavior, with detailed results for each run. + +2. **Unified Provider and Model Picker**: The assistant editor now combines provider and model into a single picker for your LLM, voice, and transcriber. + +3. **Chat and Session Log Export**: You can now export selected rows from chat and session logs and use a bulk-actions bar, matching the call logs experience. + +4. **SIP Transfer Improvements**: Blind [call transfers](/call-forwarding) now support a configurable `fallbackPlan`, SIP verb, and dial timeout, and cold-transfer outcomes now appear in call logs. + +5. **Composer Improvements**: [Composer](/composer) is now more capable, reliable, and easier to use when building voice agents. + - Upload files for it to reference, read current Vapi documentation directly, and follow new Vapi-built skills for building assistants, choosing models, managing tools, configuring phone numbers, and debugging calls. + - Longer, multi-step tasks are far more reliable, with mid-task error recovery and progress that survives page refreshes and thread switches. + - Connect Google Calendar from the conversation, clickable resource mentions with copyable IDs, and cleaner, collapsible activity timelines. diff --git a/fern/changelog/2026-08-17.mdx b/fern/changelog/2026-08-17.mdx new file mode 100644 index 000000000..6c03aa84f --- /dev/null +++ b/fern/changelog/2026-08-17.mdx @@ -0,0 +1,7 @@ +# What's New: Week of August 17, 2026 + +1. **Assistant and Tool Versioning**: Edits no longer go live immediately. Work in a draft, publish when you're ready, and every publish creates a named [version snapshot](/assistants/versioning), so you can go back to your history to see what changed or roll back to a previous version as needed. You can also pin a specific tool version to an assistant. + +2. **Call Artifact Upload Webhook**: A new [`call.artifact.upload`](/api-reference/webhooks/server-message) server message fires as each recording, packet capture, and log finishes uploading, and it includes the result for each, so you can process artifacts as they arrive instead of waiting for the end of call report. + +3. **Azure Region Pinning for GPT-5 Models**: You can now pin a GPT-5 model to a specific [Azure](/providers/model/azure-openai) region by adding the region to the model name after a colon (for example `gpt-5:eastus2`), which keeps requests in that region for lower latency and data residency. It uses Vapi's platform Azure credential, so no Bring Your Own Key (BYOK) is needed. diff --git a/fern/changelog/2026-08-24.mdx b/fern/changelog/2026-08-24.mdx new file mode 100644 index 000000000..f60a319be --- /dev/null +++ b/fern/changelog/2026-08-24.mdx @@ -0,0 +1,5 @@ +# What's New: Week of August 24, 2026 + +1. **AssemblyAI Universal 3.5 Pro**: AssemblyAI's [Universal 3.5 Pro](/providers/transcriber/assembly-ai) model is now available as a transcriber for your assistants. + +2. **Websocket Call Type Filter**: You can now filter call logs by Websocket call type. diff --git a/fern/changelog/overview.mdx b/fern/changelog/overview.mdx index 6beee95dd..168d27496 100644 --- a/fern/changelog/overview.mdx +++ b/fern/changelog/overview.mdx @@ -1,90 +1,34 @@ --- -slug: changelog +slug: whats-new --- document.querySelector('input[type="email"]').focus()}>Get the (almost) daily changelog} + title="Subscribe to the latest product updates" icon="envelope" iconType="solid" >
{ - const emailInput = document.getElementById('email_input'); - const emailValue = emailInput.value; - const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; - if (!emailPattern.test(emailValue)) { - e.preventDefault(); - alert('Please enter a valid email address.'); - } - }} > -
+
+
\ No newline at end of file diff --git a/fern/chat/non-streaming.mdx b/fern/chat/non-streaming.mdx index 7ca58d880..d7085ea8f 100644 --- a/fern/chat/non-streaming.mdx +++ b/fern/chat/non-streaming.mdx @@ -1,6 +1,7 @@ --- title: Non-streaming chat subtitle: Build reliable chat integrations with complete response patterns for batch processing and simple UIs +description: Build a non-streaming Vapi chat integration that returns complete responses, maintains conversation context, and supports reliable request-response workflows. slug: chat/non-streaming --- diff --git a/fern/chat/openai-compatibility.mdx b/fern/chat/openai-compatibility.mdx index 50de50ca8..b2d026fe8 100644 --- a/fern/chat/openai-compatibility.mdx +++ b/fern/chat/openai-compatibility.mdx @@ -1,6 +1,7 @@ --- title: OpenAI compatibility subtitle: Seamlessly migrate existing OpenAI integrations to Vapi with zero code changes +description: Use Vapi through OpenAI-compatible chat interfaces, migrate existing integrations, and support streaming, non-streaming, and common JavaScript frameworks. slug: chat/openai-compatibility --- diff --git a/fern/chat/quickstart.mdx b/fern/chat/quickstart.mdx index 1f010c443..76537ef01 100644 --- a/fern/chat/quickstart.mdx +++ b/fern/chat/quickstart.mdx @@ -1,6 +1,7 @@ --- title: Chat quickstart subtitle: Build your first text-based conversation with a Vapi assistant in 5 minutes +description: "Create a text chat with a Vapi assistant, send messages through the Chat API, continue conversations, pass variables, and integrate with TypeScript apps." slug: chat/quickstart --- @@ -23,6 +24,7 @@ Build a customer service chat bot that can handle text-based conversations throu * A [Vapi account](https://dashboard.vapi.ai/) * An existing assistant or willingness to create one * Basic knowledge of making API requests +* For a pay-as-you-go subscription, the billing setup described in [Troubleshooting](#troubleshooting) ## Scenario @@ -33,14 +35,8 @@ We'll create a customer support chat for "TechFlow", a software company that wan ## 1. Get Your API Credentials - - Go to [dashboard.vapi.ai](https://dashboard.vapi.ai) and log in to your account. - - - Click on your profile in the top right, then select `Vapi API Keys`. - - - Copy your Private API Key. You'll need this for all chat requests. + + Follow the [Vapi API key guide](/security-and-privacy/api-keys) to create, view, or copy a private key. Use this key to authenticate server-side chat requests. Keep this key secure - never expose it in client-side code. @@ -310,11 +306,47 @@ We'll create a customer support chat for "TechFlow", a software company that wan +## Troubleshooting + +The Chat API returns HTTP `402` when the pay-as-you-go organization does not meet a billing requirement. Use the message to identify the required action. + +| Message | What it means | What to do | +| --- | --- | --- | +| `Add a payment method to use chat. Pay-as-you-go orgs require a card on file.` | The organization does not have a saved payment method. | [Add a payment method](/billing/manage-billing-and-credits). | +| `Purchase credits to use chat. New pay-as-you-go orgs require a completed payment.` | The pay-as-you-go subscription is less than 30 days old and the organization has no completed payment. | [Buy credits](/billing/manage-billing-and-credits) or complete another purchase. Adding a card does not count as a payment. | + +## Frequently asked questions + + + + Every pay-as-you-go organization needs a saved payment method. During the subscription's first 30 days, the organization must also have completed a payment. Enterprise and agency plans do not have these requirements. + + + + No. The purchase requirement applies only to chat. + + + + No. Adding a card authorizes future charges but does not complete a payment. To unblock chat during the first 30 days, [buy credits](/billing/manage-billing-and-credits) or complete another purchase. + + + + No. One completed payment permanently satisfies the requirement for the organization. The payment does not need to be recent or recurring. + + + + The completed-payment requirement ends when the pay-as-you-go subscription reaches 30 days old. The organization still needs a saved payment method to use chat. + + + + Chat access usually returns within one minute after the payment settles. If chat remains blocked, wait one minute, refresh the Dashboard, and try again. + + + ## Limitations **Current chat functionality limitations:** -- "Query" tool for knowledge-base searches is not yet supported - Server webhook events (status updates, end-of-call reports, etc.) are not supported diff --git a/fern/chat/session-management.mdx b/fern/chat/session-management.mdx index 6a0a09d79..1175f4f07 100644 --- a/fern/chat/session-management.mdx +++ b/fern/chat/session-management.mdx @@ -1,6 +1,7 @@ --- title: Session management subtitle: Maintain conversation context using previousChatId vs sessionId +description: Manage Vapi chat context with previousChatId or sessionId, understand when to use each method, and build persistent multi-turn conversations safely at scale. slug: chat/session-management --- diff --git a/fern/chat/sms-chat.mdx b/fern/chat/sms-chat.mdx new file mode 100644 index 000000000..05dfc937c --- /dev/null +++ b/fern/chat/sms-chat.mdx @@ -0,0 +1,116 @@ +--- +title: SMS chat +subtitle: Enable text-based conversations with assistants via SMS messaging +description: Connect a 10DLC-approved Twilio number to a Vapi assistant, receive customer-initiated SMS messages, and maintain context through managed chat sessions. +slug: chat/sms-chat +--- + +## Overview + +Let customers chat with your Vapi assistants through SMS text messages. Perfect for businesses that want to provide AI support through familiar messaging channels. + +**What You'll Enable:** +* Text-based conversations through SMS +* Automatic session management for each customer +* Context-aware responses across message exchanges + + +SMS chat requires a **10DLC-approved Twilio number**. Only customers can initiate conversations - assistants cannot send the first message. + + +## Prerequisites + +* A [Vapi account](https://dashboard.vapi.ai/) with an existing assistant +* A **10DLC-approved Twilio phone number** (required for assistant responses) +* Basic understanding of phone number management + +--- + +## Setup Steps + + + + Bring your approved Twilio number into Vapi so we can manage SMS messaging. + + + SMS is **enabled by default** when importing Twilio numbers. + + + See: [Import number from Twilio](/phone-numbers/import-twilio) and [Inbound SMS setup](/phone-numbers/inbound-sms) + + + Assign the assistant that will handle SMS conversations for this number. + + When customers text your number, they'll automatically start a chat session with this assistant. + + + Send a text message to your phone number to verify the assistant responds correctly. + + + + +View all SMS conversations in the [Session Logs](https://dashboard.vapi.ai/logs/session) page of your dashboard. Each SMS conversation creates a session where you can see the full message history and conversation flow. + + +--- + +## How It Works + +When a customer texts your number: + +1. **Session Creation**: Vapi automatically creates a chat session for the customer +2. **Context Management**: All messages maintain conversation context within the session +3. **Response Delivery**: Assistant responses are sent back as SMS messages +4. **Session Expiry**: Sessions expire after 24 hours of inactivity, then create fresh sessions for new conversations + +```mermaid +sequenceDiagram + participant Customer + participant Twilio + participant Vapi + participant Assistant + + Customer->>Twilio: "Hi, I need help" + Twilio->>Vapi: SMS webhook + Vapi->>Vapi: Create/find session + Vapi->>Assistant: Process message + Assistant->>Vapi: Generate response + Vapi->>Twilio: Send SMS response + Twilio->>Customer: "Hello! How can I help?" +``` + +--- + +## Session Management + +SMS conversations use automatic session management: + +* **New customers**: Get a fresh session on first text +* **Returning customers**: Continue existing session if under 24 hours +* **Session expiry**: After 24 hours, new session created automatically +* **Context preservation**: Full conversation history maintained within session + +--- + +## Limitations + + +**Current SMS chat limitations:** +- **10DLC requirement**: Only 10DLC-approved Twilio numbers support assistant responses +- **Customer-initiated**: Assistants cannot send the first message to customers +- **Twilio only**: Other SMS providers are not currently supported + + +--- + +## Next Steps + +Enhance your SMS chat implementation: + +* **[Chat API](/chat/quickstart)** - Understand the underlying chat technology +* **[Session management](/chat/session-management)** - Learn how sessions work in detail +* **[Assistant configuration](/assistants/quickstart)** - Optimize your assistant for text conversations + + +For the best SMS experience, configure your assistant with concise responses and clear conversation flows. SMS users expect quick, direct answers. + diff --git a/fern/chat/streaming.mdx b/fern/chat/streaming.mdx index 083d58792..6e4cca4f1 100644 --- a/fern/chat/streaming.mdx +++ b/fern/chat/streaming.mdx @@ -1,6 +1,7 @@ --- title: Streaming chat subtitle: Build real-time chat experiences with token-by-token responses like ChatGPT +description: Build a streaming Vapi chat integration with server-sent events, display tokens as they arrive, and maintain context across real-time app conversations. slug: chat/streaming --- diff --git a/fern/chat/variable-substitution.mdx b/fern/chat/variable-substitution.mdx new file mode 100644 index 000000000..54553663b --- /dev/null +++ b/fern/chat/variable-substitution.mdx @@ -0,0 +1,172 @@ +--- +title: Variable substitution in sessions +subtitle: Learn how template variables behave with sessions and chats +description: Use variable substitution in Vapi chat sessions, understand when values are resolved, and choose safe patterns for updating personalized conversation context. +slug: chat/variable-substitution +--- + +## Overview + +When using sessions with the Chat API, understanding how variable substitution works is essential for building dynamic, personalized conversations. + +**Key concept:** Variables are substituted at session creation time and "baked into" the stored assistant configuration. Template placeholders like `{{name}}` are replaced with actual values and no longer exist in the session. + + +Vapi uses [LiquidJS](https://liquidjs.com/) for variable substitution. The `{{ }}` syntax follows Liquid template language conventions, giving you access to filters, conditionals, and other Liquid features beyond simple variable replacement. + + +--- + +## How variable substitution works + +### At session creation + +When you create a session with `assistantOverrides.variableValues`, the system: + +1. Takes your assistant's template variables (e.g., `"Hello {{name}} from {{company}}"`) +2. Substitutes all `{{ }}` placeholders using LiquidJS +3. Stores the **pre-substituted assistant** in the session +4. Saves the original variable values in `session.metadata.variableValues` for reference + +```bash title="Create session with variables" +curl -X POST https://api.vapi.ai/session \ + -H "Authorization: Bearer $VAPI_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "assistantId": "79f3cae3-5e47-4d8c-a1b2-9f8e7d6c5b4a", + "assistantOverrides": { + "variableValues": { + "name": "John", + "company": "Acme Corp" + } + } + }' +``` + +If your assistant's system prompt was `"You are a helpful assistant for {{name}} at {{company}}"`, the session stores: `"You are a helpful assistant for John at Acme Corp"`. + +### At chat creation + +When you send a chat request with a `sessionId`: + +1. The system loads the session's pre-substituted assistant +2. Any `variableValues` in the chat request are processed, but **there are no `{{ }}` placeholders left** to substitute +3. New variable values have **no effect** on already-substituted text + +--- + +## Behavior examples + +### Variables persist across chats + +Once you set variables at session creation, they persist for all chats in that session: + +```bash title="Chat using the session" +curl -X POST https://api.vapi.ai/chat \ + -H "Authorization: Bearer $VAPI_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "sessionId": "6b4c494f-c22c-4bce-84fa-a7a86942c7d3", + "input": "What is my name and company?" + }' +``` + +The assistant will respond with the values set at session creation (John, Acme Corp). + +### New variableValues don't override session values + + +Passing new `variableValues` in a chat request **will not** change the session's pre-substituted assistant. The template placeholders no longer exist. + + +```bash title="This will NOT change the assistant's context" +curl -X POST https://api.vapi.ai/chat \ + -H "Authorization: Bearer $VAPI_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "sessionId": "6b4c494f-c22c-4bce-84fa-a7a86942c7d3", + "input": "What is my name and company?", + "assistantOverrides": { + "variableValues": { + "name": "Jane", + "company": "Wayne Enterprises" + } + } + }' +``` + +The assistant still responds with "John" and "Acme Corp" because the original templates were already replaced. + +### Provide fresh templates to use new values + +To use different variable values mid-session, provide a new template with `{{ }}` placeholders along with the new values: + +```bash title="Override with fresh template" +curl -X POST https://api.vapi.ai/chat \ + -H "Authorization: Bearer $VAPI_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "sessionId": "6b4c494f-c22c-4bce-84fa-a7a86942c7d3", + "input": "What is my name and company?", + "assistantOverrides": { + "model": { + "provider": "openai", + "model": "gpt-4.1", + "systemPrompt": "You are a helpful assistant for {{name}} at {{company}}. Be very formal." + }, + "variableValues": { + "name": "Jane", + "company": "Wayne Enterprises" + } + } + }' +``` + +Now the assistant responds with "Jane" and "Wayne Enterprises" because fresh template placeholders were provided. + +--- + +## Quick reference + +| Scenario | Variables applied? | Why | +|----------|-------------------|-----| +| Session creation with `variableValues` | ✅ Yes | Templates exist, substitution happens | +| Chat with just `sessionId` | ✅ Session values persist | Pre-substituted assistant is used | +| Chat with `sessionId` + new `variableValues` | ❌ No effect | No `{{ }}` placeholders left to substitute | +| Chat with `sessionId` + new template with `{{ }}` + new `variableValues` | ✅ New values applied | Fresh templates provided | + +--- + +## Best practices + +### For consistent variables across a session + +Pass `assistantOverrides.variableValues` once when creating the session. Subsequent chat requests only need the `sessionId` and `input`. + +### For different variables per conversation + +Choose one of these approaches: + + + + Pass the full assistant configuration in each chat request. This gives you complete control over variables per request. + + + Include a new system prompt (or other text field) with `{{ }}` placeholders plus new `variableValues` in your chat request. + + + Create a new session for each unique variable context. This keeps conversations cleanly separated. + + + +--- + +## Next steps + +- **[Session management](/chat/session-management)** - Learn about `previousChatId` vs `sessionId` approaches +- **[Variables](/assistants/dynamic-variables)** - Configure dynamic variables in your assistant +- **[Streaming responses](/chat/streaming)** - Add real-time responses to your chats + + +Need help? Chat with the team on our [Discord](https://discord.com/invite/pUFNcf2WmH) or mention us on [X/Twitter](https://x.com/Vapi_AI). + diff --git a/fern/chat/web-widget.mdx b/fern/chat/web-widget.mdx index 8b1665df5..4bf010646 100644 --- a/fern/chat/web-widget.mdx +++ b/fern/chat/web-widget.mdx @@ -1,6 +1,7 @@ --- title: Web widget subtitle: Add AI chat and voice capabilities to any website with a simple embeddable widget +description: "Add Vapi's web widget to a website for voice and text conversations, configure its appearance and behavior, and meet pay-as-you-go chat access requirements." slug: chat/web-widget --- @@ -25,7 +26,7 @@ View the complete source code and examples on [GitHub](https://github.com/VapiAI ## Prerequisites -* A [Vapi account](https://dashboard.vapi.ai/) with a public API key +* A [Vapi account](https://dashboard.vapi.ai/) with a [public API key](/security-and-privacy/api-keys) * An existing assistant or willingness to create one * A website where you want to embed the widget @@ -38,14 +39,8 @@ We'll add a customer support widget to "TechFlow's" website that allows visitors ## 1. Get Your Public API Key - - Go to [dashboard.vapi.ai](https://dashboard.vapi.ai) and log in to your account. - - - Click on your profile in the top right, then select `Vapi API Keys`. - - - Copy your **Public API Key**. This is safe to use in client-side code. + + Follow the [Vapi API key guide](/security-and-privacy/api-keys) to create, view, or copy a public key. Unlike private keys, public keys are safe to expose in your website code. @@ -459,7 +454,7 @@ You must provide either `assistant-id`, `assistant`, or both `assistant-id` and * Microphone access for voice mode * HTTPS required in production -* Vapi account and API key +* Vapi account and [API key](/security-and-privacy/api-keys) ## Next Steps @@ -471,9 +466,9 @@ Enhance your widget integration: * **[Assistant customization](/assistants)** - Fine-tune your assistant's behavior -The widget automatically handles microphone permissions, audio processing, and cross-browser compatibility. For custom implementations, consider using the [Web SDK](/sdk/web) directly. +The widget automatically handles microphone permissions, audio processing, and cross-browser compatibility. For custom implementations, consider using the [Web SDK](/quickstart/web) directly. Need help? Chat with the team on our [Discord](https://discord.com/invite/pUFNcf2WmH) or mention us on [X/Twitter](https://x.com/Vapi_AI). - \ No newline at end of file + diff --git a/fern/cli/authentication.mdx b/fern/cli/authentication.mdx index 3215cd174..327cc60a3 100644 --- a/fern/cli/authentication.mdx +++ b/fern/cli/authentication.mdx @@ -193,7 +193,7 @@ vapi auth switch production # Client B work vapi auth switch client-b - vapi workflow list + vapi assistant list ``` diff --git a/fern/cli/mcp-integration.mdx b/fern/cli/mcp-integration.mdx index d5dd5ed22..7d767647f 100644 --- a/fern/cli/mcp-integration.mdx +++ b/fern/cli/mcp-integration.mdx @@ -287,7 +287,7 @@ The Vapi MCP server provides these tools to your IDE: Step-by-step guides for complex features - **Example:** "Workflow implementation guide" + **Example:** "Custom tool implementation guide" @@ -387,8 +387,8 @@ Now that MCP is configured: - **[Create assistants](/quickstart/phone):** Build your first voice AI - **[Test webhooks locally](/cli/webhook):** Debug webhooks with tunneling services -- **[Manage resources](/cli/overview#common-commands):** Use CLI commands +- **[Manage resources](/cli#common-commands):** Use CLI commands --- -**Pro tip:** After setting up MCP, try asking your IDE to "Create a complete Vapi voice assistant with error handling and logging" - watch it generate production-ready code with all the right patterns! \ No newline at end of file +**Pro tip:** After setting up MCP, try asking your IDE to "Create a complete Vapi voice assistant with error handling and logging" - watch it generate production-ready code with all the right patterns! diff --git a/fern/cli/overview.mdx b/fern/cli/overview.mdx index 682850217..e6250cab1 100644 --- a/fern/cli/overview.mdx +++ b/fern/cli/overview.mdx @@ -11,7 +11,7 @@ The Vapi CLI is the official command-line interface that brings world-class deve **In this guide, you'll learn to:** - Install and authenticate with the Vapi CLI - Initialize Vapi in existing projects -- Manage assistants, phone numbers, and workflows from your terminal +- Manage assistants, phone numbers, and calls from your terminal - Forward webhooks to your local development server - Turn your IDE into a Vapi expert with MCP integration @@ -130,7 +130,6 @@ Everything you can do in the dashboard, now in your terminal: - **Assistants**: Create, update, list, and delete voice assistants - **Phone numbers**: Purchase, configure, and manage phone numbers - **Calls**: Make outbound calls and view call history -- **Workflows**: Manage conversation flows (visual editing in dashboard) - **Campaigns**: Create and manage AI phone campaigns at scale - **Tools**: Configure custom functions and integrations - **Webhooks**: Set up and test event delivery diff --git a/fern/cli/project-integration.mdx b/fern/cli/project-integration.mdx index d5e3ed5b0..18fa02f17 100644 --- a/fern/cli/project-integration.mdx +++ b/fern/cli/project-integration.mdx @@ -220,8 +220,8 @@ After initialization, configure your environment: ``` - - Get your API key from the [Vapi Dashboard](https://dashboard.vapi.ai/): + + Follow the [Vapi API key guide](/security-and-privacy/api-keys) to create, view, or copy an API key: ```bash VAPI_API_KEY=your-api-key-here ``` @@ -348,4 +348,4 @@ Next steps: 2. Add your VAPI_API_KEY 3. Run: npm run dev 4. Test the voice button at http://localhost:3000 -``` \ No newline at end of file +``` diff --git a/fern/composer.mdx b/fern/composer.mdx new file mode 100644 index 000000000..5b7105d5c --- /dev/null +++ b/fern/composer.mdx @@ -0,0 +1,286 @@ +--- +title: Composer +subtitle: Build and configure voice AI agents through natural conversation +slug: composer +--- + + +Composer is currently in **Alpha**. Features and behavior may change as we iterate based on user feedback. + + +## Overview + +Composer is Vapi's intelligent assistant that helps you build and configure voice AI agents through natural conversation. Instead of manually configuring settings and writing prompts, describe what you want to build and Composer handles the technical setup. + +Composer understands voice agent architecture and Vapi's capabilities. It can create agents, configure phone numbers, set up integrations, troubleshoot issues, and answer questions about Vapi features. + +**Why use Composer:** + +- **Faster development** — Build agents in minutes instead of hours by describing your use case +- **Best practices built in** — Composer applies Vapi best practices automatically +- **Lower barrier to entry** — No need to learn every API parameter or configuration option +- **Troubleshooting support** — Composer can diagnose issues and suggest fixes + +## Get started + + + + Log into your [Vapi dashboard](https://dashboard.vapi.ai) and click the **Composer** option in the navigation, or use the chat widget. + + + Tell Composer what you need in plain language. The more context you provide, the better the result. + + **Effective prompts:** + - "Help me build a restaurant reservation agent" + - "I need to set up a phone number for my agent" + - "Create an agent that can answer questions about my business" + - "My agent isn't transferring calls correctly, can you help?" + + + Composer asks follow-up questions to understand your requirements, then takes action to build and configure your agent. + + + Test the agent Composer creates, then request adjustments as needed. Building the right agent is an iterative process. + + + +## What Composer can do + +### Capabilities + +- Create and configure assistants +- Set up phone numbers +- Configure integrations and webhooks +- Update agent prompts and settings +- Troubleshoot technical issues +- Answer questions about Vapi features +- Recommend best practices for your use case + +### Limitations + +- **Cannot delete resources** — Composer cannot delete assistants, tools, phone numbers, or any other resources. This is an intentional safety measure. Use the dashboard sidebar to delete resources manually. +- **Cannot access external systems** — Composer operates within Vapi and cannot reach your CRM, database, or other third-party systems directly. +- **Cannot make business logic decisions** — You provide the domain knowledge; Composer handles the technical configuration. +- **Cannot test your agent** — You need to test the agent yourself and provide feedback. +- **Cannot deploy to production automatically** — You control when and how changes go live. + +## Common use cases + + + + **What you say:** + + > "I want to build an agent for my dental office that can schedule appointments and answer common questions about our services." + + **What Composer does:** + 1. Asks about your specific requirements (hours, services, appointment types) + 2. Creates an agent with an appropriate system prompt + 3. Configures necessary tools (calendar integration, knowledge base) + 4. Sets up phone number configuration + 5. Provides testing guidance + + **Your part:** + - Answer Composer's questions about your business + - Provide specific details (office hours, services offered, etc.) + - Test the agent and provide feedback + + **Example conversation:** + + ```txt title="Sample conversation" + You: "I want to build an agent for my dental office that can schedule + appointments and answer common questions." + + Composer: "I'd be happy to help you build a dental office agent! Let me + ask a few questions: + + 1. What are your office hours? + 2. What types of appointments do you offer? + 3. Do you want the agent to book directly or collect information + for your staff to follow up? + 4. What are the most common questions patients ask?" + + You: "Office hours are Mon-Fri 9am-5pm. We do cleanings, exams, and + consultations. The agent should collect appointment requests and our + staff will confirm. Common questions are about insurance, parking, + and first-visit procedures." + + Composer: "I've created your dental office agent. It's configured to: + - Collect appointment requests during business hours + - Answer questions about insurance, parking, and first visits + - Escalate to staff when needed + + Would you like me to set up a phone number for testing?" + ``` + + + + **What you say:** + + > "I need to connect a phone number to my agent." + + **What Composer does:** + 1. Asks if you want to purchase a new number or import an existing one + 2. Helps you select an area code or region + 3. Configures the number to work with your agent + 4. Provides the phone number for testing + + + If you need a specific area code for local presence, mention it upfront. If you're porting an existing number, have your account details from your current provider ready. + + + + + **What you say:** + + > "My agent keeps dropping calls when trying to transfer." + + **What Composer does:** + 1. Asks diagnostic questions (when does it happen, what number, etc.) + 2. Checks your agent configuration + 3. Identifies the issue (incorrect transfer format, missing permissions, etc.) + 4. Fixes the configuration or guides you through the fix + + **Common issues Composer can help with:** + - Call transfers not working + - Agent not responding correctly to specific inputs + - Phone number routing problems + - Integration failures (calendar, CRM, etc.) + - Voice quality or latency issues + - Prompt behavior not matching expectations + + + + **What you say:** + + > "I want my agent to check availability in our calendar before booking appointments." + + **What Composer does:** + 1. Explains integration options (API webhooks, direct integrations) + 2. Helps configure the integration endpoint + 3. Sets up the agent to call your API with the right parameters + 4. Provides example requests/responses for testing + + **Your part:** + - Provide your API endpoint URL + - Share authentication details (API keys, etc.) + - Describe the expected request/response format + - Test the integration with real scenarios + + **Popular integrations:** Google Calendar, Calendly, Salesforce, HubSpot, booking systems, knowledge bases, and custom APIs. + + + +## Safety features + +Composer includes safeguards to prevent accidental or irreversible changes to your account. + +### No deletion capability + +Composer **cannot delete any resources** — assistants, tools, phone numbers, squads, files, or anything else. This is a deliberate safety measure, not a limitation. + +If you ask Composer to delete something, it directs you to do it yourself: + +```txt title="Deletion request example" +You: "Delete my old test assistant" + +Composer: "I'm not able to delete resources to prevent accidental data loss. +You can delete it yourself from the dashboard — use the sidebar on the left, +go to Assistants, select the one you want to remove, and delete it from there." +``` + + +Unlike creating or updating a resource (which can be undone or re-done), deletion is permanent. Requiring manual confirmation through the dashboard UI prevents accidental loss of important configurations. + + +### Approval required for updates + +When Composer modifies an existing resource (like updating an assistant's prompt, changing a voice setting, or editing a tool configuration), it pauses and asks for your explicit approval first. + +**How the approval flow works:** + + + + Composer shows you a summary of the update it wants to make. + + + The chat interface displays **Approve** and **Deny** buttons. Click **Approve** to proceed or **Deny** to cancel. + + + If approved, Composer makes the update and confirms. If denied, no changes are made. + + + +```txt title="Approval flow example" +You: "Change my agent's voice to sound more energetic" + +Composer: [Proposes update] +→ UI shows: "Update Resource — Updating voice settings on assistant xyz" + [Approve] [Deny] + +You: [Clicks Approve] + +Composer: "Done! I've updated the voice settings. Test it out and let me +know if you'd like to adjust further." +``` + +**Key details about approvals:** + +- **Tokens expire after 10 minutes** — if you don't respond in time, Composer needs to re-propose the change +- **Each approval is specific** — approval tokens are cryptographically bound to the exact change being made; multiple updates each require individual approval +- **Read operations don't require approval** — Composer can freely read and list your resources without permission +- **Creating new resources doesn't require approval** — new assistants, tools, and other resources are additive and non-destructive + +## Tips for best results + +### Be specific about your use case + +Provide context about your industry, audience, and requirements upfront. + +```txt title="Compare prompt quality" +Less effective: "I need an agent" + +More effective: "I need an agent for my e-commerce store that can track +orders, answer product questions, and handle returns" +``` + +### Iterate in stages + +Build a basic working agent first, then layer on advanced features: + +1. **Phase 1** — Basic conversation flow +2. **Phase 2** — Add integrations (calendar, CRM, knowledge base) +3. **Phase 3** — Add advanced features (custom voices, complex routing) + +### Handle one task at a time + +Keep conversations focused on a single objective for best results. + +```txt title="Compare task scoping" +Less effective: "Set up my phone number, fix the transfer issue, add +Spanish support, and integrate with my CRM" + +More effective: "First, let's set up my phone number" +[Complete that task] +"Great! Now can you help me fix the transfer issue?" +``` + +### Ask Composer to explain + +If you're unsure about Vapi features or want to learn the API, ask directly: + +- "What's the best way to handle voicemail?" +- "Should I use function calling or server URL for my integration?" +- "Can you show me the API call you're making to create this agent?" + + +Ask Composer for the full configuration of an agent it builds. Save it in version control to use as a template for similar agents. + + +## Next steps + +Now that you know how Composer works: + +- **[Assistants quickstart](/assistants/quickstart):** Learn the fundamentals of building voice agents manually +- **[Prompting guide](/prompting-guide):** Write effective system prompts for your agents +- **[Tools overview](/tools):** Understand the tools and integrations available to your agents +- **[Phone numbers](/free-telephony):** Set up phone numbers for your agents diff --git a/fern/custom.js b/fern/custom.js index 8666b5c7f..6434797a4 100644 --- a/fern/custom.js +++ b/fern/custom.js @@ -1,10 +1,12 @@ const WIDGET_TAG = 'vapi-voice-agent-widget'; +const ENABLE_VOICE_WIDGET = false; // Feature flag to enable/disable the floating voice widget const isLocalhost = window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1'; const WIDGET_SCRIPT_URL = isLocalhost ? 'http://localhost:9001/widget.js' : 'https://docs-widget.vercel.app/widget.js'; const HOCKEYSTACK_API_KEY = '96e358f635f3f5ea7fda26023b10da'; +const REO_CLIENT_ID = '0dc28e3fda800b9'; function injectVapiWidget() { console.log('[custom.js] injectVapiWidget called'); @@ -46,17 +48,177 @@ function initializeHockeyStack() { hsscript.dataset.apikey = HOCKEYSTACK_API_KEY; hsscript.dataset.cookieless = 1; hsscript.dataset.autoIdentify = 1; - + document.getElementsByTagName('head')[0].append(hsscript); } +function initializeReo() { + if (isLocalhost) { + console.log('[custom.js] Skipping Reo on localhost'); + return; + } + + var reoScript = document.createElement("script"); + reoScript.type = "text/javascript"; + reoScript.src = "https://static.reo.dev/" + REO_CLIENT_ID + "/reo.js"; + reoScript.defer = true; + reoScript.onload = function() { + if (typeof Reo !== 'undefined') { + Reo.init({ clientID: REO_CLIENT_ID }); + } + }; + document.head.appendChild(reoScript); +} + +function configurePostHog() { + if (isLocalhost) { + console.log('[custom.js] Skipping PostHog configuration on localhost'); + return; + } + + // Wait for PostHog to be initialized by Fern + const checkPostHog = setInterval(() => { + if (typeof window.posthog !== 'undefined') { + clearInterval(checkPostHog); + + // Configure cross-domain tracking + window.posthog.set_config({ + cross_subdomain_cookie: true, + cross_domain: '.vapi.ai', + persistence: 'localStorage+cookie' + }); + + } + }, 100); + +} + +function initializeHubSpot() { + + if (isLocalhost) { + console.log('[custom.js] Skipping HubSpot configuration on localhost'); + return; + } + + var hubSpotScript = document.createElement("script"); + hubSpotScript.type = "text/javascript"; + hubSpotScript.id = "hs-script-loader"; + hubSpotScript.src = "https://js-na2.hs-scripts.com/244349038.js"; + hubSpotScript.async = true; + hubSpotScript.defer = true; + document.getElementsByTagName('head')[0].appendChild(hubSpotScript); +} + +function initializeSubscribeForm() { + // Fern's MDX renderer strips JSX event handlers (onSubmit, onClick), so the + // form's validation and submission logic must be attached from plain JS. + // Without this, the form falls through to a native HTML POST that silently + // redirects back to the same page with no user feedback. + + var form = document.querySelector('form.subscribe-form'); + if (!form) { + return; + } + + // Avoid attaching the handler twice on SPA navigations + if (form.dataset.enhanced === 'true') { + return; + } + form.dataset.enhanced = 'true'; + + form.addEventListener('submit', function (e) { + e.preventDefault(); + + var emailInput = form.querySelector('input[name="email"]'); + var submitBtn = form.querySelector('button[type="submit"]'); + var messageDiv = form.querySelector('.subscribe-form-message'); + + if (!emailInput || !submitBtn) { + return; + } + + var email = emailInput.value.trim(); + var emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; + + if (!emailPattern.test(email)) { + if (messageDiv) { + messageDiv.textContent = 'Please enter a valid email address.'; + messageDiv.className = 'subscribe-form-message error'; + messageDiv.style.display = 'block'; + } + return; + } + + // Hide any previous message and disable the button while submitting + if (messageDiv) { + messageDiv.style.display = 'none'; + } + submitBtn.disabled = true; + var originalText = submitBtn.textContent; + submitBtn.textContent = 'Submitting...'; + + var formAction = form.getAttribute('action'); + var formData = new FormData(); + formData.append('email', email); + + fetch(formAction, { + method: 'POST', + body: formData, + redirect: 'manual', + }) + .then(function (response) { + // Customer.io returns 302 on success which becomes an opaque redirect + // with redirect:'manual'. Both 302 and opaque (type 0) indicate success. + if (response.ok || response.status === 302 || response.status === 0 || response.type === 'opaqueredirect') { + if (messageDiv) { + messageDiv.textContent = 'Thanks for subscribing! You will receive product updates at ' + email + '.'; + messageDiv.className = 'subscribe-form-message success'; + messageDiv.style.display = 'block'; + } + emailInput.value = ''; + } else { + throw new Error('Unexpected response: ' + response.status); + } + }) + .catch(function () { + if (messageDiv) { + messageDiv.textContent = 'Something went wrong. Please try again.'; + messageDiv.className = 'subscribe-form-message error'; + messageDiv.style.display = 'block'; + } + }) + .finally(function () { + submitBtn.disabled = false; + submitBtn.textContent = originalText; + }); + }); +} + function initializeAll() { initializeHockeyStack(); - injectVapiWidget(); + initializeReo(); + initializeHubSpot(); + configurePostHog(); + initializeSubscribeForm(); + if (ENABLE_VOICE_WIDGET) { + injectVapiWidget(); + } } +// Fern uses client-side routing, so the form may appear after the initial page +// load. Re-attach the handler whenever the DOM changes on the whats-new page. +var subscribeFormObserver = new MutationObserver(function () { + if (window.location.pathname.indexOf('whats-new') !== -1) { + initializeSubscribeForm(); + } +}); + if (document.readyState === 'loading') { - document.addEventListener('DOMContentLoaded', initializeAll); + document.addEventListener('DOMContentLoaded', function () { + initializeAll(); + subscribeFormObserver.observe(document.body, { childList: true, subtree: true }); + }); } else { initializeAll(); -} \ No newline at end of file + subscribeFormObserver.observe(document.body, { childList: true, subtree: true }); +} \ No newline at end of file diff --git a/fern/custom.spec.js b/fern/custom.spec.js new file mode 100644 index 000000000..8b4860837 --- /dev/null +++ b/fern/custom.spec.js @@ -0,0 +1,155 @@ +/** + * Standalone tests for the subscribe form logic in custom.js. + * + * These tests validate the initializeSubscribeForm() function by extracting + * its logic and running it against a mock DOM. No external dependencies + * required -- run with: node fern/custom.spec.js + * + * The function under test is extracted here rather than imported because + * custom.js is a browser script that reads window.location at parse time. + */ + +'use strict'; + +let passed = 0; +let failed = 0; + +function assert(condition, message) { + if (condition) { + passed++; + console.log(' PASS: ' + message); + } else { + failed++; + console.error(' FAIL: ' + message); + } +} + +function assertEqual(actual, expected, message) { + if (actual === expected) { + passed++; + console.log(' PASS: ' + message); + } else { + failed++; + console.error(' FAIL: ' + message + ' (expected ' + JSON.stringify(expected) + ', got ' + JSON.stringify(actual) + ')'); + } +} + +// --------------------------------------------------------------------------- +// Extracted logic from initializeSubscribeForm (the core of the fix) +// --------------------------------------------------------------------------- + +function emailValidate(email) { + var emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; + return emailPattern.test(email); +} + +// --------------------------------------------------------------------------- +// Tests +// --------------------------------------------------------------------------- + +console.log('\n--- Email validation ---'); + +assert(emailValidate('user@example.com'), 'accepts standard email'); +assert(emailValidate('user+tag@domain.co.uk'), 'accepts email with plus and subdomain'); +assert(emailValidate('a@b.c'), 'accepts minimal valid email'); +assert(!emailValidate(''), 'rejects empty string'); +assert(!emailValidate('not-an-email'), 'rejects string without @'); +assert(!emailValidate('user@'), 'rejects email missing domain'); +assert(!emailValidate('@domain.com'), 'rejects email missing local part'); +assert(!emailValidate('user @domain.com'), 'rejects email with space'); +assert(!emailValidate('user@domain'), 'rejects email without TLD dot'); + +console.log('\n--- MDX structure validation ---'); + +var fs = require('fs'); +var path = require('path'); + +var mdxPath = path.join(__dirname, 'changelog', 'overview.mdx'); +var mdxContent = fs.readFileSync(mdxPath, 'utf-8'); + +assert(mdxContent.indexOf('class="subscribe-form"') !== -1 || mdxContent.indexOf('className="subscribe-form"') !== -1, + 'MDX contains form with subscribe-form class'); +assert(mdxContent.indexOf('customerioforms.com') !== -1, + 'MDX contains Customer.io form action URL'); +assert(mdxContent.indexOf('name="email"') !== -1, + 'MDX contains email input with correct name attribute'); +assert(mdxContent.indexOf('type="submit"') !== -1, + 'MDX contains submit button'); +assert(mdxContent.indexOf('subscribe-form-message') !== -1, + 'MDX contains message div for feedback'); +assert(mdxContent.indexOf('subscribe-form-input') !== -1, + 'MDX uses CSS class for input styling'); +assert(mdxContent.indexOf('subscribe-form-button') !== -1, + 'MDX uses CSS class for button styling'); + +// Verify the broken onSubmit handler is removed +assert(mdxContent.indexOf('onSubmit') === -1, + 'MDX does not contain onSubmit handler (Fern strips JSX event handlers)'); +assert(mdxContent.indexOf('onClick') === -1, + 'MDX does not contain onClick handler (Fern strips JSX event handlers)'); + +console.log('\n--- custom.js structure validation ---'); + +var customJsPath = path.join(__dirname, 'custom.js'); +var customJsContent = fs.readFileSync(customJsPath, 'utf-8'); + +assert(customJsContent.indexOf('initializeSubscribeForm') !== -1, + 'custom.js contains initializeSubscribeForm function'); +assert(customJsContent.indexOf('addEventListener') !== -1 && customJsContent.indexOf("'submit'") !== -1, + 'custom.js attaches submit event listener'); +assert(customJsContent.indexOf('e.preventDefault()') !== -1, + 'custom.js prevents default form submission'); +assert(customJsContent.indexOf("redirect: 'manual'") !== -1, + 'custom.js uses fetch with redirect:manual to handle 302'); +assert(customJsContent.indexOf('opaqueredirect') !== -1, + 'custom.js checks for opaqueredirect response type'); +assert(customJsContent.indexOf('subscribe-form-message') !== -1, + 'custom.js updates the message div'); +assert(customJsContent.indexOf('Thanks for subscribing') !== -1, + 'custom.js shows success message'); +assert(customJsContent.indexOf('Something went wrong') !== -1, + 'custom.js shows error message on failure'); +assert(customJsContent.indexOf("dataset.enhanced === 'true'") !== -1, + 'custom.js guards against duplicate handler attachment'); +assert(customJsContent.indexOf('MutationObserver') !== -1, + 'custom.js uses MutationObserver for SPA route changes'); +assert(customJsContent.indexOf('Submitting...') !== -1, + 'custom.js shows loading state on button'); + +console.log('\n--- CSS validation ---'); + +var cssPath = path.join(__dirname, 'assets', 'styles.css'); +var cssContent = fs.readFileSync(cssPath, 'utf-8'); + +assert(cssContent.indexOf('.subscribe-form-input') !== -1, + 'CSS contains subscribe-form-input styles'); +assert(cssContent.indexOf('.subscribe-form-button') !== -1, + 'CSS contains subscribe-form-button styles'); +assert(cssContent.indexOf('.subscribe-form-message.success') !== -1, + 'CSS contains success message styles'); +assert(cssContent.indexOf('.subscribe-form-message.error') !== -1, + 'CSS contains error message styles'); +assert(cssContent.indexOf('.subscribe-form-input:focus') !== -1, + 'CSS contains focus styles for input'); +assert(cssContent.indexOf('.subscribe-form-button:hover') !== -1, + 'CSS contains hover styles for button'); +assert(cssContent.indexOf('.subscribe-form-button:disabled') !== -1, + 'CSS contains disabled styles for button'); +assert(cssContent.indexOf(':is(.dark) .subscribe-form-input') !== -1, + 'CSS contains dark mode styles for input'); +assert(cssContent.indexOf(':is(.dark) .subscribe-form-button') !== -1, + 'CSS contains dark mode styles for button'); +assert(cssContent.indexOf('.subscribe-form-row') !== -1, + 'CSS contains flex row layout for form'); + +// --------------------------------------------------------------------------- +// Summary +// --------------------------------------------------------------------------- + +console.log('\n--- Results ---'); +console.log('Passed: ' + passed); +console.log('Failed: ' + failed); + +if (failed > 0) { + process.exit(1); +} diff --git a/fern/customization/custom-keywords.mdx b/fern/customization/custom-keywords.mdx index 6c88d4691..0fb5e0a0f 100644 --- a/fern/customization/custom-keywords.mdx +++ b/fern/customization/custom-keywords.mdx @@ -1,11 +1,13 @@ --- -title: Custom Keywords -subtitle: Enhanced transcription accuracy guide +title: Keywords and keyterm prompting +subtitle: Boost STT accuracy for domain words and phrases slug: customization/custom-keywords --- -Vapi allows you to improve the accuracy of your transcriptions by leveraging Deepgram's keyword boosting feature. This is particularly useful when dealing with specialized terminology or uncommon proper nouns. By providing specific keywords to the Deepgram model, you can enhance transcription quality directly through Vapi. +Vapi allows you to improve the accuracy of your transcriptions by leveraging keyword boosting and keyterm prompting. This is particularly useful when dealing with specialized terminology or uncommon proper nouns. Both [Deepgram](#deepgram-keywords-and-keyterm-prompting) and [AssemblyAI](#assemblyai-keyterms-prompting) transcribers support this through Vapi. + +## Deepgram keywords and keyterm prompting ### Why Use Keyword Boosting? @@ -18,21 +20,25 @@ Keyword boosting is beneficial for: ### Important Notes - Keywords should be uncommon words or proper nouns not frequently recognized by the model. -- Custom model training is the most effective way to ensure accurate keyword recognition. -- For more than 50 keywords, consider custom model training by contacting Deepgram. +- Use single words for `keywords` (no spaces or punctuation). For multi-word phrases, use `keyterm` instead. +- Custom model training is the most effective way to ensure accurate keyword recognition when you need extensive vocabulary coverage. + +### Model support -## Enabling Keyword Boosting in Vapi +- Keywords is available on Deepgram Nova-2, Nova-1, Enhanced, and Base speech-to-text models. +- For Nova-3 models, use Keyterm Prompting instead of Keywords. -### API Call Integration +### Enabling Keyword Boosting in Vapi -To enable keyword boosting, you need to add a `keywords` parameter to your Vapi assistant's transcriber section. This parameter should include the keywords and their respective intensifiers. +#### API Call Integration + +To enable keyword boosting, add the `keywords` parameter to your assistant's `transcriber` configuration when using the Deepgram provider. You can also supply `keyterm` to boost recall for phrases. ### Example of POST Request To create an assistant with keyword boosting enabled, you can make the following POST request to Vapi: ```bash -bashCopy code curl \ --request POST \ --header 'Authorization: Bearer ' \ @@ -40,27 +46,33 @@ curl \ --data '{ "name": "Emma", "model": { - "model": "gpt-4o", - "provider": "openai" + "model": "gpt-4o", + "provider": "openai" }, "voice": { - "voiceId": "emma", - "provider": "azure" + "voiceId": "emma", + "provider": "azure" }, "transcriber": { - "provider": "deepgram", - "model": "nova-2", - "language": "bg", - "smartFormat": true, - "keywords": [ - "snuffleupagus:1" - ] + "provider": "deepgram", + "model": "nova-2", + "language": "en", + "smartFormat": true, + "keywords": [ + "snuffleupagus:5", + "systrom", + "krieger" + ], + "keyterm": [ + "order number", + "account ID", + "PCI compliance" + ] }, "firstMessage": "Hi, I am Emma, what is your name?", "firstMessageMode": "assistant-speaks-first" }' \ https://api.vapi.ai/assistant - ``` In this configuration: @@ -68,28 +80,85 @@ In this configuration: - **name**: The name of the assistant. - **model**: Specifies the model and provider for the assistant's conversational capabilities. - **voice**: Specifies the voice and provider for the assistant's speech. -- **transcriber**: Specifies Deepgram as the transcription provider, along with the model, language, smart formatting, and keywords for boosting. +- **transcriber**: Specifies Deepgram as the transcription provider, along with the model, language, smart formatting, and both `keywords` (single words) and `keyterm` (phrases) for boosting. - **firstMessage**: The initial message the assistant will speak. - **firstMessageMode**: Specifies that the assistant speaks first. -### Intensifiers +### Format and intensifiers -Intensifiers are exponential factors that boost or suppress the likelihood of the specified keyword being recognized. The default intensifier is `1`. Higher values increase the likelihood, while `0` is equivalent to not specifying a keyword. +The `keywords` array accepts single-word tokens consisting of letters and digits, with an optional integer intensifier after a colon: + +- Accepted forms: `apple`, `apple:3`, `apple:-2` +- Not accepted: `order number` (use `keyterm`), `hello-world`, `foo_bar`, `rate:1.5` (decimals are not supported by this schema) + +Intensifiers are exponential factors that boost or suppress the likelihood of the specified keyword being recognized. The default intensifier is `1`. Higher values increase the likelihood, while `0` is equivalent to not specifying a keyword. Negative values suppress recognition. - **Boosting Example:** `keywords=snuffleupagus:5` - **Suppressing Example:** `keywords=kansas:-10` -### Best Practices for Keyword Boosting +### Keyterm prompting (phrases) + +Deepgram's Keyterm Prompting improves Keyword Recall Rate (KRR) for important keyterms or phrases. Use `keyterm` for multi‑word phrases you want the model to detect more reliably. Unlike `keywords`, keyterms are specified as plain strings without intensifiers. + +Example: `"keyterm": ["account number", "confirmation code", "HIPAA compliance"]` -1. **Send Uncommon Keywords:** Focus on keywords not successfully transcribed by the model. -2. **Send Keywords Once:** Avoid repeating keywords. -3. **Use Individual Keywords:** Prefer individual terms over phrases. -4. **Use Proper Spelling:** Spell proper nouns as you want them to appear in transcripts. -5. **Moderate Intensifiers:** Start with small increments to avoid false positives. -6. **Custom Model Training:** For extensive vocabulary needs, consider custom model training. +### Best Practices for Keyword and Keyterm Boosting + +1. **Start small:** Begin without any boosting; add keywords/keyterms only where needed. +2. **Send uncommon words:** Focus on proper nouns or domain terms the model often misses. +3. **Use `keywords` for single words; `keyterm` for phrases:** Avoid spaces in `keywords`. +4. **Avoid duplicates:** Send each keyword once; duplicates don't improve results. +5. **Moderate intensifiers:** Use minimal integer boosts to reduce false positives; increase cautiously. +6. **Correct spelling/casing:** Provide the spelling and capitalization you want in transcripts. +7. **Consider custom models:** For extensive vocabularies, consider custom model training with Deepgram. ### Additional Resources -For more detailed information on Deepgram's keyword boosting feature, refer to the Deepgram Keyword Boosting Documentation. +For more details, see: + +- Deepgram Keywords: [developers.deepgram.com/docs/keywords](https://developers.deepgram.com/docs/keywords) +- Deepgram Keyterm Prompting: [developers.deepgram.com/docs/keyterm](https://developers.deepgram.com/docs/keyterm) +- API reference: Deepgram transcriber `keywords` and `keyterm` in the [API reference](https://api.vapi.ai/api#:~:text=DeepgramTranscriber) + +By following these guidelines, you can effectively utilize Deepgram's keyword boosting feature within your Vapi assistant, ensuring enhanced transcription accuracy for specialized terminology and uncommon proper nouns. + +## AssemblyAI keyterms prompting + +AssemblyAI's Universal-Streaming keyterms prompting boosts recognition of domain-specific words and phrases. Add the `keytermsPrompt` parameter to your assistant's `transcriber` configuration when using the `assembly-ai` provider. + +- Up to 100 keyterms per session, each up to 50 characters. +- Keyterms can be single words or multi-word phrases — no intensifiers needed. +- Supported with the `universal-streaming-english` and `universal-3-5-pro` speech models. Not supported with `universal-streaming-multilingual`. +- Keyterms prompting adds $0.04/hour to transcription cost on `universal-streaming-english`. + +### Example + +```bash +curl \ + --request POST \ + --header 'Authorization: Bearer ' \ + --header 'Content-Type: application/json' \ + --data '{ + "name": "Emma", + "model": { + "model": "gpt-4o", + "provider": "openai" + }, + "transcriber": { + "provider": "assembly-ai", + "speechModel": "universal-streaming-english", + "keytermsPrompt": [ + "order number", + "account ID", + "PCI compliance" + ] + }, + "firstMessage": "Hi, I am Emma, what is your name?" + }' \ + https://api.vapi.ai/assistant +``` + +### Additional resources -By following these guidelines, you can effectively utilize Deepgram's keyword boosting feature within your Vapi assistant, ensuring enhanced transcription accuracy for specialized terminology and uncommon proper nouns. \ No newline at end of file +- AssemblyAI Keyterms Prompting: [AssemblyAI's prompting and keyterms guide](https://www.assemblyai.com/docs/streaming/prompting-and-keyterms) +- API reference: [`AssemblyAITranscriber` fields](/api-reference/assistants/create#request.body.transcriber.AssemblyAITranscriber) diff --git a/fern/customization/custom-llm/using-your-server.mdx b/fern/customization/custom-llm/using-your-server.mdx index 4f5bb6ef9..65e25a5cf 100644 --- a/fern/customization/custom-llm/using-your-server.mdx +++ b/fern/customization/custom-llm/using-your-server.mdx @@ -58,7 +58,7 @@ Log in to your Vapi account and navigate to the "Model" section. Choose the "Custom LLM" option to set up the integration. **3. Enter Ngrok URL:** -Paste the public URL generated by ngrok (e.g., https://your-unique-id.ngrok.io) into the endpoint field. This will be the URL Vapi uses to communicate with your local server. +Paste the public URL generated by ngrok (for example, `https://your-unique-id.ngrok.io`) into the endpoint field. This will be the URL Vapi uses to communicate with your local server. **4. Test the Connection:** Send a test message through the Vapi interface to ensure it reaches your local server and receives a response from the OpenAI API. Verify that the response is displayed correctly in Vapi. @@ -134,4 +134,4 @@ By following these detailed steps and understanding the communication flow, you width="100%" height="400px" allowfullscreen - /> \ No newline at end of file + /> diff --git a/fern/customization/custom-transcriber.mdx b/fern/customization/custom-transcriber.mdx index 6157c8e82..36162c8d3 100644 --- a/fern/customization/custom-transcriber.mdx +++ b/fern/customization/custom-transcriber.mdx @@ -5,7 +5,7 @@ slug: customization/custom-transcriber --- ## Overview -A custom transcriber lets you use your own transcription service with Vapi, instead of a built-in provider. This is useful if you need more control, want to use a specific provider like Deepgram, or have custom processing needs. +A custom transcriber lets you use your own transcription service with Vapi, instead of a built-in provider. This is useful if you need more control, want to use a specific provider like Deepgram, Cartesia Ink-2, or have custom processing needs. This guide shows you how to set up Deepgram as your custom transcriber. The same approach can be adapted for other providers. @@ -43,14 +43,22 @@ You'll learn how to: Your server forwards the audio to Deepgram (or your chosen transcriber) using its SDK. Deepgram processes the audio and returns transcript events that include a `channel_index` (e.g. `[0, ...]` for customer, `[1, ...]` for assistant). The service buffers the incoming data, processes the transcript events (with debouncing and channel detection), and emits a final transcript. - The final transcript is sent back to Vapi as a JSON message: + The transcript is sent back to Vapi as a JSON message: ```json { "type": "transcriber-response", "transcription": "The transcribed text", - "channel": "customer" // or "assistant" + "channel": "customer", + "transcriptType": "final" } ``` + + The optional `transcriptType` field controls how Vapi handles the transcript: + + - **`"final"`** (default) — the transcription is definitive. + - **`"partial"`** — the transcription is provisional and may be superseded by a later message. Each partial replaces the previous one until a `"final"` arrives. + + If omitted, `transcriptType` defaults to `"final"` for backward compatibility. @@ -362,6 +370,7 @@ You'll learn how to: type: "transcriber-response", transcription: text, channel, + transcriptType: "final", }; ws.send(JSON.stringify(response)); logger.logDetailed("INFO", "Sent transcription to client", "Server", { @@ -408,9 +417,9 @@ You'll learn how to: "transcriber": { "provider": "custom-transcriber", "server": { - "url": "wss://your-server.ngrok.io/api/custom-transcriber" - }, - "secret": "your_optional_secret_value" + "url": "wss://your-server.ngrok.io/api/custom-transcriber", + "credentialId": "cred_transcriber_auth_123" + } }, "firstMessage": "Hello! I am using a custom transcriber with Deepgram." }, @@ -423,12 +432,13 @@ You'll learn how to: - The `"start"` message initializes the Deepgram session. - PCM audio data is forwarded to Deepgram. - Deepgram returns transcript events, which are processed with channel detection and debouncing. - - The final transcript is sent back as a JSON message: + - The transcript is sent back as a JSON message: ```json { "type": "transcriber-response", "transcription": "The transcribed text", - "channel": "customer" // or "assistant" + "channel": "customer", + "transcriptType": "final" } ``` @@ -438,12 +448,14 @@ You'll learn how to: - **Streaming support requirement:** The custom transcriber must support streaming. Vapi sends continuous audio data over the WebSocket, and your server must handle this stream in real time. -- **Secret header:** - The custom transcriber configuration accepts an optional field called **`secret`**. When set, Vapi will send this value with every request as an HTTP header named `x-vapi-secret`. This can also be configured via a headers field. +- **Authentication:** + For secure transcriber endpoints, use **Custom Credentials** with `credentialId`. Create [Custom Credentials](../../server-url/server-authentication) in the dashboard to manage Bearer Token, OAuth 2.0, or HMAC authentication. For backward compatibility, the legacy `secret` field is still supported and sends the value as an `x-vapi-secret` HTTP header. - **Buffering:** The solution buffers PCM audio and performs simple validation (e.g. ensuring stereo PCM data length is a multiple of 4). If the audio data is malformed, it is trimmed to a valid length. - **Channel detection:** Transcript events from Deepgram include a `channel_index` array. The service uses the first element to determine whether the transcript is from the customer (`0`) or the assistant (`1`). Ensure Deepgram's response format remains consistent with this logic. +- **Partial transcripts:** + Set `transcriptType` to `"partial"` to send progressive transcription updates. Each partial supersedes the previous one until a `"final"` message arrives. This is useful for STT providers that emit fast, low-latency partials that get refined over time (e.g. ElevenLabs Scribe). If `transcriptType` is omitted, Vapi treats the message as `"final"`. --- diff --git a/fern/customization/custom-transcriber/gradium.mdx b/fern/customization/custom-transcriber/gradium.mdx new file mode 100644 index 000000000..02c6618de --- /dev/null +++ b/fern/customization/custom-transcriber/gradium.mdx @@ -0,0 +1,57 @@ +--- +title: Gradium +subtitle: Use Gradium speech-to-text as a custom transcriber in Vapi +description: Stream Vapi call audio to Gradium's real-time speech-to-text over a WebSocket bridge. +slug: customization/custom-transcriber/gradium +--- + +[Gradium](https://gradium.ai) builds real-time audio models, including streaming speech-to-text with semantic voice activity detection. You can connect it through a [custom transcriber](/customization/custom-transcriber) endpoint: a small WebSocket bridge that forwards call audio to Gradium and returns transcripts to Vapi. + +A Gradium account and API key are required. + + + + Gradium's [Vapi integration guide](https://docs.gradium.ai/integrations/agent-frameworks/vapi) has the complete bridge, including end-of-turn detection and reconnecting on long calls. + + Two things matter most: forward **only channel 0** of the interleaved audio, or the agent transcribes its own speech; and send `partial` transcripts as well as `final` ones, which Vapi needs for barge-in. + + + Host the bridge somewhere Vapi can reach over `wss`, then reference it with + a [custom credential](/server-url/server-authentication) so Vapi can + authenticate to it: + + ```json + { + "transcriber": { + "provider": "custom-transcriber", + "server": { + "url": "wss://your-server.com/vapi/transcriber", + "credentialId": "cred_transcriber_auth_123" + } + } + } + ``` + + Start a call and your assistant transcribes with Gradium. + + + +## Troubleshooting + +| Symptom | Fix | +| --- | --- | +| The agent transcribes its own speech | Both channels are being forwarded. Send only channel 0 from the interleaved PCM | +| Turns get swallowed, barge-in stops working | Send `partial` transcripts as well as `final` | +| Final transcripts lose the last word or two | Finalize on Gradium's flush acknowledgement, not on the VAD threshold crossing. See [Gradium's Vapi guide](https://docs.gradium.ai/integrations/agent-frameworks/vapi) | +| The assistant replies before the caller finishes | Vapi's endpointing is racing Gradium's VAD. Tune [start and stop speaking plans](/customization/voice-pipeline-configuration), or hand the decision to Gradium with a [custom endpointing model](https://docs.gradium.ai/integrations/agent-frameworks/vapi) | + +## Related + + + + The full bridge, tuning, and configuration reference. + + + Use Gradium voices as a custom voice. + + diff --git a/fern/customization/custom-tts.mdx b/fern/customization/custom-tts.mdx index b12264f6c..fc7903ad0 100644 --- a/fern/customization/custom-tts.mdx +++ b/fern/customization/custom-tts.mdx @@ -53,20 +53,20 @@ VAPI's custom TTS system operates through a webhook pattern: ## Authentication setup -VAPI needs secure communication with your TTS endpoint. Choose from these authentication options: +VAPI needs secure communication with your TTS endpoint. Use **Custom Credentials** for authentication: -### Secret header authentication +### Using Custom Credentials (Recommended) -The most common approach uses a secret token in the `X-VAPI-SECRET` header: +Create authentication credentials in the dashboard and reference them by ID: -```json title="Assistant Configuration" +```json title="Assistant Configuration with Custom Credentials" { "voice": { "provider": "custom-voice", "server": { "url": "https://your-tts-api.com/synthesize", - "secret": "your-secret-token-here", + "credentialId": "cred_tts_auth_123", "timeoutSeconds": 30 } } @@ -74,9 +74,13 @@ The most common approach uses a secret token in the `X-VAPI-SECRET` header: ``` -### Enhanced authentication with custom headers + +Create [Custom Credentials](../../server-url/server-authentication) in the Vapi dashboard for better security and credential management. + + +### Legacy Authentication Methods -Add extra headers for API versioning or enhanced security: +For backward compatibility, you can still use inline authentication: ```json title="Assistant Configuration with Custom Headers" diff --git a/fern/customization/custom-tts/gradium.mdx b/fern/customization/custom-tts/gradium.mdx new file mode 100644 index 000000000..1db0ec544 --- /dev/null +++ b/fern/customization/custom-tts/gradium.mdx @@ -0,0 +1,56 @@ +--- +title: Gradium +subtitle: Use Gradium text-to-speech as a custom voice in Vapi +description: Connect the Gradium text-to-speech API to Vapi through a custom voice endpoint. +slug: customization/custom-tts/gradium +--- + +[Gradium](https://gradium.ai) builds real-time audio models, including streaming text-to-speech with instant voice cloning. You connect it through a [custom voice](/customization/custom-voices/custom-tts) endpoint: a small server that receives the text Vapi wants spoken and streams raw PCM back. + +A Gradium account and API key are required. + + + + Gradium's [Vapi integration guide](https://docs.gradium.ai/integrations/agent-frameworks/vapi) has the complete endpoint, including the SDK setup and streaming loop. + + Read `message.sampleRate` on each request and synthesize at that rate. Vapi expects raw 16-bit little-endian mono PCM at exactly the rate it asked for, streamed as it is produced. + + + Host the endpoint somewhere Vapi can reach over HTTPS, then reference it + with a [custom credential](/server-url/server-authentication) so Vapi can + authenticate to it: + + ```json + { + "voice": { + "provider": "custom-voice", + "server": { + "url": "https://your-server.com/vapi/tts", + "credentialId": "cred_tts_auth_123" + } + } + } + ``` + + Start a call and your assistant speaks with your Gradium voice. + + + +## Troubleshooting + +| Symptom | Fix | +| --- | --- | +| Audio plays at the wrong speed or pitch | Synthesize at the rate in `message.sampleRate`, and return mono 16-bit little-endian PCM with no WAV header | +| Voice or pronunciation edits don't take effect | Vapi caches custom voice audio. Set `"cachingEnabled": false` on the `voice` object while iterating | +| Long pause before the first word | A new connection per sentence. Pool them as shown in [Gradium's Vapi guide](https://docs.gradium.ai/integrations/agent-frameworks/vapi) | + +## Related + + + + The full endpoint, tuning, and configuration reference. + + + Use Gradium as a custom transcriber. + + diff --git a/fern/customization/custom-voices/cartesia.mdx b/fern/customization/custom-voices/cartesia.mdx new file mode 100644 index 000000000..90034880c --- /dev/null +++ b/fern/customization/custom-voices/cartesia.mdx @@ -0,0 +1,27 @@ +--- +title: Cartesia +subtitle: Set up a custom Cartesia voice in Vapi +description: Use a custom Cartesia voice in Vapi by connecting your Cartesia API key and selecting your voice. +slug: customization/custom-voices/cartesia +--- + +This guide shows you how to use a voice you created with Cartesia in your Vapi assistant. Cartesia's prebuilt voices are already available in the [Voice Library](/providers/voice/overview); follow this page only to use your own custom voice. + +A Cartesia account and API key are required for this process. + + + + Sign up at [Cartesia](https://play.cartesia.ai), then create a custom voice in the [Cartesia playground](https://play.cartesia.ai/voices). Note that you will need to set the access of the voice to public in Cartesia to use it in Vapi. [Check their docs](https://docs.cartesia.ai/build-with-cartesia/capability-guides/choosing-a-voice#sharing-a-voice) for more information. + + + Get your API key from your Cartesia account. + + + In the [Vapi Dashboard](https://dashboard.vapi.ai), open **Settings**, then **Integrations**, and add your Cartesia API key under **Cartesia**. + + Once you save, your Cartesia voices sync automatically. + + + Open an assistant and open **Voice Settings**. Choose **Cartesia** as the provider and select your voice, or switch to **Custom Voice ID** and paste your Cartesia voice ID. You can find your voice ID in the [Voice Library](/providers/voice/overview). + + diff --git a/fern/customization/custom-voices/elevenlabs.mdx b/fern/customization/custom-voices/elevenlabs.mdx index 0c5c78e1f..664e5e994 100644 --- a/fern/customization/custom-voices/elevenlabs.mdx +++ b/fern/customization/custom-voices/elevenlabs.mdx @@ -16,7 +16,7 @@ This guide outlines the procedure for integrating your cloned voice with ElevenL Go to the 'Profile + Keys' section on the ElevenLabs website to get your API key. - Navigate to the [Vapi Provider Key section](https://dashboard.vapi.ai/keys) and input your ElevenLabs API key under the ElevenLabs section. + Navigate to the [Vapi Integrations section](https://dashboard.vapi.ai/settings/integrations) and input your ElevenLabs API key under the ElevenLabs section. Once you click save, your voice library will sync automatically. diff --git a/fern/customization/custom-voices/gandr.mdx b/fern/customization/custom-voices/gandr.mdx new file mode 100644 index 000000000..42729f5a4 --- /dev/null +++ b/fern/customization/custom-voices/gandr.mdx @@ -0,0 +1,49 @@ +--- +title: Gandr +subtitle: Use Gandr voices in Vapi through the custom-voice provider +description: Wire Gandr, a text to speech API for voice agents, into Vapi with the custom-voice provider and Custom Credentials. +slug: customization/custom-voices/gandr +--- + +Gandr is a text to speech API built for voice agents. It reads numbers, dates, order IDs and addresses correctly, one engine speaks 23 languages with six voices, and every render carries an inaudible watermark. Audio streams back as it is generated. + +Gandr's `/v1/vapi` endpoint implements the custom-voice contract described in the [Custom TTS guide](/customization/custom-voices/custom-tts): it reads the nested `message` envelope, honours the requested `sampleRate` (8000, 16000, 22050, 24000 or 44100), and returns raw 16-bit little-endian mono PCM. + +A Gandr account and API key are required. + + + + Sign up at [gandr.ai](https://gandr.ai) and copy your API key. + + + In the [Vapi Dashboard](https://dashboard.vapi.ai), create a **Custom Credential** holding your Gandr key, following [server authentication](/server-url/server-authentication), so the key never travels in the assistant config. + + + In the assistant config, set the voice provider to `custom-voice` and point it at Gandr: + + ```json + { + "voice": { + "provider": "custom-voice", + "server": { + "url": "https://tts.gandr.ai/v1/vapi", + "credentialId": "", + "timeoutSeconds": 10 + } + } + } + ``` + + + Gandr's stock voices are `gandr-ava`, `gandr-dane`, `gandr-jenny`, `gandr-leo`, `gandr-lewis` and `gandr-mia`. The default is an English female voice. Any of the 23 languages can be set per request, independent of the voice. + + + Run a test call in the dashboard. If you hear audio, you are done. If the call times out, check that the Gandr key in the Custom Credential is active and that `https://tts.gandr.ai/v1/vapi` answers. + + + +## Pricing + +See [Gandr's pricing page](https://gandr.ai/pricing/) for current plan and usage pricing. + +Full API reference: [gandr.ai/docs](https://gandr.ai/docs). diff --git a/fern/customization/custom-voices/playht.mdx b/fern/customization/custom-voices/playht.mdx index 62f6f57d9..2dd2ba3d0 100644 --- a/fern/customization/custom-voices/playht.mdx +++ b/fern/customization/custom-voices/playht.mdx @@ -18,7 +18,7 @@ An API subscription is required for this process. Go to the [API Access section](https://play.ht/studio/api-access) on PlayHT to get your User ID and Secret Key. - Navigate to the [Vapi Provider Key section](https://dashboard.vapi.ai/keys) and add your PlayHT API keys under the PlayHT section. + Navigate to the [Vapi Integrations section](https://dashboard.vapi.ai/settings/integrations) and add your PlayHT API keys under the PlayHT section. From the [Voice Library](https://dashboard.vapi.ai/voice-library) in Vapi, select PlayHT as your voice provider and click on "Sync with PlayHT." diff --git a/fern/customization/custom-voices/tavus.mdx b/fern/customization/custom-voices/tavus.mdx index 8911fbf15..66650551d 100644 --- a/fern/customization/custom-voices/tavus.mdx +++ b/fern/customization/custom-voices/tavus.mdx @@ -18,7 +18,7 @@ An API subscription is required for this process. These steps are only needed fo Go to the [API Keys section](https://platform.tavus.io/api-keys) on Tavus to get your API key. - Navigate to the [Vapi Provider Key section](https://dashboard.vapi.ai/keys) and add your Tavus API key under the Tavus section. + Navigate to the [Vapi Integrations section](https://dashboard.vapi.ai/settings/integrations) and add your Tavus API key under the Tavus section. After adding your API key, select Tavus as your assistant's voice provider and add your Custom Replica ID manually through the dashboard. Alternatively, use the API and specify the replica ID in the `voiceId` field. diff --git a/fern/customization/multilingual.mdx b/fern/customization/multilingual.mdx index 07dc4c289..fe4dc192f 100644 --- a/fern/customization/multilingual.mdx +++ b/fern/customization/multilingual.mdx @@ -16,7 +16,7 @@ Configure your voice assistant to communicate in multiple languages with automat - Test and optimize multilingual performance -**Multilingual Support:** Multiple providers support automatic language detection. **Deepgram** (Nova 2, Nova 3 with "Multi" setting) and **Google STT** (with "Multilingual" setting) both offer automatic language detection for seamless multilingual conversations. +**Multilingual Support:** Multiple providers support automatic language detection. **Deepgram** (Nova 2, Nova 3 with "Multi" setting), **Google STT** (with "Multilingual" setting), and **Gladia** (automatic language detection) all offer seamless multilingual conversations. ## Configure automatic language detection @@ -28,10 +28,10 @@ Set up your transcriber to automatically detect and process multiple languages. 1. Navigate to **Assistants** in your [Vapi Dashboard](https://dashboard.vapi.ai/) 2. Create a new assistant or edit an existing one 3. In the **Transcriber** section: - - **Provider**: Select `Deepgram` (recommended) or `Google` - - **Model**: For Deepgram, choose `Nova 2` or `Nova 3`; for Google, choose `Latest` - - **Language**: Set to `Multi` (Deepgram) or `Multilingual` (Google) - 4. **Other providers**: Single language only, no automatic detection + - **Provider**: Select `Deepgram` (recommended), `Google`, or `Gladia` + - **Model**: For Deepgram, choose `Nova 2` or `Nova 3`; for Google, choose `Gemini 2.0 Flash`; for Gladia, choose `Solaria` + - **Language / Mode**: Set `Multi` (Deepgram), `Multilingual` (Google), or choose the language you want to transcribe (Gladia) + 4. **Other providers**: May require a single languages and not auto-detect 5. Click **Save** to apply the configuration @@ -53,8 +53,8 @@ Set up your transcriber to automatically detect and process multiple languages. // Alternative: Google for multilingual support const googleMultilingual = { provider: "google", - model: "latest", - language: "multilingual" + model: "gemini-2.0-flash", + language: "Multilingual" }; ``` @@ -78,8 +78,8 @@ Set up your transcriber to automatically detect and process multiple languages. # Alternative: Google for multilingual support google_multilingual = { "provider": "google", - "model": "latest", - "language": "multilingual" + "model": "gemini-2.0-flash", + "language": "Multilingual" } ``` @@ -105,8 +105,8 @@ Set up your transcriber to automatically detect and process multiple languages. -d '{ "transcriber": { "provider": "google", - "model": "latest", - "language": "multilingual" + "model": "gemini-2.0-flash", + "language": "Multilingual" } }' ``` @@ -114,7 +114,7 @@ Set up your transcriber to automatically detect and process multiple languages. -**Provider Performance:** **Deepgram** offers the best balance of speed and multilingual accuracy. **Google** provides broader language support but may be slower. Both providers support automatic language detection within conversations. +**Provider Performance:** **Deepgram** offers the best balance of speed and multilingual accuracy. **Google** provides broader language support but may be slower. **Gladia** offers excellent automatic language recognition and code-switching with strong accuracy reported by customers. All three support automatic language detection within conversations. ## Set up multilingual voices @@ -198,6 +198,21 @@ Configure your assistant to use appropriate voices for each detected language. + +Vapi Voices V2 can select the synthesis language automatically. Set `voice.provider` to `vapi`, `voice.version` to `2`, and `voice.language` to `auto`: + +```json +{ + "voice": { + "provider": "vapi", + "voiceId": "Elliot", + "version": 2, + "language": "auto" + } +} +``` + + **Voice Provider Support:** Unlike transcription, all major voice providers (Azure, ElevenLabs, OpenAI, etc.) support multiple languages. Azure offers the most comprehensive coverage with 400+ voices across 140+ languages. @@ -460,10 +475,10 @@ Validate your configuration with different languages and scenarios. |----------|---------------------|-----------|-------| | **Deepgram** | ✅ Full auto-detection | 100+ | **Recommended**: Nova 2/Nova 3 with "Multi" language setting | | **Google STT** | ✅ Full auto-detection | 125+ | Latest models with "Multilingual" language setting | -| **Assembly AI** | ❌ English only | English | No multilingual support | +| **Gladia** | ✅ Full auto-detection | 110+ | Supports automatic language detection and code-switching | +| **AssemblyAI** | ✅ Full auto-detection | 18 | Set `speechModel` to `universal-3-5-pro` for automatic language detection and code-switching | | **Azure STT** | ❌ Single language | 100+ | Many languages, but no auto-detection | | **OpenAI Whisper** | ❌ Single language | 90+ | Many languages, but no auto-detection | -| **Gladia** | ❌ Single language | 80+ | Many languages, but no auto-detection | | **Speechmatics** | ❌ Single language | 50+ | Many languages, but no auto-detection | | **Talkscriber** | ❌ Single language | 40+ | Many languages, but no auto-detection | @@ -471,6 +486,7 @@ Validate your configuration with different languages and scenarios. | Provider | Languages | Multilingual Voice Selection | Best For | |----------|-----------|------------------------------|----------| +| **Vapi** | 40+ | ✅ Automatic | Curated voices with built-in language detection | | **Azure** | 140+ | ✅ Automatic | Maximum language coverage | | **ElevenLabs** | 30+ | ✅ Automatic | Premium voice quality | | **OpenAI TTS** | 50+ | ✅ Automatic | Consistent quality across languages | @@ -481,7 +497,7 @@ Validate your configuration with different languages and scenarios. **Solutions:** - - Use Deepgram (Nova 2/Nova 3 with "Multi") or Google STT (with "Multilingual") + - Use AssemblyAI Universal 3.5 Pro (`speechModel: "universal-3-5-pro"`), Deepgram (Nova 2/Nova 3 with "Multi"), Google STT (with "Multilingual"), or Gladia (automatic language detection) - Ensure high-quality audio input for better detection accuracy - Test with native speakers of target languages - Consider provider-specific language combinations for optimal results @@ -516,7 +532,7 @@ Validate your configuration with different languages and scenarios. Now that you have multilingual support configured: -- **[Build a complete multilingual agent](../assistants/examples/multilingual-agent):** Follow our step-by-step implementation guide -- **[Custom voices](custom-voices/custom-voice):** Set up region-specific custom voices -- **[System prompting](../prompting-guide):** Design effective multilingual prompts -- **[Call analysis](../call-analysis):** Monitor language performance and usage +- **[Build a complete multilingual agent](/assistants/examples/multilingual-agent):** Follow our step-by-step implementation guide +- **[Custom voices](/customization/custom-voices/custom-voice):** Set up region-specific custom voices +- **[System prompting](/prompting-guide):** Design effective multilingual prompts +- **[Call analysis](/assistants/call-analysis):** Monitor language performance and usage diff --git a/fern/customization/provider-keys.mdx b/fern/customization/provider-keys.mdx index 7ca102ef4..a19ffa68d 100644 --- a/fern/customization/provider-keys.mdx +++ b/fern/customization/provider-keys.mdx @@ -1,29 +1,28 @@ --- title: Provider Keys subtitle: Bring your own API keys to Vapi. +description: Connect provider credentials in Vapi and find configuration details for transcriber, model, voice, and cloud providers. slug: customization/provider-keys --- Have a custom model or voice with one of the providers? Or an enterprise account with volume pricing? -No problem! You can bring your own API keys to Vapi. You can add them in the [Dashboard](https://dashboard.vapi.ai) under the **Provider Keys** tab. Once your API key is validated, you won't be charged when using that provider through Vapi. Instead, you'll be charged directly by the provider. +No problem! You can bring your own API keys to Vapi. You can add them in the [Dashboard](https://dashboard.vapi.ai) under the **Integrations** tab. Once your API key is validated, you won't be charged when using that provider through Vapi. Instead, you'll be charged directly by the provider. ## Transcription Providers -Currently, the only available transcription provider is `deepgram`. To use a custom model, you can specify the deepgram model ID in the `transcriber.model` parameter of the [Assistant](/api-reference/assistants/create-assistant). +Choose the provider and its supported options in the assistant's `transcriber` configuration. See [Transcriber providers](/providers/transcriber/overview) and the [`transcriber` configuration](/api-reference/assistants/create#request.body.transcriber) in the API reference. ## Model Providers -We are currently have support for any OpenAI-compatible endpoint. This includes services like [OpenRouter](https://openrouter.ai/), [AnyScale](https://www.anyscale.com/), [Together AI](https://www.together.ai/), or your own server. +Choose the provider and model in the assistant's `model` configuration. See [Model providers](/providers/model/overview) and the [`model` configuration](/api-reference/assistants/create#request.body.model) in the API reference. -To use one of these providers, you can specify the `provider` and `model` in the `model` parameter of the [Assistant](/api-reference/assistants/create-assistant). - -You can find more details in the [Custom LLMs](/customization/custom-llm/fine-tuned-openai-models) section of the documentation. +For an OpenAI-compatible endpoint that is not represented by a native provider, see [Custom LLMs](/customization/custom-llm/using-your-server). ## Voice Providers -All voice providers are supported. Once you've validated your API through the [Dashboard](https://dashboard.vapi.ai), any voice ID from your provider can be used in the `voice.voiceId` field of the [Assistant](/api-reference/assistants/create-assistant). +Choose the provider, voice ID, and supported options in the assistant's `voice` configuration. See [Voice providers](/providers/voice/overview) and the [`voice` configuration](/api-reference/assistants/create#request.body.voice) in the API reference. ## Cloud Providers @@ -33,6 +32,6 @@ Cloudflare R2. You can find more details on how to configure your Cloud Provider keys here: - * [AWS S3](/providers/cloud/s3) - * [GCP Cloud Storage](/providers/cloud/gcp) - * [Cloudflare R2](/providers/cloud/cloudflare) +- [AWS S3](/providers/cloud/s3) +- [Google Cloud Storage](/providers/cloud/gcp) +- [Cloudflare R2](/providers/cloud/cloudflare) diff --git a/fern/customization/speech-configuration.mdx b/fern/customization/speech-configuration.mdx index 60957d958..3f8f4c8e7 100644 --- a/fern/customization/speech-configuration.mdx +++ b/fern/customization/speech-configuration.mdx @@ -6,32 +6,56 @@ slug: customization/speech-configuration ## Overview -Speech configuration lets you control exactly when your assistant starts and stops speaking during a conversation. By tuning these settings, you can make your assistant feel more natural, avoid interrupting the customer, and reduce awkward pauses. +Speech configuration lets you control exactly when your assistant starts and stops speaking during a conversation. By tuning these settings, you can make your assistant feel more natural, avoid interrupting the customer, and reduce awkward pauses. -Speech speed can be controlled, but only PlayHT currently supports this feature with the `speed` field. Other providers do not currently support speed. + Speech speed can be controlled, but only PlayHT currently supports this + feature with the `speed` field. Other providers do not currently support + speed. The two main components are: + - **Speaking Plan**: Controls when the assistant begins speaking after the customer finishes or pauses. - **Stop Speaking Plan**: Controls when the assistant stops speaking if the customer starts talking. -Fine-tuning these plans helps you adapt the assistant's responsiveness to your use case—whether you want fast, snappy replies or a more patient, human-like conversation flow. - - -Currently, these configurations can only be set via API. - +Fine-tuning these plans helps you adapt the assistant's responsiveness to your use case—whether you want fast, snappy replies or a more patient, human-like conversation flow. The rest of this page explains each setting and provides practical examples for different scenarios. ## Start Speaking Plan + This plan defines the parameters for when the assistant begins speaking after the customer pauses or finishes. - **Wait Time Before Speaking**: You can set how long the assistant waits before speaking after the customer finishes. The default is 0.4 seconds, but you can increase it if the assistant is speaking too soon, or decrease it if there's too much delay. -**Example:** For tech support calls, set `waitSeconds` for the assistant to more than 1.0 seconds to give customers time to complete their thoughts, even if they have some pauses in between. + **Example:** For tech support calls, set `waitSeconds` for the assistant to more than 1.0 seconds to give customers time to complete their thoughts, even if they have some pauses in between. + +- **Smart Endpointing Plan**: This feature uses advanced processing to detect when the customer has truly finished speaking, especially if they pause mid-thought. + + In general, turn-taking includes the following tasks: + + - **End-of-turn prediction** - predicting when the current speaker is likely to finish their turn. + - **Backchannel prediction** - detecting moments where a listener may provide short verbal acknowledgments like "uh-huh", "yeah", etc. to show engagement, without intending to take over the speaking turn. This is better handled by the assistant's stopSpeakingPlan. + + We offer different providers that can be audio-based, text-based, or audio-text based: + + **Audio-based providers:** + + - **Krisp**: Audio-based model that analyzes prosodic and acoustic features such as changes in intonation, pitch, and rhythm to detect when users finish speaking. Since it's audio-based, it always notifies when the user is done speaking, even for brief acknowledgments. Vapi offers configurable acknowledgement words and a well-configured stop speaking plan to handle this properly. + + Configure Krisp with a threshold between 0 and 1 (default 0.5), where 1 means the user definitely stopped speaking and 0 means they're still speaking. Use lower values for snappier conversations and higher values for more conservative detection. -- **Smart Endpointing Plan**: This feature uses advanced processing to detect when the customer has truly finished speaking, especially if they pause mid-thought. It can be configured in three ways: - - **Off**: Disabled by default + When interacting with an AI agent, users may genuinely want to interrupt to ask a question or shift the conversation, or they might simply be using backchannel cues like "right" or "okay" to signal they're actively listening. The core challenge lies in distinguishing meaningful interruptions from casual acknowledgments. Since the audio-based model signals end-of-turn after each word, configure the stop speaking plan with the right number of words to interrupt, interruption settings, and acknowledgement phrases to handle backchanneling properly. + + **Audio-text based providers:** + + - **Deepgram Flux**: Deepgram's latest transcriber model with built-in conversational speech recognition. Flux combines high-quality speech-to-text with native turn detection, while delivering ultra-low latency and Nova-3 level accuracy. Available in English (`flux-general-en`) and multilingual (`flux-general-multi`) variants. See [Deepgram's supported languages](/providers/transcriber/deepgram#supported-languages) for the current model and language combinations. + + - **Assembly**: Transcriber that also reports end-of-turn detection. To use Assembly, choose it as your transcriber without setting a separate smart endpointing plan. As transcripts arrive, we consider the `end_of_turn` flag that Assembly sends to mark the end-of-turn, stream to the LLM, and generate a response. + + **Text-based providers:** + + - **Off**: Disabled by default. When smart endpointing is set to "Off", the system will automatically use the transcriber's end-of-turn detection if available. If no transcriber EOT detection is available, the system defaults to LiveKit if the language is set to English or to Vapi's standard endpointing mode. - **LiveKit**: Recommended for English conversations as it provides the most sophisticated solution for detecting natural speech patterns and pauses. LiveKit can be fine-tuned using the `waitFunction` parameter to adjust response timing based on the probability that the user is still speaking. - **Vapi**: Recommended for non-English conversations or as an alternative when LiveKit isn't suitable @@ -39,32 +63,31 @@ This plan defines the parameters for when the assistant begins speaking after th **LiveKit Smart Endpointing Configuration:** When using LiveKit, you can customize the `waitFunction` parameter which determines how long the bot will wait to start speaking based on the likelihood that the user has finished speaking: - + ``` waitFunction: "200 + 8000 * x" ``` - + This function maps probabilities (0-1) to milliseconds of wait time. A probability of 0 means high confidence the caller has stopped speaking, while 1 means high confidence they're still speaking. The default function (`200 + 8000 * x`) creates a wait time between 200ms (when x=0) and 8200ms (when x=1). You can customize this with your own mathematical expression, such as `4000 * (1 - cos(pi * x))` for a different response curve. **Example:** In insurance claims, smart endpointing helps avoid interruptions while customers think through complex responses. For instance, when the assistant asks "do you want a loan," the system can intelligently wait for the complete response rather than interrupting after the initial "yes" or "no." For responses requiring number sequences like "What's your account number?", the system can detect natural pauses between digits without prematurely ending the customer's turn to speak. -- **Transcription-Based Detection**: Customize how the assistant determines that the customer has stopped speaking based on what they're saying. This offers more control over the timing. **Example:** When a customer says, "My account number is 123456789, I want to transfer $500." +- **Transcription-Based Detection**: Customize how the assistant determines that the customer has stopped speaking based on what they're saying. This offers more control over the timing. **Example:** When a customer says, "My account number is 123456789, I want to transfer $500." - The system detects the number "123456789" and waits for 0.5 seconds (`WaitSeconds`) to ensure the customer isn't still speaking. - If the customer were to finish with an additional line, "I want to transfer $500.", the system uses `onPunctuationSeconds` to confirm the end of the speech and then proceed with the request processing. - - In a scenario where the customer has been silent for a long and has already finished speaking but the transcriber is not confident to punctuate the transcription, `onNoPunctuationSeconds` is used for 1.5 seconds. - + - In a scenario where the customer has been silent for a long time and has already finished speaking but the transcriber is not confident to punctuate the transcription, `onNoPunctuationSeconds` is used for 1.5 seconds. ## Stop Speaking Plan + The Stop Speaking Plan defines when the assistant stops talking after detecting customer speech. - **Words to Stop Speaking**: Define how many words the customer needs to say before the assistant stops talking. If you want immediate reaction, set this to 0. Increase it to avoid interruptions by brief acknowledgments like "okay" or "right". **Example:** While setting an appointment with a clinic, set `numWords` to 2-3 words to allow customers to finish brief clarifications without triggering interruptions. - **Voice Activity Detection**: Adjust how long the customer needs to be speaking before the assistant stops. The default is 0.2 seconds, but you can tweak this to balance responsiveness and avoid false triggers. -**Example:** For a banking call center, setting a higher `voiceSeconds` value ensures accuracy by reducing false positives. This avoids interruptions caused by background sounds, even if it slightly delays the detection of speech onset. This tradeoff is essential to ensure the assistant processes only correct and intended information. - + **Example:** For a banking call center, setting a higher `voiceSeconds` value ensures accuracy by reducing false positives. This avoids interruptions caused by background sounds, even if it slightly delays the detection of speech onset. This tradeoff is essential to ensure the assistant processes only correct and intended information. - **Pause Before Resuming**: Control how long the assistant waits before starting to talk again after being interrupted. The default is 1 second, but you can adjust it depending on how quickly the assistant should resume. -**Example:** For quick queries (e.g., "What's the total order value in my cart?"), set `backoffSeconds` to 1 second. + **Example:** For quick queries (e.g., "What's the total order value in my cart?"), set `backoffSeconds` to 1 second. Here's a code snippet for Stop Speaking Plan - @@ -72,18 +95,16 @@ Here's a code snippet for Stop Speaking Plan - "stopSpeakingPlan": { "numWords": 0, "voiceSeconds": 0.2, - "backoffSeconds": 1 + "backoffSeconds": 1 } ``` - ## Considerations for Configuration - **Customer Style**: Think about whether the customer pauses mid-thought or provides continuous speech. Adjust wait times and enable smart endpointing as needed. - **Background Noise**: If there's a lot of background noise, you may need to tweak the settings to avoid false triggers. Default for phone calls is 'office' and default for web calls is 'off'. - ```json "backgroundSound": "off", ``` diff --git a/fern/customization/transcriber-fallback-plan.mdx b/fern/customization/transcriber-fallback-plan.mdx new file mode 100644 index 000000000..28ec3311a --- /dev/null +++ b/fern/customization/transcriber-fallback-plan.mdx @@ -0,0 +1,274 @@ +--- +title: Transcriber fallback configuration +subtitle: Configure fallback transcribers that activate automatically if your primary transcriber fails. +description: Configure fallback transcribers so calls keep working if your primary speech-to-text provider fails. Covers automatic fallback, manual fallback, and HIPAA-compliant provider options. +slug: customization/transcriber-fallback-plan +--- + +## Overview + +Transcriber fallback configuration ensures your calls continue even if your primary speech-to-text provider experiences issues. Vapi supports two approaches: + +- **Auto fallback** — Vapi intelligently routes transcription to an alternative provider when your primary fails. No configuration required. +- **Manual fallback** — You specify exact backup providers in priority order for full control over the failover sequence. + +You can use both together. When combined, your manual fallbacks are tried first. If all of them fail, Vapi's auto fallback takes over as a final safety net. + +**Key benefits:** +- **Call continuity** during provider outages +- **Automatic failover** with no user intervention required +- **Provider diversity** to protect against single points of failure + + + Without any fallback plan configured, your call will end with an error if your chosen transcription provider fails. + + +## How it works + +When a transcriber failure occurs, Vapi follows this priority order: + +1. **Manual fallbacks first** — If you've configured explicit fallback transcribers, Vapi tries each one sequentially in the order you specified. +2. **Auto fallback as safety net** — If all manual fallbacks fail (or none are configured), and auto fallback is enabled, Vapi intelligently selects an alternative provider and routes your transcription audio to it. +3. **Call termination** — The call ends only if every fallback option has been exhausted. + +## Auto fallback + +Auto fallback is the simplest way to add resilience. Toggle it on, and Vapi handles provider selection for you—automatically routing transcription audio to an alternative STT provider when your primary fails. + + + Enabling auto fallback may route audio to other providers. If your organization has strict compliance requirements, review your compliance settings to ensure this aligns with your needs. + + +To enable auto fallback via API, set `transcriber.fallbackPlan.autoFallback.enabled` to `true`: + +```json +{ + "transcriber": { + "provider": "deepgram", + "model": "nova-3", + "language": "en", + "fallbackPlan": { + "autoFallback": { + "enabled": true + } + } + } +} +``` + +## Manual fallbacks + +Manual fallbacks give you full control over which providers Vapi tries, and in what order. This is useful when you need specific providers for compliance, language support, or cost reasons. + +### Configure via Dashboard + + + + Open the [Dashboard](https://dashboard.vapi.ai/). Select **Assistants**, then select an assistant. + + + Select the **Advanced** tab. In the **Fallbacks** section, locate **Fallback Transcriber**. + + + Select **Add**, then choose a **Provider**, **Language**, and **Model**. + + + Expand **Additional Configuration**, then configure the available settings. Review the [provider-specific settings](#provider-specific-settings) for details about each option. + + + Select **Add** to configure another fallback transcriber. Vapi attempts fallback transcribers in the order they are listed. + + + + + If HIPAA compliance is enabled, choose every fallback from the current list of [HIPAA-compliant transcription providers](/security-and-privacy/hipaa#transcription-providers-stt). + + +### Configure via API + +Add the `fallbackPlan` property to your assistant's transcriber configuration, and specify the fallback transcribers within the `transcribers` property. You can combine manual fallbacks with auto fallback for maximum resilience. + +```json +{ + "transcriber": { + "provider": "deepgram", + "model": "nova-3", + "language": "en", + "fallbackPlan": { + "autoFallback": { + "enabled": true + }, + "transcribers": [ + { + "provider": "assembly-ai", + "speechModel": "universal-streaming-multilingual", + "language": "en" + }, + { + "provider": "azure", + "language": "en-US" + } + ] + } + } +} +``` + +In this example, if Deepgram fails, Vapi tries AssemblyAI first, then Azure. If both manual fallbacks fail, auto fallback intelligently selects another available provider. + +## Provider-specific settings + +Each transcriber provider supports different configuration options. Expand a provider below to review its available settings. For the complete schema, see the provider-specific transcriber fields in the [Create Assistant API reference](/api-reference/assistants/create#request.body.transcriber). + + + + - **language**: Language code (`multi` for multilingual or `en` for English). + - **speechModel**: AssemblyAI streaming speech model. + - **mode**: Accuracy and latency mode for `universal-3-5-pro`: `max_accuracy`, `min_latency`, or `balanced`. + - **prompt**: Additional context for `universal-3-5-pro`, up to 1,750 characters. + - **agentContext**: Voice-agent context for `universal-3-5-pro`, up to 1,750 characters. + - **languageCodes**: Language hints for `universal-3-5-pro` automatic language detection. + - **realtimeUrl**: WebSocket URL used for the realtime transcription connection. + - **wordBoost**: Custom vocabulary array, up to 2,500 characters per entry. + - **keytermsPrompt**: Up to 100 keyterms, with a maximum of 50 characters each. + - **endUtteranceSilenceThreshold**: Duration of silence in milliseconds used to detect the end of an utterance. + - **disablePartialTranscripts**: Set to `true` to disable partial transcripts. + - **confidenceThreshold**: Minimum confidence for accepting transcripts, from `0` to `1`. + - **formatTurns**: Enables transcript formatting. + - **endOfTurnConfidenceThreshold**: Minimum end-of-turn confidence, from `0` to `1`. + - **minEndOfTurnSilenceWhenConfident**: Minimum silence in milliseconds before ending a confident turn. + - **maxTurnSilence**: Maximum turn silence in milliseconds. + - **vadAssistedEndpointingEnabled**: Enables VAD-assisted endpoint detection. + + + - **language**: Language code in BCP 47 format, such as `en-US`, `es-MX`, or `fr-FR`. + - **segmentationSilenceTimeoutMs**: Duration of silence after which a phrase is finalized, from `100` to `5000` milliseconds. + - **segmentationMaximumTimeMs**: Maximum segment duration, from `20000` to `70000` milliseconds. + - **segmentationStrategy**: Phrase-boundary strategy: `Default`, `Time`, or `Semantic`. + + + - **model**: Cartesia transcription model. + - **language**: Language code. Language availability depends on the selected model. + + + - **model**: Deepgram transcription model. + - **language**: Language code for transcription. + - **languages**: Language hints for Flux Multilingual. Omit this field to allow automatic detection. + - **keywords**: Keywords with optional boost values, such as `["companyname", "productname:2"]`. + - **keyterm**: Important words or phrases for keyterm prompting. + - **smartFormat**: Enables formatting for values such as numbers and dates. + - **endpointing**: Silence duration used for endpointing, from `10` to `500` milliseconds. + - **mipOptOut**: Opts your account out of Deepgram's Model Improvement Partnership when you use your own Deepgram API key. + - **numerals**: Converts spoken numbers to numerals. + - **profanityFilter**: Replaces profanity in transcripts with asterisks. + - **redaction**: Redacts selected categories: `pci`, `pii`, `phi`, or `numbers`. + - **confidenceThreshold**: Minimum confidence for accepting transcripts, from `0` to `1`. + - **eotThreshold**: End-of-turn confidence threshold for Flux models, from `0.5` to `0.9`. + - **eotTimeoutMs**: Maximum wait after speech before finalizing a turn with Flux, from `500` to `10000` milliseconds. + + See [Deepgram](/providers/transcriber/deepgram) for current models and model-specific language support. + + + - **model**: ElevenLabs transcription model. + - **language**: ISO 639-1 language code. + - **silenceThresholdSeconds**: Silence before VAD commits, from `0.3` to `3` seconds. + - **confidenceThreshold**: VAD sensitivity, from `0.1` to `0.9`; lower values are more sensitive. + - **minSpeechDurationMs**: Minimum speech duration for VAD, from `50` to `2000` milliseconds. + - **minSilenceDurationMs**: Minimum silence duration for VAD, from `50` to `2000` milliseconds. + + + - **model**: Gladia transcription model. + - **languageBehaviour**: Controls automatic or manual language detection. + - **language**: Language code. + - **languages**: Language codes used when manual multilingual detection is configured. + - **confidenceThreshold**: Minimum confidence for accepting transcripts, from `0` to `1`. + - **endpointing**: Time to wait before considering speech complete, from `0.01` to `10` seconds. + - **speechThreshold**: Speech-detection sensitivity, from `0` to `1`. + - **prosody**: Enables detection of non-speech events such as laughter and music. + - **audioEnhancer**: Preprocesses audio to improve accuracy, with additional latency. + - **transcriptionHint**: Context that guides transcription, up to 600 characters. + - **customVocabularyEnabled**: Enables custom vocabulary. + - **customVocabularyConfig**: Custom vocabulary and intensity configuration. + - **region**: Processing region, `us-west` or `eu-west`. + - **receivePartialTranscripts**: Enables partial transcripts. + + + - **model**: Gemini transcription model. + - **language**: Language selection, such as `Multilingual`, `English`, `Spanish`, or `French`. + + + - **model**: OpenAI realtime transcription model. + - **language**: Language code for transcription. + + + - **model**: Soniox transcription model. + - **language**: ISO 639-1 language code. + - **languages**: Expected-language hints. An empty array enables automatic detection without hints. + - **languageHintsStrict**: Restricts transcription to selected language hints when enabled. + - **maxEndpointDelayMs**: Maximum endpoint delay, from `500` to `3000` milliseconds. + - **customVocabulary**: Brand names, product names, or other domain-specific terms. + - **contextGeneral**: Key-value pairs that provide domain or topic context. + + See [Soniox](/providers/transcriber/soniox) for current model and language details. + + + - **model**: Speechmatics transcription model. + - **language**: Language code or `auto` for automatic detection. + - **operatingPoint**: `standard` for faster transcription or `enhanced` for higher accuracy. Defaults to `enhanced`. + - **region**: Processing region, `eu` or `us`. Defaults to `eu`. + - **enableDiarization**: Enables speaker identification for multi-speaker conversations. + - **maxDelay**: Maximum delay for partial transcripts, from `500` to `10000` milliseconds. Defaults to `3000`. + - **customVocabulary**: Words or phrases to improve recognition, with optional `soundsLike` variations. + - **numeralStyle**: Number formatting style: `written` or `spoken`. Defaults to `written`. + - **endOfTurnSensitivity**: End-of-turn sensitivity, from `0` to `1`. Defaults to `0.5`. + - **removeDisfluencies**: Removes disfluencies from English transcripts when enabled. + - **minimumSpeechDuration**: Minimum speech-segment duration, from `0` to `5` seconds. + + + - **model**: Talkscriber transcription model. + - **language**: Language code for transcription. + + See [Talkscriber](/providers/transcriber/talkscriber) for the supported model and languages. + + + - **model**: xAI transcription model. + - **language**: Language code for transcription. + + See [xAI](/providers/transcriber/xai) for the supported model and languages. + + + +## Best practices + +- **Start with auto fallback** for quick, zero-config resilience—it works well for most use cases. +- **Add manual fallbacks** when you need control over specific providers for compliance, language, or cost reasons. +- **Combine both** for maximum reliability—manual fallbacks run first, auto fallback catches anything they miss. +- Use **different providers** for manual fallbacks to protect against provider-wide outages. +- Consider **language compatibility** when selecting fallbacks—ensure all fallback transcribers support your required languages. +- For **HIPAA compliance**, choose every fallback from the current list of [HIPAA-compliant transcription providers](/security-and-privacy/hipaa#transcription-providers-stt) and review data-routing implications before enabling auto fallback. + +## FAQ + + + + Auto fallback lets Vapi intelligently select an alternative provider for you—no configuration needed. Manual fallback lets you specify exact providers in a specific priority order. You can use both together: manual fallbacks are tried first, and auto fallback acts as a safety net if they all fail. + + + Review [Transcriber providers](/providers/transcriber/overview) for the current provider list and the [`fallbackPlan.transcribers` schema](/api-reference/assistants/create#request.body.transcriber) for accepted fallback configurations. + + + No additional fees for using fallback transcribers. You are only billed for the transcriber that processes the audio. + + + Failover typically occurs within milliseconds of detecting a failure, ensuring minimal disruption to the call. + + + Yes. When auto fallback activates, Vapi may route transcription audio to a different cloud provider than your primary. If you have data residency or compliance requirements, we recommend reviewing your organization's policies to ensure this aligns with your needs. + + + If your primary transcriber supports native endpointing (like Deepgram Flux), that capability won't carry over to the fallback provider. Vapi will automatically switch to heuristic-based endpointing to continue detecting turn boundaries. + + + Yes, each fallback transcriber can have its own language configuration. However, for the best user experience, we recommend using the same or similar languages across all fallbacks. + + diff --git a/fern/customization/voice-pipeline-configuration.mdx b/fern/customization/voice-pipeline-configuration.mdx index e3a8b5fdb..bd2c85f26 100644 --- a/fern/customization/voice-pipeline-configuration.mdx +++ b/fern/customization/voice-pipeline-configuration.mdx @@ -18,6 +18,38 @@ Configure VAPI's voice pipeline to create natural conversation experiences throu For implementation examples, see **[Configuration examples](#configuration-examples)**. +## Configure via Dashboard + + + + Open the [Dashboard](https://dashboard.vapi.ai/assistants). Select **Assistants**, then select the assistant you want to configure. + + + + Select the **Advanced** tab, then locate **Start Speaking Plan** and **Stop Speaking Plan**. + + + + In **Start Speaking Plan**, set **Wait Seconds**. Choose **Off**, **Vapi**, or **LiveKit** under **Smart Endpointing**, then set **On Punctuation Seconds**, **On No Punctuation Seconds**, and **On Number Seconds**. + + + + In **Stop Speaking Plan**, set **Number of Words**, **Voice Seconds**, and **Back Off Seconds**. + + + + Select **publish** in the unsaved-changes message to apply the update. + + + + + + + + + + + ## Quick start ### English conversations (recommended) @@ -86,9 +118,10 @@ User Audio → VAD → Transcription → Start Speaking Decision → LLM → TTS Voice Activity Detection (VAD) detects utterance-stop - System evaluates completion using: - Custom Rules (highest priority) - Smart - Endpointing Plan (LiveKit for English) - Transcription Endpointing Plan - (fallback) + System evaluates completion using this priority order: + 1. **Transcriber EOT detection** (if transcriber has built-in EOT and no smart endpointing plan) + 2. **Custom Rules** (highest priority when configured) + 3. **Smart Endpointing Plan** (LiveKit for English, Vapi for non-English) LLM request sent immediately → TTS processes → waitSeconds applied → @@ -121,6 +154,10 @@ The start speaking plan determines when your assistant begins responding after a Analyzes transcription text to determine user completion based on patterns like punctuation and numbers. + +This plan is only used if `smartEndpointingPlan` is not set and transcriber does not have built-in endpointing capabilities. If both are provided, `smartEndpointingPlan` takes precedence. This plan will also be overridden by any matching `customEndpointingRules`. + + ```json @@ -159,6 +196,8 @@ Analyzes transcription text to determine user completion based on patterns like Uses AI models to analyze speech patterns, context, and audio cues to predict when users have finished speaking. Only available for English conversations. +**Important:** If your transcriber has built-in end-of-turn detection (like Deepgram Flux or Assembly) and you don't configure a smart endpointing plan, the system will automatically use the transcriber's EOT detection instead of smart endpointing. + ```json @@ -174,22 +213,79 @@ Uses AI models to analyze speech patterns, context, and audio cues to predict wh ``` - **livekit** - Advanced model trained on conversation data (recommended for English) - - **vapi** - Alternative VAPI-trained model - + **Text-based providers:** + - **livekit**: Advanced model trained on conversation data (English only) + - **vapi**: VAPI-trained model (non-English conversations or LiveKit alternative) + + **Audio-based providers:** + - **krisp**: Audio-based model analyzing prosodic features (intonation, pitch, rhythm) + + **Audio-text based providers:** + - **deepgram-flux**: Deepgram's latest transcriber model with built-in conversational speech recognition. Use `flux-general-en` for English-only conversations or `flux-general-multi` for multilingual conversations. + - **assembly**: Transcriber with built-in end-of-turn detection for Universal-Streaming English, Universal-Streaming Multilingual, and Universal 3.5 Pro + +
-**When to use:** -- English conversations -- Natural conversation flow requirements -- Reduced false endpointing triggers +**When to use smart endpointing:** + +- **Deepgram Flux**: English and Multi-lingual conversations using Deepgram as a transcriber. +- **AssemblyAI**: Use when AssemblyAI is already your transcriber provider and you want integrated end-of-turn detection +- **LiveKit**: English conversations where Deepgram is not the transcriber of choice. +- **Vapi**: Non-English conversations with default stop speaking plan settings +- **Krisp**: Non-English conversations with a robustly configured stop speaking plan + +### Deepgram Flux configuration + +Deepgram Flux's end-of-turn detection is configured at the transcriber level, allowing you to fine-tune how aggressive or conservative the bot should be in detecting when users finish speaking. Do NOT set a `smartEndpointingPlan` to leverage Deepgram's end-of-turn events. + +**Configuration parameters:** + +- **eotThreshold** (Default: 0.7): Confidence level required to trigger end-of-turn detection + - **0.5-0.6:** Aggressive detection - responds quickly but may interrupt users mid-sentence + - **0.6-0.8:** Balanced detection (default: 0.7) - good balance between responsiveness and accuracy + - **0.9-1.0:** Conservative detection - waits longer to ensure users have finished speaking + +- **eotTimeoutMs** (Default: 5000): Maximum wait time in milliseconds before forcing turn end + - **2000-3000:** Fast timeout for quick interactions + - **4000-6000:** Standard timeout (default: 5000) - natural conversation flow + - **7000-10000:** Extended timeout for complex or thoughtful responses + +**Configuration examples:** + + + + ```json + { + "transcriber": { + "provider": "deepgram", + "model": "flux-general-en", + "language": "en", + "eotThreshold": 0.7, + "eotTimeoutMs": 5000 + } + } + ``` + + + ```json + { + "transcriber": { + "provider": "deepgram", + "model": "flux-general-multi", + "eotThreshold": 0.7, + "eotTimeoutMs": 5000 + } + } + ``` + + Omit `languages` to enable automatic language detection, or set it to an array of expected language codes to provide hints. See [Deepgram's supported languages](/providers/transcriber/deepgram#supported-languages) for the current Flux language list. + + -### Wait function +### LiveKit's Wait function Mathematical expression that determines wait time based on speech completion probability. The function takes a confidence value (0-1) and returns a wait time in milliseconds. @@ -223,6 +319,121 @@ Mathematical expression that determines wait time based on speech completion pro - **Use case:** Healthcare, formal settings, sensitive conversations - **Timing:** ~2700ms wait at 50% confidence, ~700ms at 90% confidence +### Vapi heuristic endpointing + +Vapi's text-based endpointing uses heuristic rules to analyze transcription patterns and determine when users have finished speaking. The system applies these rules in priority order using the `transcriptionEndpointingPlan` settings: + +**Heuristic priority order:** + +1. **Number detection**: If the latest message ends with a number, waits for `onNumberSeconds` (default: 0.5) +2. **Punctuation detection**: If the message contains punctuation, waits for `onPunctuationSeconds` (default: 0.1) +3. **No punctuation fallback**: If no punctuation is detected, waits for `onNoPunctuationSeconds` (default: 1.5) +4. **Default**: If no rules match, waits 0ms (immediate response) + +**How it works:** + +The system continuously analyzes the latest user message and applies the first matching rule. Each rule sets a specific timeout delay before triggering the end-of-turn event. + +**Configuration example:** + +```json +{ + "startSpeakingPlan": { + "smartEndpointingPlan": { + "provider": "vapi" + }, + "transcriptionEndpointingPlan": { + "onPunctuationSeconds": 0.1, + "onNoPunctuationSeconds": 1.5, + "onNumberSeconds": 0.5 + } + } +} +``` + +**When to use:** + +- Non-English conversations where LiveKit isn't available +- Scenarios requiring predictable, rule-based endpointing behavior +- Fallback option when other smart endpointing providers aren't suitable + +### Krisp threshold configuration + +Krisp's audio-base model returns a probability between 0 and 1, where 1 means the user definitely stopped speaking and 0 means they're still speaking. + +**Threshold settings:** + +- **0.0-0.3:** Very aggressive detection - responds quickly but may interrupt users mid-sentence +- **0.4-0.6:** Balanced detection (default: 0.5) - good balance between responsiveness and accuracy +- **0.7-1.0:** Conservative detection - waits longer to ensure users have finished speaking + +**Configuration example:** + +```json +{ + "startSpeakingPlan": { + "smartEndpointingPlan": { + "provider": "krisp", + "threshold": 0.5 + } + } +} +``` + +**Important considerations:** +Since Krisp is audio-based, it always notifies when the user is done speaking, even for brief acknowledgments. Configure the stop speaking plan with appropriate `acknowledgementPhrases` and `numWords` settings to handle backchanneling properly. + +### Assembly turn detection + +AssemblyAI's turn detection model uses a neural network to detect when someone has finished speaking. The model understands the meaning and flow of speech to make better decisions about when a turn has ended. + +When the model detects an end-of-turn, it returns `end_of_turn=True` in the response. + +**Quick start configurations:** + +To use Assembly's turn detection, set Assembly as your transcriber provider and configure these fields in the assistant's transcriber (**do not set any smartEndpointingPlan**): + +**Aggressive (Fast Response):** + +```json +{ + "endOfTurnConfidenceThreshold": 0.4, + "minEndOfTurnSilenceWhenConfident": 160, + "maxTurnSilence": 400 +} +``` + +- **Use cases:** Agent Assist, IVR replacements, Retail/E-commerce, Telecom +- **Behavior:** Ends turns very quickly, optimized for short responses + +**Balanced (Natural Flow):** + +```json +{ + "endOfTurnConfidenceThreshold": 0.4, + "minEndOfTurnSilenceWhenConfident": 400, + "maxTurnSilence": 1280 +} +``` + +- **Use cases:** Customer Support, Tech Support, Financial Services, Travel & Hospitality +- **Behavior:** Natural middle ground, allowing enough pause for conversational turns + +**Conservative (Patient Response):** + +```json +{ + "endOfTurnConfidenceThreshold": 0.7, + "minEndOfTurnSilenceWhenConfident": 800, + "maxTurnSilence": 3600 +} +``` + +- **Use cases:** Healthcare, Mental Health Support, Sales & Consulting, Legal & Insurance +- **Behavior:** Holds the floor longer, optimized for reflective or complex speech + +For detailed information about how Assembly's turn detection works, see the [AssemblyAI Turn Detection documentation](https://www.assemblyai.com/docs/universal-streaming/turn-detection). + ### Wait seconds Final audio delay applied after all processing completes, before the assistant speaks. @@ -454,6 +665,118 @@ User Interrupts → Assistant Audio Stopped → backoffSeconds Blocks All Output **Optimized for:** Text-based endpointing with longer timeouts for different speech patterns and international support. +### Audio-based endpointing (Krisp example) + +```json +{ + "startSpeakingPlan": { + "waitSeconds": 0.4, + "smartEndpointingPlan": { + "provider": "krisp", + "threshold": 0.5 + } + }, + "stopSpeakingPlan": { + "numWords": 2, + "voiceSeconds": 0.2, + "backoffSeconds": 1.0, + "acknowledgementPhrases": [ + "okay", + "right", + "uh-huh", + "yeah", + "mm-hmm", + "got it" + ] + } +} +``` + +**Optimized for:** Non-English conversations with robust backchanneling configuration to handle audio-based detection limitations. + +### Audio-text based endpointing (Assembly example) + +```json +{ + "transcriber": { + "provider": "assembly", + "endOfTurnConfidenceThreshold": 0.4, + "minEndOfTurnSilenceWhenConfident": 400, + "maxTurnSilence": 1280 + }, + "startSpeakingPlan": { + "waitSeconds": 0.4 + }, + "stopSpeakingPlan": { + "numWords": 0, + "voiceSeconds": 0.2, + "backoffSeconds": 1.0 + } +} +``` + +**Optimized for:** English conversations with integrated transcriber and sophisticated end-of-turn detection. + +### Audio-text based endpointing (Deepgram Flux example) + + + + ```json + { + "transcriber": { + "provider": "deepgram", + "model": "flux-general-en", + "language": "en", + "eotThreshold": 0.7, + "eotTimeoutMs": 5000 + }, + "stopSpeakingPlan": { + "numWords": 2, + "voiceSeconds": 0.2, + "backoffSeconds": 1.0, + "acknowledgementPhrases": [ + "okay", + "right", + "uh-huh", + "yeah", + "mm-hmm", + "got it" + ] + } + } + ``` + + **Optimized for:** English conversations where Deepgram is set as transcriber. + + + ```json + { + "transcriber": { + "provider": "deepgram", + "model": "flux-general-multi", + "eotThreshold": 0.7, + "eotTimeoutMs": 5000 + }, + "stopSpeakingPlan": { + "numWords": 2, + "voiceSeconds": 0.2, + "backoffSeconds": 1.0, + "acknowledgementPhrases": [ + "okay", + "right", + "uh-huh", + "yeah", + "mm-hmm", + "got it" + ] + } + } + ``` + + **Optimized for:** Multilingual conversations where Deepgram is set as transcriber. Omit `languages` to enable automatic language detection, or set it to an array of expected language codes to provide hints. See [Deepgram's supported languages](/providers/transcriber/deepgram#supported-languages) for the current Flux language list. + + + ### Education and training ```json diff --git a/fern/debugging.mdx b/fern/debugging.mdx index 8ac703a52..3fdc5dabe 100644 --- a/fern/debugging.mdx +++ b/fern/debugging.mdx @@ -1,6 +1,6 @@ --- title: Debugging voice agents -subtitle: Learn to identify, diagnose, and fix common issues with your voice assistants and workflows +subtitle: Learn to identify, diagnose, and fix common issues with your voice assistants slug: debugging --- @@ -19,7 +19,7 @@ Voice agents involve multiple AI systems working together—speech recognition, * Call quality issues or audio problems * Tool integrations failing or returning errors - * Workflow logic not executing as expected + * Unexpected behavior or configuration errors @@ -31,14 +31,9 @@ Start with these immediate checks before diving deeper: Test your voice agent directly in the [dashboard](https://dashboard.vapi.ai/): - - - Click "Talk to Assistant" to test - - - Click "Call" to test workflow - - + + Click "Talk to Assistant" to test + **Benefits:** - Eliminates phone network variables @@ -83,6 +78,7 @@ Start with these immediate checks before diving deeper: - [Anthropic Status](https://status.anthropic.com/) for Anthropic language models - [ElevenLabs Status](https://status.elevenlabs.io/) for ElevenLabs voice synthesis - [Deepgram Status](https://status.deepgram.com/) for Deepgram speech-to-text + - [Gladia Status](https://status.gladia.io/) for Gladia speech-to-text - And other providers' status pages as needed @@ -98,7 +94,7 @@ Navigate to `Observe > Call Logs` to: - Check call duration and completion status - Identify where calls failed or ended unexpectedly - See tool execution results and errors -- Analyze conversation flow in workflows +- Analyze conversation flow