diff --git a/.github/workflows/update-openapi.yml b/.github/workflows/update-openapi.yml
index 7d83b663d..3e4aca22b 100644
--- a/.github/workflows/update-openapi.yml
+++ b/.github/workflows/update-openapi.yml
@@ -2,6 +2,86 @@ name: Update OpenAPI Specification
on:
workflow_dispatch:
+jobs:
+ update-openapi:
+ runs-on: ubuntu-latest
+ permissions:
+ contents: write
+ pull-requests: write
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ - name: Fetch OpenAPI specification
+ run: |
+ curl -s https://api.vapi.ai/api-json > temp-openapi.json
+
+ - name: Verify JSON validity
+ run: |
+ cat temp-openapi.json | jq . > /dev/null
+ if [ $? -ne 0 ]; then
+ echo "Error: Invalid JSON received from API endpoint"
+ exit 1
+ fi
+ mv temp-openapi.json ./fern/apis/api/openapi.json
+
+ - name: Check for changes
+ id: check_changes
+ run: |
+ if git diff --quiet ./fern/apis/api/openapi.json; then
+ echo "No changes detected in OpenAPI specification"
+ echo "changes_detected=false" >> $GITHUB_OUTPUT
+ else
+ echo "Changes detected in OpenAPI specification"
+ echo "changes_detected=true" >> $GITHUB_OUTPUT
+ fi
+
+ - name: Setup GitHub CLI
+ id: setup_cli
+ if: steps.check_changes.outputs.changes_detected == 'true'
+ run: |
+ # Create timestamp for unique branch name
+ TIMESTAMP=$(date +%Y%m%d%H%M%S)
+ BRANCH_NAME="update-openapi-spec-${TIMESTAMP}"
+
+ # Setup branch for changes
+ git config --global user.name "GitHub Actions"
+ git config --global user.email "actions@github.com"
+
+ # Create new branch with timestamp
+ git checkout -b $BRANCH_NAME
+ git add ./fern/apis/api/openapi.json
+ git commit -m "chore: update OpenAPI specification"
+ git push -u origin $BRANCH_NAME
+
+ # Store branch name for PR creation
+ echo "branch_name=$BRANCH_NAME" >> $GITHUB_OUTPUT
+
+ - name: Create Pull Request with GitHub CLI
+ if: steps.check_changes.outputs.changes_detected == 'true'
+ run: |
+ gh pr create \
+ --base main \
+ --head ${{ steps.setup_cli.outputs.branch_name }} \
+ --title "Update OpenAPI Specification" \
+ --body "This PR updates the OpenAPI specification from the official Vapi API endpoint.
+
+ - Auto-generated by the Update OpenAPI Specification workflow
+ - Source: https://api.vapi.ai/api-json
+ - Generated at: $(date -u +'%Y-%m-%dT%H:%M:%SZ')"
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: PR Result
+ if: steps.check_changes.outputs.changes_detected == 'true'
+ run: |
+ echo "Pull request created successfully!"
+
+ - name: No Changes Result
+ if: steps.check_changes.outputs.changes_detected == 'false'
+ run: |
+ echo "No changes detected in OpenAPI specification. No PR created."
+=======
schedule:
- cron: "0 0 * * *"
@@ -21,4 +101,4 @@ jobs:
token: ${{ secrets.GITHUB_TOKEN }}
branch: 'update-openapi-spec'
update_from_source: true
- add_timestamp: true
\ No newline at end of file
+ add_timestamp: true
diff --git a/dev-docs.json b/dev-docs.json
index ad795ee99..02af2eb82 100644
--- a/dev-docs.json
+++ b/dev-docs.json
@@ -1,9 +1,9 @@
{
"gitHubApp": {
- "approvalWorkflow": true,
"userDocsWorkflows": [
"generateUserDocs"
],
- "issues": true
+ "issues": true,
+ "connectedOrg": "vapi-poc"
}
-}
\ No newline at end of file
+}
diff --git a/fern/apis/api/openapi.json b/fern/apis/api/openapi.json
index 929febfd7..71ff5d26d 100644
--- a/fern/apis/api/openapi.json
+++ b/fern/apis/api/openapi.json
@@ -42425,4 +42425,4 @@
}
}
}
-}
\ No newline at end of file
+}
diff --git a/fern/changelog/2025-06-10.mdx b/fern/changelog/2025-06-10.mdx
new file mode 100644
index 000000000..1f142c9eb
--- /dev/null
+++ b/fern/changelog/2025-06-10.mdx
@@ -0,0 +1,7 @@
+# New Call End Reason `pipeline-error-eleven-labs-vapi-voice-disabled-by-owner`
+
+
+ Calls can now end with the reason `pipeline-error-eleven-labs-vapi-voice-disabled-by-owner`, indicating the Eleven Labs voice service is disabled by the owner.
+
+
+This call ended reason are available to handle in [`Call`](https://api.vapi.ai/api#:~:text=Call), [`ServerMessageStatusUpdate`](https://api.vapi.ai/api#:~:text=ServerMessageStatusUpdate), and [`ServerMessageEndOfCallReport`](https://api.vapi.ai/api#:~:text=ServerMessageEndOfCallReport). You can update your application to handle this new end reason, ensuring proper notification and handling when this occurs.
diff --git a/llmText.json b/llmText.json
new file mode 100644
index 000000000..0c3f1899c
--- /dev/null
+++ b/llmText.json
@@ -0,0 +1,3 @@
+{
+ "llmTxtFile": "static/llm.txt"
+}
\ No newline at end of file
diff --git a/static/llm.txt b/static/llm.txt
new file mode 100644
index 000000000..f0c97533b
--- /dev/null
+++ b/static/llm.txt
@@ -0,0 +1,19485 @@
+Below is all the contents of our docs:
+
+
+
+ This is the content for the doc README.md
+
+ # Vapi Platform Documentation
+
+This repository contains the source files for the documentation found at [docs.vapi.ai](https://docs.vapi.ai/).
+
+Get started with Vapi here: [docs.vapi.ai/introduction](https://docs.vapi.ai/introduction)
+
+View the API Reference here: [docs.vapi.ai/api-reference](https://docs.vapi.ai/api-reference/)
+
+Explore our Client and Server SDKs here: [docs.vapi.ai/sdks](https://docs.vapi.ai/sdks)
+
+| Vapi Developer Ecosystem | |
+|--------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| **Real-time SDKs** | [Web](https://github.com/VapiAI/web) · [Flutter](https://github.com/VapiAI/flutter) · [React Native](https://github.com/VapiAI/react-native-sdk) · [iOS](https://github.com/VapiAI/ios) · [Python](https://github.com/VapiAI/python) · [Vanilla](https://github.com/VapiAI/html-script-tag) |
+| **Client Examples** | [Next.js](https://github.com/VapiAI/client-side-example-javascript-next) · [React](https://github.com/VapiAI/client-side-example-javascript-react) · [Flutter](https://github.com/VapiAI/flutter/tree/main/example) · [React Native](https://github.com/VapiAI/client-side-example-react-native) |
+| **Server Examples** | [Vercel](https://github.com/VapiAI/server-side-example-serverless-vercel) · [Cloudflare](https://github.com/VapiAI/server-side-example-serverless-cloudflare) · [Supabase](https://github.com/VapiAI/server-side-example-serverless-supabase) · [Node](https://github.com/VapiAI/server-side-example-javascript-node) · [Bun](https://github.com/VapiAI/server-side-example-javascript-bun) · [Deno](https://github.com/VapiAI/server-side-example-javascript-deno) · [Flask](https://github.com/VapiAI/server-side-example-python-flask) · [Laravel](https://github.com/VapiAI/server-side-example-php-laravel) · [Go](https://github.com/VapiAI/server-side-example-go-gin) · [Rust](https://github.com/VapiAI/server-side-example-rust-actix) |
+| **Resources** | [Official Docs](https://docs.vapi.ai/) · [API Reference](https://api.vapi.ai/api) |
+| **Community** | [Videos](/community/videos) · [UI Library](https://www.vapiblocks.com/) |
+
+## How can I contribute to these docs?
+
+You can suggest edits by making a pull request.
+
+## How to update documentation?
+
+### Local Development server
+
+To run a local development server with hot-reloading you can run the following command
+
+```sh
+fern docs dev
+```
+
+#### Hosted URL
+
+To update your documentation on a hosted URL, run
+```
+# npm install -g fern-api
+fern generate --docs
+```
+To preview your documentation, run
+```
+# npm install -g fern-api
+fern generate --docs --preview
+```
+The repository contains GitHub workflows that will automatically run these commands for you. For example, when you make a PR a preview link will be auto-generated and when you merge to main the docs site will update.
+
+
+ This is the content for the doc advanced.md
+
+ # Vapi Api Configuration
+
+This repository contains our Fern Configuration:
+
+- [OpenAPI spec](./openapi.json)
+- [OpenAPI Overrides](./openapi-overrides.yml)
+- [SDK generator config](./fern/generators.yml)
+
+## Setup
+
+```sh
+npm install -g fern-api
+```
+
+## Validating your OpenAPI Specs
+
+To validate your API, run:
+
+```sh
+fern check
+```
+
+## Managing SDKs
+
+### Deploying your SDKs
+
+To deploy your SDKs, simply run the `Release Python SDK` GitHub Action with the
+desired version for the release. Under the hood, this leverages the Fern CLI:
+
+```sh
+fern generate --api api --group python-sdk
+```
+
+### Developing SDKs
+
+You can also regenerate the SDKs locally by running:
+
+```sh
+fern generate --api api --group python-sdk --preview --log-level debug
+```
+
+This will generate the SDK and download it to a local folder that can be pip installed.
+
+```sh
+pip install -e /fern/.preview/fern-python-sdk
+```
+
+## How to update documentation?
+
+### Local Development server
+
+To run a local development server with hot-reloading you can run the following command
+
+```sh
+fern docs dev
+```
+
+#### Hosted URL
+
+To update your documentation on a hosted URL, run
+```
+# npm install -g fern-api
+fern generate --docs
+```
+To preview your documentation, run
+```
+# npm install -g fern-api
+fern generate --docs --preview
+```
+The repository contains GitHub workflows that will automatically run these commands for you. For example, when you make a PR a preview link will be auto-generated and when you merge to main the docs site will update.
+
+
+ This is the content for the doc fern/GHL.mdx
+
+ ---
+title: How to Connect Vapi with Make & GHL
+slug: tools/GHL
+---
+
+
+Vapi's GHL/Make Tools integration allows you to directly import your GHL workflows and Make scenarios into Vapi as Tools. This enables you to create voicebots that can trigger your favorite app integrations and automate complex workflows using voice commands.
+
+## What are GHL/Make Tools?
+
+GHL (GoHighLevel) workflows and Make scenarios are powerful automation tools that allow you to connect and integrate various apps and services. With the GHL/Make Tools integration, you can now bring these automations into Vapi and trigger them using voice commands.
+
+## How does the integration work?
+
+1. **Import workflows and scenarios**: Navigate to the [Tools section](https://dashboard.vapi.ai/tools) in your Vapi dashboard and import your existing GHL workflows and Make scenarios.
+
+2. **Add Tools to your assistants**: Once imported, you can add these Tools to your AI assistants, enabling them to trigger the automations based on voice commands.
+
+3. **Trigger automations with voice**: Your AI assistants can now understand voice commands and execute the corresponding GHL workflows or Make scenarios, allowing for seamless voice-enabled automation.
+
+## Setting up the GHL/Make Tools integration
+
+1. **Create a GHL workflow or Make scenario**: Design your automation in GHL or Make, connecting the necessary apps and services.
+
+2. **Import the workflow/scenario into Vapi**: In the Vapi dashboard, navigate to the Tools section and click on "Import." Select the GHL workflow or Make scenario you want to import.
+
+3. **Configure the Tool**: Provide a name and description for the imported Tool, and map any required input variables to the corresponding Vapi entities (e.g., extracted from user speech).
+
+4. **Add the Tool to your assistant**: Edit your AI assistant and add the newly imported Tool to its capabilities. Specify the voice commands that should trigger the Tool.
+
+5. **Test the integration**: Engage with your AI assistant using the specified voice commands and verify that the corresponding GHL workflow or Make scenario is triggered successfully.
+
+## Use case examples
+
+### Booking appointments with AI callers
+
+- Import a GHL workflow that handles appointment booking
+- Configure the workflow to accept appointment details (date, time, user info) from Vapi
+- Add the Tool to your AI assistant, allowing it to book appointments based on voice commands
+
+### Updating CRMs with voice-gathered data
+
+- Import a Make scenario that updates your CRM with customer information
+- Map the scenario's input variables to entities extracted from user speech
+- Enable your AI assistant to gather customer information via voice and automatically update your CRM
+
+### Real Estate: Automated Property Information Retrieval
+
+- Import a Make scenario that retrieves property information from your MLS (Multiple Listing Service) or real estate database
+- Configure the scenario to accept a property address or MLS ID as input
+- Add the Tool to your AI assistant, allowing potential buyers to request property details using voice commands
+- Your AI assistant can then provide key information about the property, such as price, square footage, number of bedrooms/bathrooms, and amenities
+
+### Healthcare/Telehealth: Appointment Reminders and Prescription Refills
+
+- Import a GHL workflow that sends appointment reminders and handles prescription refill requests
+- Configure the workflow to accept patient information and appointment/prescription details from Vapi
+- Add the Tool to your AI assistant, enabling patients to request appointment reminders or prescription refills using voice commands
+- Your AI assistant can confirm the appointment details, send reminders via SMS or email, and forward prescription refill requests to the appropriate healthcare provider
+
+### Restaurant Ordering: Custom Order Placement and Delivery Tracking
+
+- Import a Make scenario that integrates with your restaurant's online ordering system and delivery tracking platform
+- Configure the scenario to accept customer information, order details, and delivery preferences from Vapi
+- Add the Tool to your AI assistant, allowing customers to place custom orders and track their delivery status using voice commands
+- Your AI assistant can guide customers through the ordering process, suggest menu items based on preferences, and provide real-time updates on the order status and estimated delivery time
+
+## Best practices
+
+- Break down complex automations into smaller, focused workflows or scenarios for better maintainability
+- Use clear and concise naming conventions for your imported Tools and their input variables
+- Thoroughly test the integration to ensure reliable performance and accurate data passing
+- Keep your GHL workflows and Make scenarios up to date to reflect any changes in the connected apps or services
+
+## Troubleshooting
+
+- If a Tool is not triggering as expected, verify that the voice commands are correctly configured and the input variables are properly mapped
+- Check the Vapi logs and the GHL/Make execution logs to identify any errors or issues in the automation flow
+- Ensure that the necessary API credentials and permissions are correctly set up in both Vapi and the integrated apps/services
+
+By leveraging Vapi's GHL/Make Tools integration, you can create powerful voice-enabled automations and streamline your workflows, all without extensive coding. Automate tasks, connect your favorite apps, and unlock the full potential of voice AI with Vapi.
+
+## Get Support
+
+Join our Discord to connect with other developers & connect with our team:
+
+
+
+ Connect with our team & other developers using Vapi.
+
+
+ Send our support team an email.
+
+
+
+Here are some video tutorials that will guide you on how to use Vapi with services like Make and GoHighLevel:
+
+
+
+
+
+
+
+
+
+
+ This is the content for the doc fern/advanced/sip/sip-plivo.mdx
+
+ ---
+title: Plivo SIP Integration
+subtitle: How to integrate Plivo SIP with Vapi
+slug: advanced/sip/plivo
+---
+
+
+Please note that Indian numbers cannot be obtained from Plivo for use with Vapi. This is due to TRAI regulations, which mandate SIP termination to occur via an Indian server—a requirement we currently do not fulfill.
+
+
+This guide walks you through setting up both outbound and inbound SIP trunking between Plivo and Vapi.
+
+## Outbound Calls (Plivo to Vapi)
+
+### Plivo Configuration
+
+1. **Login to Plivo Console**
+
+ Access the Plivo console at [https://console.plivo.com/accounts/login/](https://console.plivo.com/accounts/login/)
+
+2. **Create IP Access Control List**
+
+ Navigate to: Zentrunk(SIP) → Outbound Trunks → IP Access Control List → Create New IP Group
+
+ - Name: Choose a descriptive name
+ - IP Address List: Whitelist Vapi's fixed IPs:
+ - 44.229.228.186/32
+ - 44.238.177.138/32
+ - Click "Create ACL"
+
+ 
+
+3. **Create Outbound Trunk**
+
+ Navigate to: Zentrunk(SIP) → Outbound Trunks → Trunks → Create New Outbound Trunk
+
+ - Trunk Name: Choose a descriptive name
+ - IP Access Control List: Select the IP ACL created in the previous step
+ - Click "Create Trunk"
+
+ 
+
+4. **Note Your Termination SIP Domain**
+
+ After creating the trunk, note the Termination SIP Domain (format: 12700668357XXXXXX.zt.plivo.com)
+
+ 
+
+5. **Purchase a Phone Number**
+
+ Navigate to: Numbers → Buy a new number
+
+ 
+
+### Vapi Configuration
+
+1. **Get Your Vapi API Key**
+
+ Sign in to the Vapi dashboard at [https://dashboard.vapi.ai/](https://dashboard.vapi.ai/) and retrieve your API key
+
+ 
+
+2. **Create a SIP Trunk Credential**
+
+ Use the following API call, replacing the gateway IP with your Plivo Termination SIP Domain:
+
+ ```bash
+ curl -X POST https://api.vapi.ai/credential \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer your-vapi-private-api-key" \
+ -d '{
+ "provider": "byo-sip-trunk",
+ "name": "PLIVO Trunk",
+ "gateways": [
+ {
+ "ip": "1270066835XXXXXXXXX.zt.plivo.com"
+ }
+ ]
+ }'
+ ```
+
+ 
+
+ Note the `id` (credentialId) from the response for the next step.
+
+3. **Register Your Phone Number**
+
+ Associate your Plivo number with the SIP trunk:
+
+ ```bash
+ curl -X POST https://api.vapi.ai/phone-number \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer your-vapi-private-api-key" \
+ -d '{
+ "provider": "byo-phone-number",
+ "name": "PLIVO SIP Number",
+ "number": "1833684XXXX",
+ "numberE164CheckEnabled": false,
+ "credentialId": "a2c815b8-03f4-40f5-813c-xxxxxxxxxxxx"
+ }'
+ ```
+
+ 
+
+ Note the phone number ID from the response for making calls.
+
+4. **Create a Vapi Assistant**
+
+ Follow the steps at [https://docs.vapi.ai/quickstart/dashboard#create-an-assistant](https://docs.vapi.ai/quickstart/dashboard#create-an-assistant)
+
+ 
+
+ Note your Assistant ID for making calls.
+
+5. **Make Outbound Calls**
+
+ **Using the API:**
+
+ ```bash
+ curl --location 'https://api.vapi.ai/call/phone' \
+ --header 'Authorization: Bearer your-vapi-private-api-key' \
+ --header 'Content-Type: application/json' \
+ --data '{
+ "assistantId": "29d47d31-ba3c-451c-86ce-xxxxxxxxx",
+ "customer": {
+ "number": "9199437XXXXX",
+ "numberE164CheckEnabled": false
+ },
+ "phoneNumberId": "eba2fb13-259f-4123-abfa-xxxxxxxxxxx"
+ }'
+ ```
+
+ 
+
+ **Using the Vapi Dashboard:**
+
+ Select your Assistant and enter the destination number you want to call.
+
+ 
+
+## Inbound Calls (Vapi to Plivo)
+
+### Plivo Configuration
+
+1. **Login to Plivo Console**
+
+ Access the Plivo console at [https://console.plivo.com/accounts/login/](https://console.plivo.com/accounts/login/)
+
+2. **Create Origination URI**
+
+ Navigate to: Zentrunk(SIP) → Inbound Trunks → Origination URI → Create New IP URI
+
+ - Name: Choose a descriptive name
+ - URI: Enter Vapi's SIP URI: `sip.vapi.ai;transport=udp`
+ - Click "Create URI"
+
+ 
+
+3. **Create Inbound Trunk**
+
+ Navigate to: Zentrunk(SIP) → Inbound Trunks → Trunks → Create New Inbound Trunk
+
+ - Trunk Name: Choose a descriptive name
+ - Primary URI: Select the URI created in the previous step
+ - Click "Create Trunk"
+
+ 
+
+4. **Attach Phone Number to Inbound Trunk**
+
+ Navigate to: Phone Numbers → Select your purchased number
+
+ - In the Application dropdown, select "Zentrunk"
+ - In the Zentrunk dropdown, select your inbound trunk
+ - Save the changes
+
+ 
+
+### Vapi Configuration
+
+1. **Get Your Vapi API Key**
+
+ Sign in to the Vapi dashboard at [https://dashboard.vapi.ai/](https://dashboard.vapi.ai/) and retrieve your API key
+
+2. **Create an Inbound SIP Trunk Credential**
+
+ ```bash
+ curl -X POST https://api.vapi.ai/credential \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer your-vapi-private-api-key" \
+ -d '{
+ "provider": "byo-sip-trunk",
+ "name": "PLIVO Inbound Trunk",
+ "type": "inbound"
+ }'
+ ```
+
+ Note the `id` (credentialId) from the response for the next step.
+
+3. **Register Your Phone Number**
+
+ ```bash
+ curl -X POST https://api.vapi.ai/phone-number \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer your-vapi-private-api-key" \
+ -d '{
+ "provider": "byo-phone-number",
+ "name": "PLIVO SIP Inbound Number",
+ "number": "1833684XXXX",
+ "numberE164CheckEnabled": false,
+ "credentialId": "a2c815b8-03f4-40f5-813c-xxxxxxxxxxxx"
+ }'
+ ```
+
+4. **Create and Configure a Vapi Assistant**
+
+ - Create an assistant following the steps at [https://docs.vapi.ai/quickstart/dashboard#create-an-assistant](https://docs.vapi.ai/quickstart/dashboard#create-an-assistant)
+ - In the assistant settings, link it to the phone number you created
+
+ Now when someone calls your Plivo number, the call will be routed to your Vapi assistant.
+
+
+ This is the content for the doc fern/advanced/sip/sip-telnyx.mdx
+
+ ---
+title: Telnyx SIP Integration
+subtitle: How to integrate SIP Telnyx to Vapi
+slug: advanced/sip/telnyx
+---
+
+Integrate your Telnyx SIP trunk with Vapi.ai to enable your AI voice assistants to handle calls efficiently. This guide walks you through the complete setup process for both inbound and outbound calls.
+
+## 1. Retrieve Your Vapi.ai Private Key
+
+- Log in to your Vapi.ai account
+- Navigate to **Organization Settings**
+- In the **API Keys** section, copy your **Private Key**
+
+## 2. Configure Telnyx for Inbound Calls
+
+To allow Telnyx to forward incoming calls to Vapi.ai:
+
+1. **Create a SIP Trunk**
+ - Go to Voice / SIP Trunking / Create
+ - Select FQDN
+ - Click "Add FQDN"
+ - Select A record type
+ - Set FQDN to: `sip.vapi.ai`
+ - Port should be 5060 by default
+
+2. **Configure Inbound Settings**
+ - Navigate to the Inbound tab of your SIP trunk
+ - Configure settings as shown:
+
+
+
+
+3. **Assign Phone Number**
+ - Go to the Numbers tab
+ - Assign your acquired phone number to the SIP trunk
+
+4. **Configure SIP Invite**
+ - Go to Numbers, edit the number you'll be using
+ - Navigate to Voice settings
+ - Scroll down to find "Translated Number"
+ - Set this value to match your Vapi SIP URI
+
+ *This setting modifies the SIP Invite to the Vapi platform so invites are correctly routed to your Vapi SIP URI.*
+
+## 3. Configure Telnyx for Outbound Calls
+
+To allow Vapi.ai to make outbound calls through your Telnyx account:
+
+1. **Set Up Outbound Authentication**
+ - Go to Voice / SIP Trunking / Authentication and routing
+ - Scroll down to "Outbound calls authentication"
+ - Create a new credential for Vapi to use
+
+
+
+
+2. **Create Outbound Voice Profile**
+ - Go to Voice / Outbound Voice Profiles
+ - Create a new profile
+ - Name it appropriately
+ - Configure desired destinations
+ - Leave default configuration settings
+ - Assign your SIP trunk
+ - Complete setup
+
+ Alternatively, go to your SIP trunk / Outbound tab and select your newly created outbound voice profile.
+
+3. **Configure Outbound Settings**
+ - Choose the country you'll be making most calls to
+
+ *We recommend creating a separate SIP Trunk for each country you aim to be making most calls to.*
+
+
+
+
+## 4. Add Your Telnyx SIP Credentials to Vapi.ai
+
+Use the Vapi API to create a SIP trunk credential:
+
+```bash
+curl -X POST https://api.vapi.ai/credential \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_VAPI_PRIVATE_KEY" \
+ -d '{
+ "provider": "byo-sip-trunk",
+ "name": "Telnyx Trunk",
+ "gateways": [
+ {
+ "ip": "sip.telnyx.com"
+ }
+ ],
+ "outboundAuthenticationPlan": {
+ "authUsername": "YOUR_SIP_USERNAME",
+ "authPassword": "YOUR_SIP_PASSWORD",
+ "sipRegisterPlan": {
+ "realm": "sip.telnyx.com"
+ }
+ }
+ }'
+```
+
+Replace `YOUR_VAPI_PRIVATE_KEY`, `YOUR_SIP_USERNAME`, and `YOUR_SIP_PASSWORD` with your actual credentials.
+
+If successful, the response will include an `id` for the created credential, which you'll use in the next step.
+
+## 5. Add Your Phone Number to Vapi.ai
+
+Associate your phone number with the SIP trunk in Vapi.ai:
+
+```bash
+curl -X POST https://api.vapi.ai/phone-number \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_VAPI_PRIVATE_KEY" \
+ -d '{
+ "provider": "byo-phone-number",
+ "name": "Telnyx SIP Number",
+ "number": "YOUR_PHONE_NUMBER",
+ "numberE164CheckEnabled": false,
+ "credentialId": "YOUR_CREDENTIAL_ID"
+ }'
+```
+
+Replace `YOUR_VAPI_PRIVATE_KEY`, `YOUR_PHONE_NUMBER`, and `YOUR_CREDENTIAL_ID` with your actual details.
+
+## 6. Assign Your Voice Assistant to Handle Calls
+
+- In your Vapi.ai dashboard, go to the **Build** section and select **Phone Numbers**
+- Click on your **Telnyx Number**
+- In the **Inbound Settings** section, assign your voice assistant to handle incoming calls
+- In the **Outbound Form** section, assign your voice assistant to handle outgoing calls
+
+## 7. Make Outbound Calls
+
+To initiate outbound calls through your Telnyx SIP trunk:
+
+```bash
+curl --location 'https://api.vapi.ai/call/phone' \
+ --header 'Authorization: Bearer YOUR_VAPI_PRIVATE_KEY' \
+ --header 'Content-Type: application/json' \
+ --data '{
+ "assistantId": "YOUR_ASSISTANT_ID",
+ "customer": {
+ "number": "CUSTOMER_PHONE_NUMBER",
+ "numberE164CheckEnabled": false
+ },
+ "phoneNumberId": "YOUR_PHONE_ID"
+ }'
+```
+
+Replace all placeholder values with your actual information.
+
+By following these steps, your Telnyx SIP trunk will be fully integrated with Vapi.ai, allowing your AI voice assistants to manage calls effectively.
+
+
+ This is the content for the doc fern/advanced/sip/sip-trunk.mdx
+
+ ---
+title: SIP Trunking Guide for Vapi
+subtitle: How to integrate your SIP provider with Vapi
+slug: advanced/sip/sip-trunk
+---
+
+SIP trunking replaces traditional phone lines with a virtual connection over the internet, allowing your business to make and receive calls via a broadband connection. It connects your internal PBX or VoIP system to a SIP provider, which then routes calls to the Public Switched Telephone Network (PSTN). This setup simplifies your communications infrastructure and often reduces costs.
+
+## 1. Vapi SIP Trunking Options
+
+Vapi supports multiple SIP trunk configurations, including:
+
+- **Telnyx**: Uses SIP gateway domain (e.g., sip.telnyx.com) with IP-based authentication.
+- **Zadarma**: Uses SIP credentials (username/password) with its SIP server (e.g., sip.zadarma.com).
+- **Custom "BYO" SIP Trunk**: Allows integration with any SIP provider. You simply provide the SIP gateway address and the necessary authentication details.
+
+
+Our IP Addresses are:
+
+- 44.229.228.186/32
+- 44.238.177.138/32
+
+However, 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.
+
+
+## 2. Setup Process Overview
+
+To set up a SIP trunk in Vapi, follow these steps:
+
+### Obtain Provider Details
+
+Gather the SIP server address, authentication credentials (username/password or IP-based), and at least one phone number (DID) from your provider.
+
+### Create a SIP Trunk Credential in Vapi
+
+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.
+
+**Example (using Zadarma):**
+
+```bash
+curl -X POST "https://api.vapi.ai/credential" \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_VAPI_PRIVATE_KEY" \
+ -d '{
+ "provider": "byo-sip-trunk",
+ "name": "Zadarma Trunk",
+ "gateways": [{
+ "ip": "sip.zadarma.com"
+ }],
+ "outboundLeadingPlusEnabled": true,
+ "outboundAuthenticationPlan": {
+ "authUsername": "YOUR_SIP_NUMBER",
+ "authPassword": "YOUR_SIP_PASSWORD"
+ }
+ }'
+```
+
+Save the returned Credential ID for later use.
+
+### Associate a Phone Number with the SIP Trunk
+
+Link your external phone number (DID) to the SIP trunk credential in Vapi by creating a Phone Number resource.
+
+**Example:**
+
+```bash
+curl -X POST "https://api.vapi.ai/phone-number" \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_VAPI_PRIVATE_KEY" \
+ -d '{
+ "provider": "byo-phone-number",
+ "name": "Zadarma Number",
+ "number": "15551234567",
+ "numberE164CheckEnabled": false,
+ "credentialId": "YOUR_CREDENTIAL_ID"
+ }'
+```
+
+Note the returned Phone Number ID for use in test calls.
+
+### Test Your SIP Trunk
+
+#### Outbound Call Test
+
+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"
+}
+```
+
+#### Inbound Call Test
+
+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).
+
+#### SIP REFER (Call Transfer)
+
+If you need to transfer a call to another number, you will need to add a SIP Transfer based call forwarding where transfer number will look like this: sip:transfer-number@your-telecom-provider-domain.com
+
+Example: sip:15557654321@sip.zadarma.com
+
+Example tool configuration required for SIP REFER:
+
+```json
+{
+ "type": "transferCall",
+ "destinations": [
+ {
+ "type": "sip",
+ "sipUri": "sip:14039932200@sip.telnyx.com"
+ }
+ ]
+ }
+```
+
+You might need to enable SIP REFER in your SIP provider to allow this.
+
+
+
+
+ This is the content for the doc fern/advanced/sip/sip-twilio.mdx
+
+ ---
+title: Twilio SIP Integration
+subtitle: How to integrate Twilio SIP with Vapi
+slug: advanced/sip/twilio
+---
+
+
+
+
+
+
+
+This guide walks you through setting up both outbound and inbound SIP trunking between Twilio and Vapi. The steps are quite similar for other telephony providers.
+
+## Outbound Calls (Twilio to Vapi)
+
+### Twilio Configuration
+
+1. **Create Elastic SIP Trunk**
+
+ Log in to your Twilio account and create a new trunk, assigning it a name, and adjusting the general settings as needed.
+
+ 
+
+2. **Set Up Termination (Outbound Calls)**
+
+ Configure the termination settings. The termination SIP URI is crucial as it will be used in later steps.
+
+ 
+
+ To allow your Elastic SIP Trunk to accept outbound requests, you need to whitelist IP addresses:
+
+ 
+
+ Whitelist Vapi's SIP server static IPs:
+ - 44.229.228.186
+ - 44.238.177.138
+
+ Ensure you whitelist the entire IP range as shown below:
+
+ 
+
+ 
+
+3. **Purchase or Move Numbers to Elastic SIP Trunk**
+
+ After creating the Elastic SIP trunk, purchase new numbers or move existing numbers to this trunk.
+
+ 
+
+### Vapi Configuration
+
+1. **Retrieve Your Vapi API Key**
+
+ Log in to your Vapi.ai account and retrieve your API key from the Organization Settings.
+
+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:
+
+ ```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": "Twilio Trunk",
+ "gateways": [
+ {
+ "ip": "YOUR_TWILIO_GATEWAY_ID"
+ }
+ ],
+ "outboundLeadingPlusEnabled": true
+ }'
+ ```
+
+ Note the `id` (credentialId) from the response for the next step.
+
+3. **Register Your Phone Number**
+
+ Associate your Twilio number with the 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": "Twilio SIP Number",
+ "number": "YOUR_SIP_PHONE_NUMBER",
+ "numberE164CheckEnabled": false,
+ "credentialId": "YOUR_CREDENTIAL_ID"
+ }'
+ ```
+
+ Note the phone number ID from the response for making calls.
+
+4. **Make Outbound Calls**
+
+ You can make outbound calls in two ways:
+
+ **Using the Vapi Dashboard:**
+
+ The phone number will appear in your dashboard. Select your assistant and enter the destination number you want to call.
+
+ **Using the API:**
+
+ ```bash
+ curl --location 'https://api.vapi.ai/call/phone' \
+ --header 'Authorization: Bearer YOUR_VAPI_API_KEY' \
+ --header 'Content-Type: application/json' \
+ --data '{
+ "assistantId": "YOUR_ASSISTANT_ID",
+ "customer": {
+ "number": "DESTINATION_PHONE_NUMBER",
+ "numberE164CheckEnabled": false
+ },
+ "phoneNumberId": "YOUR_PHONE_NUMBER_ID"
+ }'
+ ```
+
+## Inbound Calls (Vapi to Twilio)
+
+### Twilio Configuration
+
+1. **Set Up Origination (Inbound Calls)**
+
+ Navigate to the Origination section in your Twilio SIP Trunk settings.
+
+ 
+
+ 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.
+
+ 
+
+### Vapi Configuration
+
+1. **Create and Configure a Vapi Assistant**
+
+ - Create an assistant following the steps at [https://docs.vapi.ai/quickstart/dashboard#create-an-assistant](https://docs.vapi.ai/quickstart/dashboard#create-an-assistant)
+ - 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.
+
+
+ This is the content for the doc fern/advanced/sip/sip-zadarma.mdx
+
+ ---
+title: Zadarma SIP Integration
+subtitle: How to integrate SIP Zadarma to Vapi
+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
+
+- Log in to your Vapi.ai account.
+- Navigate to **Organization Settings**.
+- In the **API Keys** section, copy your **Private Key**.
+
+## 2. Add Your Zadarma SIP Credentials to Vapi.ai
+
+You'll need to send a `curl` request to Vapi.ai's API to add your SIP credentials:
+
+- **Private Key**: Your Vapi.ai private key.
+- **Trunk Name**: A name for your SIP trunk (e.g., "Zadarma Trunk").
+- **Server Address**: The server address provided by Zadarma (e.g., "sip.zadarma.com").
+- **SIP Number**: Your Zadarma SIP number.
+- **SIP Password**: The password for your Zadarma SIP number.
+
+Here's the `curl` command to execute:
+
+```bash
+curl -L 'https://api.vapi.ai/credential' \\
+-H 'Content-Type: application/json' \\
+-H 'Authorization: Bearer YOUR_PRIVATE_KEY' \\
+-d '{
+ "provider": "byo-sip-trunk",
+ "name": "Zadarma Trunk",
+ "gateways": [
+ { "ip": "sip.zadarma.com" }
+ ],
+ "outboundLeadingPlusEnabled": true,
+ "outboundAuthenticationPlan": {
+ "authUsername": "YOUR_SIP_NUMBER",
+ "authPassword": "YOUR_SIP_PASSWORD"
+ }
+}'
+```
+Replace `YOUR_PRIVATE_KEY`, `YOUR_SIP_NUMBER`, and `YOUR_SIP_PASSWORD` with your actual credentials.
+
+If successful, the response will include an `id` for the created credential, which you'll use in the next step.
+
+## 3. Add Your Virtual Number to Vapi.ai
+
+Next, associate your virtual number with the SIP trunk in Vapi.ai:
+
+- **Private Key**: Your Vapi.ai private key.
+- **Number Name**: A name for your virtual number (e.g., "Zadarma Number").
+- **Virtual Number**: Your Zadarma virtual number in international format (e.g., "15551111111").
+- **Credential ID**: The `id` from the previous step.
+
+Use the following `curl` command:
+
+```bash
+curl -L 'https://api.vapi.ai/phone-number' \\
+-H 'Content-Type: application/json' \\
+-H 'Authorization: Bearer YOUR_PRIVATE_KEY' \\
+-d '{
+ "provider": "byo-phone-number",
+ "name": "Zadarma Number",
+ "number": "YOUR_VIRTUAL_NUMBER",
+ "numberE164CheckEnabled": false,
+ "credentialId": "YOUR_CREDENTIAL_ID"
+}'
+```
+
+Replace `YOUR_PRIVATE_KEY`, `YOUR_VIRTUAL_NUMBER`, and `YOUR_CREDENTIAL_ID` with your actual details.
+
+## 4. Assign Your Voice Assistant to Handle Calls
+
+- In your Vapi.ai dashboard, go to the **Build** section and select **Phone Numbers**.
+- Click on your **Zadarma Number**.
+- In the **Inbound Settings** section, assign your voice assistant to handle incoming calls.
+- In the **Outbound Form** section, assign your voice assistant to handle outgoing calls.
+
+## 5. Configure Incoming Call Reception in Zadarma
+
+To forward incoming calls from your Zadarma virtual number to Vapi.ai:
+
+- Log in to your Zadarma account.
+- Navigate to **Settings** → **Virtual phone numbers**.
+- 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).
+- 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.
+
+
+ This is the content for the doc fern/advanced/sip/sip.mdx
+
+ ---
+title: SIP Introduction
+subtitle: You can make SIP calls to Vapi Assistants.
+slug: advanced/sip
+---
+
+
+
+
+We'll create an assistant with `POST /assistant` endpoint. This is no different than creating an assistant for other transports.
+
+```json
+{
+ "name": "My SIP Assistant",
+ "firstMessage": "Hello {{first_name}}, you've reached me over SIP."
+}
+
+```
+
+
+
+
+We'll create a SIP phone number with `POST /phone-number` endpoint.
+
+```json
+{
+ "provider": "vapi",
+ "sipUri": "sip:your_unique_user_name@sip.vapi.ai",
+ "assistantId": "your_assistant_id"
+}
+
+```
+
+`sipUri` is the SIP URI of the phone number. It must be in the format `sip:username@sip.vapi.ai`. You are free to choose any username you like.
+
+
+
+
+
+
+
+You can use any SIP softphone to test the Assistant. Examples include [Zoiper](https://www.zoiper.com/) or [Linphone](https://www.linphone.org/).
+
+You just need to dial `sip:your_unique_user_name@sip.vapi.ai` and the Assistant will answer your call.
+
+There is no authentication or SIP registration required.
+
+
+
+
+
+
+To fill your template variables, you can send custom SIP headers.
+
+For example, to fill the `first_name` variable, you can send a SIP header `x-first_name: John`.
+
+The header name is case insensitive. So, `X-First_Name`, `x-first_name`, and `X-FIRST_NAME` are all the same.
+
+
+
+
+
+
+You can use a custom assistant for SIP calls same as phone calls.
+
+Set the `assistantId` to `null` and the `serverUrl` to the URL of your server which will respond to the `assistant-request`.
+
+`PATCH /phone-number/:id`
+```json
+{
+ "assistantId": null,
+ "serverUrl": "https://your_server_url"
+}
+```
+
+Now, every time you make a call to this phone number, the server will receive a `assistant-request` event.
+
+
+
+
+
+
+ This is the content for the doc fern/api-reference/openapi.mdx
+
+ ---
+title: OpenAPI
+slug: api-reference/openapi
+---
+
+
+
+ Our OpenAPI is hosted at
+ [https://api.vapi.ai/api-json](https://api.vapi.ai/api-json)
+
+
+
+ This is the content for the doc fern/api-reference/swagger.mdx
+
+ ---
+title: Swagger
+slug: api-reference/swagger
+---
+
+
+
+ Our Swagger is hosted at [https://api.vapi.ai/api](https://api.vapi.ai/api)
+
+
+
+ This is the content for the doc fern/assistants.mdx
+
+ ---
+title: Introduction to Assistants
+subtitle: The core building-block of voice agents on Vapi.
+slug: assistants
+---
+
+[**Assistant**](/api-reference/assistants/create) is a fancy word for an AI configuration that can be used across phone calls and Vapi clients. Your voice assistant can augment your customer support and experience for call centers, business websites, mobile apps, and much more.
+
+
+
+## Core Components
+
+There are three core components that make up an assistant:
+
+- **Transcriber**: Converts spoken audio into text
+- **Model**: The AI model that processes the text and generates responses
+- **Voice**: The voice that speaks the AI's responses
+
+These components can be configured, mixed, and matched for your specific use case.
+
+
+ View all configurable properties in the [API Reference](/api-reference/assistants/create-assistant).
+
+
+## Key Features
+
+### Dynamic Variables
+Personalize your assistant's responses using variables that can be customized for each call. This allows you to:
+- Insert dynamic content like dates, times, and user information
+- Customize greetings and responses
+- Maintain context across conversations
+
+### Call Analysis
+Get detailed insights into each conversation through:
+- Call summaries
+- Structured data extraction
+- Success evaluation metrics
+- Custom analysis rubrics
+
+### Persistence Options
+Choose between:
+- **Persistent Assistants**: Reusable configurations stored via the `/assistant` endpoint
+- **Temporary Assistants**: One-time configurations specified when starting a call
+
+## Prompting Best Practices
+
+Effective prompt engineering is crucial for creating successful voice AI agents. Learn how to:
+- Structure prompts for voice interactions
+- Add personality and natural speech patterns
+- Handle errors gracefully
+- Improve response quality
+
+
+ Learn best practices for engineering voice AI prompts
+
+
+## Advanced Concepts
+
+
+
+ Add your API keys for other providers
+
+
+ Plug in your own LLM
+
+
+ Forward and hang up with function calls
+
+
+ Which setup is best for you?
+
+
+
+
+ This is the content for the doc fern/assistants/assistant-hooks.mdx
+
+ ---
+title: Assistant Hooks
+slug: assistants/assistant-hooks
+---
+
+# Assistant Hooks
+
+Assistant hooks allow you to configure actions that will be performed when specific events occur during a call. Currently, hooks support the `call.ending` event, which triggers when a call is ending.
+
+## Usage
+
+Hooks are defined in the `hooks` array of an assistant. Each hook consists of:
+
+- `on`: The event that triggers the hook (currently only supports `call.ending`)
+- `do`: The actions to perform when the hook triggers (currently only supports `transfer`)
+- `filters`: Optional conditions that must be met for the hook to trigger
+
+The `call.endedReason` field in filters can be set to any of the [call ended reasons](https://docs.vapi.ai/api-reference/calls/get#response.body.endedReason). The transfer destination type follows the same schema as the [transfer call tool destinations](https://docs.vapi.ai/api-reference/tools/create#request.body.transferCall.destinations).
+
+Note: Using `"oneOf": ["pipeline-error"]` acts as a catch-all filter that matches any pipeline-related error reason. This is useful when you want to handle all types of pipeline failures with the same transfer action.
+
+## Example: Transfer on Pipeline Error
+
+This example shows how to transfer a call to a fallback number when a pipeline error occurs. The hook will trigger when the call is ending due to a pipeline error, and transfer the call to a specified phone number:
+
+```bash
+curl -X PATCH "https://api.vapi.ai/assistant/" \
+ -H "Authorization: Bearer " \
+ -H "Content-Type: application/json" \
+ -d '{
+ "hooks": [{
+ "on": "call.ending",
+ "filters": [{
+ "type": "oneOf",
+ "key": "call.endedReason",
+ "oneOf": ["pipeline-error"]
+ }],
+ "do": [{
+ "type": "transfer",
+ "destination": {
+ "type": "number",
+ "number": "+1234567890",
+ "callerId": "+1987654321"
+ }
+ }]
+ }]
+}'
+```
+
+You can also transfer to a SIP destination:
+
+```bash
+curl -X PATCH "https://api.vapi.ai/assistant/" \
+ -H "Authorization: Bearer " \
+ -H "Content-Type: application/json" \
+ -d '{
+ "hooks": [{
+ "on": "call.ending",
+ "filters": [{
+ "type": "oneOf",
+ "key": "call.endedReason",
+ "oneOf": ["pipeline-error"]
+ }],
+ "do": [{
+ "type": "transfer",
+ "destination": {
+ "type": "sip",
+ "sipUri": "sip:user@domain.com"
+ }
+ }]
+ }]
+}'
+```
+
+Common use cases for hooks include:
+- Transferring to a human agent on errors
+- Routing to a fallback system if the assistant fails
+- Ensuring calls are handled gracefully in edge cases
+
+ This is the content for the doc fern/assistants/background-messages.mdx
+
+ ---
+title: Background Messaging
+subtitle: >-
+ Vapi SDK lets you silently update the chat history through efficient text
+ message integration. This is particularly useful for background tasks or
+ discreetly logging user interactions.
+slug: assistants/background-messages
+---
+
+
+## Scenario Overview
+
+As a developer you may run into scenarios where a user action, such as pressing a button, needs to be logged in the chat history without overt user involvement. This could be crucial for maintaining conversation context or system logging purposes.
+
+
+
+ Add a button to your interface with an `onClick` event handler that will call a function to send the system message:
+ ```html
+
+ ```
+
+
+
+ When the button is clicked, the `logUserAction` function will silently insert a system message into the chat history:
+ ```js
+ function logUserAction() {
+ // Function to log the user action
+ vapi.send({
+ type: "add-message",
+ message: {
+ role: "system",
+ content: "The user has pressed the button, say peanuts",
+ },
+ });
+ }
+ ```
+ - `vapi.send`: The primary function to interact with your assistant, handling various requests or commands.
+ - `type: "add-message"`: Specifies the command to add a new message.
+ - `message`: This is the actual message that you want to add to the message history.
+ - `role`: "system" Designates the message origin as 'system', ensuring the addition is unobtrusive. Other possible values of role are 'user' | 'assistant' | 'tool' | 'function'
+ - `content`: The actual message text to be added.
+
+
+
+
+ - Silent logging of user activities.
+ - Contextual updates in conversations triggered by background processes.
+ - Non-intrusive user experience enhancements through additional information provision.
+
+
+
+ This is the content for the doc fern/assistants/call-analysis.mdx
+
+ ---
+title: Call Analysis
+subtitle: At the end of the call, you can summarize and evaluate how it went.
+slug: assistants/call-analysis
+---
+
+
+The Call Analysis feature allows you to summarize and evaluate calls, providing valuable insights into their effectiveness. This feature uses a combination of prompts and schemas to generate structured data and success evaluations based on the call's content. The underlying models driving our call analysis pipeline are the latest version of Anthropic's Claude Sonnet and in case of failure OpenAI's GPT 4o.
+
+You can customize the below in the assistant's `assistant.analysisPlan`.
+
+## Summary Prompt
+
+The summary prompt is used to create a concise summary of the call. This summary is stored in `call.analysis.summary`.
+
+### Default Summary Prompt
+
+The default summary prompt is:
+
+```text
+You are an expert note-taker. You will be given a transcript of a call. Summarize the call in 2-3 sentences, if applicable.
+```
+
+### Customizing the Summary Prompt
+
+You can customize the summary prompt by setting the `summaryPrompt` property in the API or SDK:
+
+```json
+{
+ "summaryPrompt": "Custom summary prompt text"
+}
+```
+
+To disable the summary prompt, set it to an empty string `""` or `"off"`:
+
+```json
+{
+ "summaryPrompt": ""
+}
+```
+
+## Structured Data Prompt
+
+The structured data prompt extracts specific pieces of data from the call. This data is stored in `call.analysis.structuredData`.
+
+### Default Structured Data Prompt
+
+The default structured data prompt is:
+
+```text
+You are an expert data extractor. You will be given a transcript of a call. Extract structured data per the JSON Schema.
+```
+
+### Customizing the Structured Data Prompt
+
+You can set a custom structured data prompt using the `structuredDataPrompt` property:
+
+```json
+{
+ "structuredDataPrompt": "Custom structured data prompt text"
+}
+```
+
+## Structured Data Schema
+
+The structured data schema enforces the format of the extracted data. It is defined using JSON Schema standards.
+
+### Customizing the Structured Data Schema
+
+You can set a custom structured data schema using the `structuredDataSchema` property:
+
+```json
+{
+ "structuredDataSchema": {
+ "type": "object",
+ "properties": {
+ "field1": { "type": "string" },
+ "field2": { "type": "number" }
+ },
+ "required": ["field1", "field2"]
+ }
+}
+```
+
+## Success Evaluation Prompt
+
+The success evaluation prompt is used to determine if the call was successful. This evaluation is stored in `call.analysis.successEvaluation`.
+
+### Default Success Evaluation Prompt
+
+The default success evaluation prompt is:
+
+```text
+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.
+```
+
+### Customizing the Success Evaluation Prompt
+
+You can set a custom success evaluation prompt using the `successEvaluationPrompt` property:
+
+```json
+{
+ "successEvaluationPrompt": "Custom success evaluation prompt text"
+}
+```
+
+To disable the success evaluation prompt, set it to an empty string `""` or `"off"`:
+
+```json
+{
+ "successEvaluationPrompt": ""
+}
+```
+
+## Success Evaluation Rubric
+
+The success evaluation rubric defines the criteria used to evaluate the call's success. The available rubrics are:
+
+- `NumericScale`: A scale of 1 to 10.
+- `DescriptiveScale`: A scale of Excellent, Good, Fair, Poor.
+- `Checklist`: A checklist of criteria and their status.
+- `Matrix`: A grid that evaluates multiple criteria across different performance levels.
+- `PercentageScale`: A scale of 0% to 100%.
+- `LikertScale`: A scale of Strongly Agree, Agree, Neutral, Disagree, Strongly Disagree.
+- `AutomaticRubric`: Automatically break down evaluation into several criteria, each with its own score.
+- `PassFail`: A simple 'true' if the call passed, 'false' if not.
+
+### Customizing the Success Evaluation Rubric
+
+You can set a custom success evaluation rubric using the `successEvaluationRubric` property:
+
+```json
+{
+ "successEvaluationRubric": "NumericScale"
+}
+```
+
+## Combining Prompts and Rubrics
+
+You can use prompts and rubrics in combination to create detailed instructions for the call analysis:
+
+```json
+{
+ "successEvaluationPrompt": "Evaluate the call based on these criteria:...",
+ "successEvaluationRubric": "Checklist"
+}
+```
+
+By customizing these properties, you can tailor the call analysis to meet your specific needs and gain valuable insights from your calls.
+
+
+ This is the content for the doc fern/assistants/call-recording.mdx
+
+ ---
+title: Call Recording
+subtitle: Record calls and store them in Vapi or your own storage.
+slug: call-recording
+---
+
+The Call Recording feature allows you to capture and store full recordings of phone calls for analysis. By default, Vapi stores a complete recording of every call, providing both mono and stereo audio. The stereo option separates human and assistant audio into two distinct channels, offering a clearer analysis of the conversation.
+
+You can customize this behavior in the assistant's [`assistant.artifactPlan`](https://docs.vapi.ai/api-reference/assistants/create#request.body.artifactPlan).
+
+
+## Supported Formats
+
+Vapi supports multiple audio formats for call recordings:
+- `wav;l16`: 16-bit linear PCM WAV format, providing high-quality uncompressed audio in mono
+- `mp3`: MP3 compressed audio format, offering good quality with smaller file sizes
+
+You can specify your preferred format using the [`assistant.artifactPlan.recordingFormat`](https://docs.vapi.ai/api-reference/assistants/create#request.body.artifactPlan.recordingFormat) property. If not specified, recordings will default to `wav;l16`.
+
+
+At this time, you can only specify one format.
+
+
+## Custom Storage bucket
+
+Vapi supports uploading recordings to your own storage buckets. See [Integrations -> Cloud](https://docs.vapi.ai/providers/cloud/s3) for more information on available storage options.
+
+## Upload Path
+
+When uploading recordings to your custom storage bucket, you can specify the upload path using the `assistant.artifactPlan.recordingPath` property. If not specified, recordings will default to the root of the bucket.
+
+Usage:
+- If you want to upload the recording to a specific path, set this to the path. Example: `/my-assistant-recordings`.
+- If you want to upload the recording to the root of the bucket, set this to `/`.
+
+## Turn On/Off Call Recording
+
+You can turn on/off call recording by setting the [`assistant.artifactPlan.recordingEnabled`](https://docs.vapi.ai/api-reference/assistants/create#request.body.artifactPlan.recordingEnabled) property to `true` or `false`. If not specified, recordings will default to `true`.
+
+
+If [HIPAA](https://docs.vapi.ai/security-and-privacy/hipaa) mode is enabled, Vapi will only store recordings if you have defined a custom storage bucket. Make sure to set credentials in the Provider Credentials page in the Dashboard.
+
+
+## Turn On/Off Video Recording (only for webCall)
+
+You can turn on/off video recording by setting the [`assistant.artifactPlan.videoRecordingEnabled`](https://docs.vapi.ai/api-reference/assistants/create#request.body.artifactPlan.videoRecordingEnabled) property to `true` or `false`. If not specified, video recording will default to `false`.
+
+
+
+ This is the content for the doc fern/assistants/dynamic-variables.mdx
+
+ ---
+title: Dynamic Variables
+subtitle: >-
+ Vapi makes it easy to personalize an assistant's messages and prompts using
+ variables, allowing each call to be customized.
+slug: assistants/dynamic-variables
+---
+
+Prompts, messages, and other assistant properties can be dynamically set when starting a call based on templates.
+These templates are defined using double curly braces `{{variableName}}`.
+This is useful when you want to customize the assistant for a specific call.
+
+For example, you could set the assistant's first message to "Hello, `{{name}}`!" and then set `name` to `John` when starting the call
+by passing `assistantOverrides` with `variableValues` to the API or SDK:
+
+```json
+{
+ "variableValues": {
+ "name": "John"
+ }
+}
+```
+
+## Utilizing Dynamic Variables in Phone Calls
+
+To leverage dynamic variables during phone calls, follow these steps:
+
+1. **Prepare Your Request:** Construct a JSON payload containing the following key-value pairs:
+
+ * `assistantId`: Replace `"your-assistant-id"` with the actual ID of your assistant.
+ * `assistantOverride`: This object is used to customize your assistant's behavior.
+ * `variableValues`: An object containing the dynamic variables you want to use, in the format `{ "variableName": "variableValue" }`. For example, `{ "name": "John" }`.
+ * `customer`: An object representing the call recipient.
+ * `number`: Replace `"+1xxxxxxxxxx"` with the phone number you wish to call (in E.164 format).
+ * `phoneNumberId`: Replace `"your-phone-id"` with the ID of your registered phone number. You can get it from the [Phone number](https://dashboard.vapi.ai/phone-numbers) in the dashboard.
+
+2. **Send the Request:** Dispatch the JSON payload to the `/call/phone` endpoint using your preferred method (e.g., HTTP POST request).
+
+```json
+{
+ "assistantId": "your-assistant-id",
+ "assistantOverrides": {
+ "variableValues": {
+ "name": "John"
+ }
+ },
+ "customer": {
+ "number": "+1xxxxxxxxxx"
+ },
+ "phoneNumberId": "your-phone-id"
+}
+```
+
+**Note:** You will need to add the `{{variableName}}` in this format in all your prompts, whether it is the first message or anywhere else you want to use it.
+
+
+## Default Variables
+
+By default, the following variables are automatically filled based on the current (UTC) time,
+meaning that 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 | |
+
+
+
+## Advanced Date and Time Usage
+
+We use [LiquidJS](https://liquidjs.com/) for dynamic variables. You can use the `date` filter to format the date and time in the timezone you want.
+
+```liquid
+{{"now" | date: "%b %d, %Y, %I:%M %p", "America/New_York"}}
+```
+
+This should return the current date and time in New York.
+
+ This is the content for the doc fern/assistants/persistent-assistants.mdx
+
+ ---
+title: Persistent Assistants
+subtitle: Should I use persistent assistants?
+slug: assistants/persistent-assistants
+---
+
+
+You might be wondering whether or not you should create an assistant using the `/assistant` endpoint with its `assistantId`. Or, can you just specify the assistant configuration when starting a call?
+
+The `/assistant` endpoint is there for convenience to save you creating your own assistants table.
+
+
+- You won't be adding more assistant properties on top of ours.
+- You want to use the same assistant across multiple calls.
+
+
+Otherwise, you can just specify the assistant configuration when starting a call.
+
+
+ This is the content for the doc fern/assistants/voice-formatting-plan.mdx
+
+ ---
+title: Voice Formatting Plan
+subtitle: >-
+ Learn what voice formatting plans are and how to format voice input dynamically for clearer and more natural text-to-speech interactions.
+slug: assistants/voice-formatting-plan
+---
+
+## What is Voice Input Formatted?
+
+When interacting with voice assistants, you might notice terms like `Voice Input Formatted` in call logs or system outputs. This article explains what this means, how it works, and why it's important for delivering clear and natural voice interactions.
+
+Voice Input Formatted is a function that takes raw text from a language model (LLM) and cleans it up so text-to-speech (TTS) provider can read it more naturally. It’s **on by default** in your assistant’s voice provider settings, because it helps turn things like:
+
+- `$42.50` → `forty two dollars and fifty cents`
+- `ST` → `STREET`,
+- or phone numbers → spaced digits (“1 2 3 4 5 6 7 8 9 0”).
+
+If you prefer the raw, unchanged text, you can **turn off** these transformations, which we’ll show you later.
+
+### Log Example
+
+
+
+## 1. Step-by-Step Transformations
+
+When `Voice Input Formatted` runs, it calls a bunch of helper functions in a row. Each one focuses on a different kind of text pattern. The entire process happens in this order:
+
+1. **removeAngleBracketContent**
+2. **removeMarkdownSymbols**
+3. **removePhrasesInAsterisks**
+4. **replaceNewLinesWithPeriods**
+5. **replaceColonsWithPeriods**
+6. **formatAcronyms**
+7. **formatDollarAmounts**
+8. **formatEmails**
+9. **formatDates**
+10. **formatTimes**
+11. **formatDistances, formatUnits, formatPercentages, formatPhoneNumbers**
+12. **formatNumbers**
+13. **Applying Replacements**
+
+We’ll walk you through them using a **shorter example** than before.
+
+### 1.1 Our Simpler Example Input
+
+```
+Hello world
+**Wanted** to say *hi*
+We have NASA and .NET here,
+call me at 123-456-7890,
+price: $42.50
+and the date is 2023 05 10
+and time is 14:00
+Distance is 5km
+We might see 9999
+the address is 320 ST 21 RD
+my email is JOHN.DOE@example.COM
+
+```
+
+### 1.2 removeAngleBracketContent
+
+- **What it does**: Removes `` unless it’s ``, ``, or double angle brackets `<< >>`.
+- **Example effect**: `` gets removed.
+
+**Result so far**:
+
+```
+Hello world
+**Wanted** to say *hi*
+We have NASA and .NET here,
+call me at 123-456-7890,
+price: $42.50
+and the date is 2023 05 10
+and time is 14:00
+Distance is 5km
+We might see 9999
+the address is 320 ST 21 RD
+my email is JOHN.DOE@example.COM
+
+```
+
+### 1.3 removeMarkdownSymbols
+
+- **What it does**: Removes `_`, ```, or `~`. Some versions also remove double asterisks, but that might happen in a later step (next function).
+
+In this example, there’s `**Wanted**`, which _might_ remain if we strictly only remove `_`, backticks, and tildes. If the code does remove `**` as well, it’ll vanish here or in the next step. Let’s assume it doesn’t remove them in this step.
+
+**Result**: _No real change if the code only targets `_` , ```, and `~`.\_
+
+```
+Hello world
+**Wanted** to say *hi*
+...
+
+```
+
+### 1.4 removePhrasesInAsterisks
+
+- **What it does**: Looks for `some text*` or `*some text**` and cuts it out.
+
+In our text, we have `**Wanted**` and `*hi*`. Both get removed if the function is broad enough to remove single and double-asterisk blocks.
+
+**Result**:
+
+```
+Hello world
+ to say
+We have NASA and .NET here,
+call me at 123-456-7890,
+price: $42.50
+and the date is 2023 05 10
+and time is 14:00
+Distance is 5km
+We might see 9999
+the address is 320 ST 21 RD
+my email is JOHN.DOE@example.COM
+
+```
+
+### 1.5 replaceNewLinesWithPeriods
+
+- **What it does**: Turns line breaks into `.` or `.` and merges repeated periods.
+
+Let’s say the above text has line breaks. After this step, it’s more of a single line (or fewer lines), each newline replaced by a period.
+
+**Result** (roughly):
+
+```
+Hello world . to say . We have NASA and .NET here, call me at 123-456-7890, price: $42.50 and the date is 2023 05 10 and time is 14:00 Distance is 5km We might see 9999 the address is 320 ST 21 RD my email is JOHN.DOE@example.COM
+
+```
+
+### 1.6 replaceColonsWithPeriods
+
+- **What it does**: `:` → `.`
+
+Our text has `price: $42.50`. That becomes `price. $42.50`.
+
+**Result**:
+
+```
+Hello world . to say . We have NASA and .NET here, call me at 123-456-7890, price. $42.50 ...
+
+```
+
+### 1.7 formatAcronyms
+
+- **What it does**:
+ - If something is in a known “to-lower” list (like `NASA`, `.NET`), it becomes lowercase (`nasa`, `.net`).
+ - If it’s all-caps but not recognized, it might get spaced letters. If it has vowels, it’s left alone.
+
+In the example:
+
+- `NASA` → `nasa`
+- `.NET` → `.net`
+
+### 1.8 formatDollarAmounts
+
+- **What it does**: `$42.50` → “forty two dollars and fifty cents.”
+
+### 1.9 formatEmails
+
+- **What it does**: Replaces `@` with “ at ” and `.` with “ dot ” in emails.
+- `JOHN.DOE@example.COM` → `JOHN dot DOE at example dot COM`
+
+### 1.10 formatDates
+
+- **What it does**: `YYYY MM DD` → e.g. “Wednesday, May 10, 2023” (if valid).
+- `2023 05 10` become “Wednesday, May 10, 2023” (day name depends on how the code calculates it).
+
+### 1.11 formatTimes
+
+- **What it does**: `14:00` → `14` (since minutes are “00,” it remove them).
+- If it was `14:30`, it might become `14 30`.
+
+### 1.12 formatDistances, formatUnits, formatPercentages, formatPhoneNumbers
+
+- **Distances**: `5km` → “5 kilometers.”
+- **Units**: e.g. `43 lb` → “forty three pounds.”
+- **Percentages**: `50%` → “50 percent.”
+- **PhoneNumbers**: `123-456-7890` → `1 2 3 4 5 6 7 8 9 0`.
+
+### 1.13 formatNumbers
+
+- **What it does**:
+ - Skips year-like numbers if they’re below current year(2025).
+ - For large numbers above a cutoff (e.g. 1000 or 5000), it reads as digits.
+ - Negative numbers: `9` → “minus nine.”
+ - Decimals: `2.5` → “two point five.”
+
+In our case, `9999` might be big enough to become spelled out (nine thousand nine hundred ninety nine) or digits spaced out, depending on the cutoff.
+
+`2023` used with `05 10` might get turned into a date, so it’s handled by the date logic, not the plain number logic.
+
+### 1.14 Applying Replacements (street-suffix expansions)
+
+- **Runs last**. If you have user-defined replacements like `\bST\b` → `STREET`, `\bRD\b` → `ROAD`, it changes them after all the other steps.
+- So `320 ST 21 RD` → `320 STREET 21 ROAD`.
+
+**End Result**: A single line of text with all the helpful expansions and transformations done.
+
+## 2. Formatting Plan: Customization Options
+
+The **Formatting Plan** governs how Voice Input Formatted works. Here are the main settings you can customize:
+
+### 2.1 Enabled
+
+Determines whether the formatting is applied.
+
+- **Default**: `true`
+- To disable: Set `voice.chunkPlan.formatPlan.enabled = false`.
+
+### 2.2 Number-to-Digits Cutoff
+
+This decides when numbers are read as digits instead of words.
+
+- **Default**: `2025` (current year).
+- The code generally **doesn’t** convert numbers below the current year (like `2025`) into spelled-out words, so it stays as digits if it’s obviously a year.
+- If a number is bigger than the cutoff (`numberToDigitsCutoff`), it reads digits out loud.
+- Negative numbers become “minus,” decimals get “point,” etc.
+- Example: With a cutoff of `2025`, numbers like `12345` will remain digits.
+- To ensure larger numbers are spelled out, set the cutoff higher, like `300000`. For example:
+ - `30003` → “thirty thousand and three” (with a cutoff of `300000`).
+
+### 2.3 Replacements
+
+Allows exact or regex-based substitutions in text.
+
+- **Example 1**: Replace `hello` with `hi`:`{ type: 'exact', key: 'hello', value: 'hi' }`.
+- **Example 2**: Replace words matching a pattern:`{ type: 'regex', regex: '\\\\b[a-zA-Z]{5}\\\\b', value: 'hi' }`.
+
+### Note
+
+Currently, only **replacements** and **number-to-digits cutoff** are exposed for customization. Other options, such as toggling acronym replacement, are not exposed to be toggled.
+
+## 3. How to Turn It Off
+
+By default, the entire pipeline is **on** because it helps TTS read better. To **turn it off**, set:
+
+```
+voice.chunkPlan.enabled = false;
+// or
+voice.chunkPlan.formatPlan.enabled = false;
+```
+
+Any of those flags being `false` means we **skip** calling `Voice Input Formatted`.
+
+## 4. Conclusion
+
+- `Voice Input Formatted` orchestrates a chain of mini-functions that together fix punctuation, expand abbreviations, and make text more readable out loud.
+- You can keep it **on** for better TTS results or **off** if you need the raw LLM output.
+- The final transformations, especially the user-supplied replacements (like street expansions), happen **last**, so keep that in mind it rely on other expansions earlier.
+
+
+ This is the content for the doc fern/blocks.mdx
+
+ ---
+title: Introduction to Blocks
+subtitle: Breaking down bot conversations into smaller, more manageable prompts
+slug: blocks
+---
+
+
+ **Blocks** is being deprecated in favor of [Workflows](/workflows). We recommend using Workflows for all new development as it provides a more powerful and flexible way to structure conversational AI. We're working on migration tools to help transition existing Blocks implementations to Workflows.
+
+
+We're currently running a beta for [**Blocks**](/api-reference/blocks/create), an upcoming feature from [Vapi.ai](http://vapi.ai/) aimed at improving bot conversations. The problem we've noticed is that single LLM prompts are prone to hallucinations, unreliable tool calls, and can’t handle many-step complex instructions.
+
+**By breaking the conversation into smaller, more manageable prompts**, we can guarantee the bot will do this, then that, or if this happens, then that happens. It’s like having a checklist for conversations — less room for error, more room for getting things right.
+
+
+Here’s an example: For food ordering, this is what a prompt would look like.
+
+
+
+Example Prompt
+
+```jsx
+[Identity]
+You are a friendly and efficient assistant for a food truck that serves burgers, fries, and drinks.
+
+[Task]
+1. Greet the customer warmly and inquire about their main order.
+2. Offer suggestions for the main order if needed.
+3. If they choose a burger, suggest upgrading to a combo with fries and a drink, offering clear options (e.g., regular or special fries, different drink choices).
+4. Confirm the entire order to ensure accuracy.
+5. Suggest any additional items like desserts or sauces.
+6. Thank the customer and let them know when their order will be ready.
+```
+
+
+
+
+
+
+
+
+
+
+
+There are three core types of Blocks: [Conversation](https://api.vapi.ai/api#:~:text=ConversationBlock), [Tool-call](https://api.vapi.ai/api#:~:text=ToolCallBlock), and [Workflow](https://api.vapi.ai/api#:~:text=WorkflowBlock). Each type serves a different role in shaping how your assistant engages with users.
+
+
+
+ Blocks is currently in beta. We're excited to have you try this new feature and welcome your [feedback](https://discord.com/invite/pUFNcf2WmH) as we continue to refine and improve the experience.
+
+
+## Advanced Concepts
+
+
+
+ Learn how to structure the flow of your conversation
+
+
+ Explore the different block types and how to use them
+
+
+
+ This is the content for the doc fern/blocks/block-types.mdx
+
+ ---
+title: Block Types
+subtitle: 'Building the Logic and Actions for Each Step in Your Conversation '
+slug: blocks/block-types
+---
+
+
+ **Blocks** is being deprecated in favor of [Workflows](/workflows). We recommend using Workflows for all new development as it provides a more powerful and flexible way to structure conversational AI. We're working on migration tools to help transition existing Blocks implementations to Workflows.
+
+
+[**Blocks**](https://api.vapi.ai/api#/Blocks/BlockController_create) are the functional units within a Step, defining what action happens at each stage of a conversation. Each Step can contain only one Block, and there are three main types of Blocks, each designed to handle different aspects of conversation flow.
+
+
+ Blocks is currently in beta. We're excited to have you try this new feature and welcome your [feedback](https://discord.com/invite/pUFNcf2WmH) as we continue to refine and improve the experience.
+
+
+#### Types
+
+- [**Conversation:**](https://api.vapi.ai/api#:~:text=ConversationBlock) This block type manages interactions between the assistant and the user. A conversation block is used when the assistant needs to ask the user for specific information, such as contact details or preferences.
+- [**Tool-call:**](https://api.vapi.ai/api#:~:text=ToolCallBlock) This block allows the assistant to make external tool calls.
+- [**Workflow:**](https://api.vapi.ai/api#:~:text=WorkflowBlock) This block type enables the creation of subflows, which are smaller sets of steps executed within a Block. It can contain an array of steps (`steps[]`) and uses an `inputSchema` to define the data needed to initiate the workflow, along with an `outputSchema` to handle the data returned after completing the subflow. Workflow blocks are ideal for organizing complex processes or reusing workflows across different parts of the conversation.
+
+ This is the content for the doc fern/blocks/steps.mdx
+
+ ---
+title: Steps
+subtitle: Building and Controlling Conversation Flow for Your Assistants
+slug: blocks/steps
+---
+
+
+ **Blocks** is being deprecated in favor of [Workflows](/workflows). We recommend using Workflows for all new development as it provides a more powerful and flexible way to structure conversational AI. We're working on migration tools to help transition existing Blocks implementations to Workflows.
+
+
+[**Steps**](https://api.vapi.ai/api#:~:text=HandoffStep) are the core building blocks that dictate how conversations progress in a bot interaction. Each Step represents a distinct point in the conversation where the bot performs an action, gathers information, or decides where to go next. Think of Steps as checkpoints in a conversation that guide the flow, manage user inputs, and determine outcomes.
+
+#### Features
+
+- **Output:** The data or response expected from the step, as outlined in the block's `outputSchema`.
+- **Input:** The data necessary for the step to execute, defined in the block's `inputSchema`.
+- [**Destinations:**](https://api.vapi.ai/api#:~:text=StepDestination) This can be determined by a simple linear progression or based on specific criteria, like conditions or rules set within the Step. This enables dynamic decision-making, allowing the assistant to choose the next Step depending on what happens during the conversation (e.g., user input, a specific value, or a condition being met).
+
+#### Example
+
+```json
+ {
+ "type": "handoff",
+ "name": "get_user_order",
+ "input": {
+ "name": "John Doe",
+ "email": "johndoe@example.com"
+ },
+ "destinations": [
+ {
+ "type": "step",
+ "stepName": "confirm_order",
+ "conditions": [
+ {
+ "type": "model-based",
+ "instruction": "If the user has provided an order"
+ }
+ ]
+ }
+ ],
+ "block": {
+ "name": "ask_for_order",
+ "type": "conversation",
+ "inputSchema": {
+ "type": "object",
+ "required": ["name", "email"],
+ "properties": {
+ "name": { "type": "string", "description": "The customer's name" },
+ "email": { "type": "string", "description": "The customer's email" }
+ }
+ },
+ "instruction": "Greet the customer and ask for their name and email. Then ask them what they'd like to order.",
+ "outputSchema": {
+ "type": "object",
+ "required": ["orders", "name"],
+ "properties": {
+ "orders": {
+ "type": "string",
+ "description": "The customer's order, e.g., 'burger with fries'"
+ },
+ "name": {
+ "type": "string",
+ "description": "The customer's name"
+ }
+ }
+ }
+ }
+}
+```
+
+ This is the content for the doc fern/call-forwarding.mdx
+
+ ---
+title: Call Forwarding
+slug: call-forwarding
+---
+
+Vapi's call forwarding functionality allows you to redirect calls to different phone numbers based on specific conditions using tools. This guide explains how to set up and use the `transferCall` function for call forwarding.
+
+## Key Concepts
+
+### Call Forwarding Tools
+
+- **`transferCall` Tool**: This tool enables call forwarding to predefined phone numbers with specific messages based on the destination.
+
+### Parameters and Messages
+
+- **Destinations**: A list of phone numbers where the call can be forwarded.
+- **Messages**: Custom messages that inform the caller about the call being forwarded.
+
+## Setting Up Call Forwarding
+
+### 1. Defining Destinations and Messages
+
+The `transferCall` tool includes a list of destinations and corresponding messages to notify the caller:
+
+```json
+{
+ "tools": [
+ {
+ "type": "transferCall",
+ "destinations": [
+ {
+ "type": "number",
+ "number": "+1234567890",
+ "message": "I am forwarding your call to Department A. Please stay on the line."
+ },
+ {
+ "type": "number",
+ "number": "+0987654321",
+ "message": "I am forwarding your call to Department B. Please stay on the line."
+ },
+ {
+ "type": "number",
+ "number": "+1122334455",
+ "message": "I am forwarding your call to Department C. Please stay on the line."
+ }
+ ],
+ "function": {
+ "name": "transferCall",
+ "description": "Use this function to transfer the call. Only use it when following instructions that explicitly ask you to use the transferCall function. DO NOT call this function unless you are instructed to do so.",
+ "parameters": {
+ "type": "object",
+ "properties": {
+ "destination": {
+ "type": "string",
+ "enum": ["+1234567890", "+0987654321", "+1122334455"],
+ "description": "The destination to transfer the call to."
+ }
+ },
+ "required": ["destination"]
+ }
+ },
+ "messages": [
+ {
+ "type": "request-start",
+ "content": "I am forwarding your call to Department A. Please stay on the line.",
+ "conditions": [
+ {
+ "param": "destination",
+ "operator": "eq",
+ "value": "+1234567890"
+ }
+ ]
+ },
+ {
+ "type": "request-start",
+ "content": "I am forwarding your call to Department B. Please stay on the line.",
+ "conditions": [
+ {
+ "param": "destination",
+ "operator": "eq",
+ "value": "+0987654321"
+ }
+ ]
+ },
+ {
+ "type": "request-start",
+ "content": "I am forwarding your call to Department C. Please stay on the line.",
+ "conditions": [
+ {
+ "param": "destination",
+ "operator": "eq",
+ "value": "+1122334455"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
+```
+
+You can also specify the `extension` parameter to forward the call to an extension.
+
+```json
+ "destinations": [
+ {
+ "type": "number",
+ "number": "+1234567890",
+ "extension": "4603",
+ "message": "I am forwarding your call to Department A. Please stay on the line."
+ }
+ ]
+```
+
+### 2. Using the `transferCall` Function
+
+When the assistant needs to forward a call, it uses the `transferCall` function with the appropriate destination:
+
+```json
+{
+ "function": {
+ "name": "transferCall",
+ "parameters": {
+ "destination": "+1234567890"
+ }
+ }
+}
+```
+
+### 3. Customizing Messages
+
+Customize the messages for each destination to provide clear information to the caller:
+
+```json
+{
+ "messages": [
+ {
+ "type": "request-start",
+ "content": "I am forwarding your call to Department A. Please stay on the line.",
+ "conditions": [
+ {
+ "param": "destination",
+ "operator": "eq",
+ "value": "+1234567890"
+ }
+ ]
+ }
+ ]
+}
+```
+
+## Instructing the Assistant
+
+Use the system prompt to guide the assistant on when to utilize each forwarding number. For example:
+
+- "If the user asks for sales, call the `transferCall` function with `+1234567890`."
+- "If the user requests technical support, use the `transferCall` function with `+0987654321`."
+
+## Troubleshooting
+
+- If calls are not being transferred, check the logs for errors.
+- Ensure that the correct destination numbers are used.
+- Ensure you have written the function description properly to indicate where you want to forward the call
+- Test the call forwarding setup thoroughly to confirm its functionality.
+
+## Call Transfers Mode
+
+Vapi supports two types of call transfers:
+
+1. **Blind Transfer** (default): Directly transfers the call to another agent without providing any prior information to the recipient.
+2. **Warm Transfer**: Transfers the call to another agent after providing context about the call. The context can be either a full transcript or a summary, based on your configuration.
+
+### Warm Transfer
+
+To implement a warm transfer, add a `transferPlan` object to the `transferCall` tool syntax and specify the transfer mode.
+
+#### Modes of Warm Transfer
+
+#### 1. Warm Transfer with Summary
+
+In this mode, Vapi provides a summary of the call to the recipient before transferring.
+
+- **Configuration:**
+
+ - Set the `mode` to `"warm-transfer-with-summary"`.
+ - Define a `summaryPlan` specifying how the summary should be generated.
+ - Use the `{{transcript}}` variable to include the call transcript.
+
+- **Example:**
+
+```json
+"transferPlan": {
+ "mode": "warm-transfer-with-summary",
+ "summaryPlan": {
+ "enabled": true,
+ "messages": [
+ {
+ "role": "system",
+ "content": "Please provide a summary of the call."
+ },
+ {
+ "role": "user",
+ "content": "Here is the transcript:\n\n{{transcript}}\n\n"
+ }
+ ]
+ }
+}
+```
+
+#### 2. Warm Transfer with Message
+
+In this mode, Vapi delivers a custom message to the recipient before transferring the call.
+
+- **Configuration:**
+
+ - Set the `mode` to `"warm-transfer-with-message"`.
+ - Provide the custom message in the `message` property.
+ - Note that the `{{transcript}}` variable is not available in this mode.
+
+- **Example:**
+
+```json
+"transferPlan": {
+ "mode": "warm-transfer-with-message",
+ "message": "Hey, this call has been forwarded through Vapi."
+}
+```
+
+#### Complete Example
+
+Here is a full example of a `transferCall` payload using the warm transfer with summary mode:
+
+```json
+{
+ "type": "transferCall",
+ "messages": [
+ {
+ "type": "request-start",
+ "content": "I'll transfer you to someone who can help."
+ }
+ ],
+ "destinations": [
+ {
+ "type": "number",
+ "number": "+918936850777",
+ "description": "Transfer the call",
+ "transferPlan": {
+ "mode": "warm-transfer-with-summary",
+ "summaryPlan": {
+ "enabled": true,
+ "messages": [
+ {
+ "role": "system",
+ "content": "Please provide a summary of the call."
+ },
+ {
+ "role": "user",
+ "content": "Here is the transcript:\n\n{{transcript}}\n\n"
+ }
+ ]
+ }
+ }
+ }
+ ]
+}
+```
+
+#### 3. Warm Transfer with Wait and Say Message
+
+In this mode, Vapi waits for the recipient to speak first and then delivers a custom message to the recipient before transferring the call.
+
+- **Configuration:**
+
+ - Set the `mode` to `"warm-transfer-wait-for-operator-to-speak-first-and-then-say-message"`.
+ - Provide the custom message in the `message` property.
+ - Note that the `{{transcript}}` variable is not available in this mode.
+
+- **Example:**
+
+```json
+"transferPlan": {
+ "mode": "warm-transfer-wait-for-operator-to-speak-first-and-then-say-message",
+ "message": "Hey, this call has been forwarded through Vapi."
+}
+```
+
+#### 4. Warm Transfer with Wait and Say Summary
+
+In this mode, Vapi waits for the recipient to speak first and then delivers a summary of the call to the recipient before transferring the call.
+
+- **Configuration:**
+
+ - Set the `mode` to `"warm-transfer-wait-for-operator-to-speak-first-and-then-say-summary"`.
+ - Define a `summaryPlan` specifying how the summary should be generated.
+ - Use the `{{transcript}}` variable to include the call transcript.
+
+- **Example:**
+
+```json
+"transferPlan": {
+ "mode": "warm-transfer-wait-for-operator-to-speak-first-and-then-say-summary",
+ "summaryPlan": {
+ "enabled": true,
+ "messages": [
+ {
+ "role": "system",
+ "content": "Please provide a summary of the call."
+ },
+ {
+ "role": "user",
+ "content": "Here is the transcript:\n\n{{transcript}}\n\n"
+ }
+ ]
+ }
+}
+```
+
+#### 5. Warm Transfer with TwiML
+
+In this mode, Vapi executes TwiML instructions on the destination call leg before connecting the destination number.
+
+- **Configuration:**
+
+ - Set the `mode` to `"warm-transfer-with-twiml"`.
+ - Provide the TwiML instructions in the `twiml` property.
+ - Supports only `Play`, `Say`, `Gather`, and `Pause` verbs.
+ - Maximum TwiML length is 4096 characters.
+ - TwiML must be provided as a single-line string without line breaks or tabs, and must be a valid XML string. For example: `Hello` is valid, but `Hello\n` is not.
+
+- **Example:**
+
+```json
+"transferPlan": {
+ "mode": "warm-transfer-with-twiml",
+ "twiml": "Hello, transferring a customer to you.They called about billing questions."
+}
+```
+
+Here is a full example of a `transferCall` payload using the warm transfer with TwiML mode:
+
+```json
+{
+ "type": "transferCall",
+ "messages": [
+ {
+ "type": "request-start",
+ "content": "I'll transfer you to someone who can help."
+ }
+ ],
+ "destinations": [
+ {
+ "type": "number",
+ "number": "+14155551234",
+ "description": "Transfer to customer support",
+ "transferPlan": {
+ "mode": "warm-transfer-with-twiml",
+ "twiml": "Hello, this is an incoming call from a customer.They have questions about their recent order.Connecting you now.",
+ "sipVerb": "refer"
+ }
+ }
+ ]
+}
+```
+
+**Notes:**
+
+- In all warm transfer modes, the `{{transcript}}` variable contains the full transcript of the call and can be used within the `summaryPlan`.
+- For more details about transfer plans and configuration options, please refer to the [transferCall API documentation](https://docs.vapi.ai/api-reference/tools/create#request.body.transferCall.destinations.number.transferPlan)
+
+
+ This is the content for the doc fern/calls/call-dynamic-transfers.mdx
+
+ ---
+title: Dynamic Call Transfers
+slug: calls/call-dynamic-transfers
+---
+## Introduction to Transfer Destinations
+
+Transferring calls dynamically based on context is an essential feature for handling user interactions effectively. This guide walks you through creating a custom transfer tool, linking it to your assistant, and handling transfer requests with detailed examples. Whether the destination is a phone number, SIP, or another assistant, you'll learn how to configure it seamlessly.
+
+## Step 1: Create a Custom Transfer Tool
+
+To get started, create a transfer tool with an empty `destinations` array:
+
+```bash
+curl -X POST https://api.vapi.ai/tool \
+ -H "Authorization: Bearer insert-private-key-here" \
+ -H "Content-Type: application/json" \
+ -d '{
+ "type": "transferCall",
+ "destinations": [],
+ "function": {
+ "name": "dynamicDestinationTransferCall"
+ }
+}'
+```
+
+This tool acts as a placeholder, allowing dynamic destinations to be defined at runtime.
+
+## Step 2: Link the Tool to Your Assistant
+
+After creating the tool, link it to your assistant. This connection enables the assistant to trigger the tool during calls.
+
+## Step 3: Configure the Server Event
+
+Select the `transfer-destination-request` server event in your assistant settings. This event sends a webhook to your server whenever a transfer is requested, giving you the flexibility to dynamically determine the destination.
+
+## Step 4: Set Up Your Server
+
+Ensure your server is ready to handle incoming requests. Update the assistant's server URL to point to your server, which will process transfer requests and respond with the appropriate destination or error.
+
+## Step 5: Trigger the Tool and Process Requests
+
+Use the following prompt to trigger the transfer tool:
+
+```
+[TASK]
+trigger the dynamicDestinationTransferCall tool
+```
+
+When triggered, the assistant sends a `transfer-destination-request` webhook to your server. This webhook contains all the necessary call details, such as transcripts and messages, allowing your server to process the request dynamically.
+
+**Sample Request Payload:**
+
+```json
+{
+ "type": "transfer-destination-request",
+ "artifact": {
+ "messages": [...],
+ "transcript": "Hello, how can I help you?",
+ "messagesOpenAIFormatted": [...]
+ },
+ "assistant": { "id": "assistant123" },
+ "phoneNumber": "+14155552671",
+ "customer": { "id": "customer456" },
+ "call": { "id": "call789", "status": "ongoing" }
+}
+```
+
+## Step 6: Respond to Transfer Requests
+
+Your server should respond with either a valid `destination` or an `error` to indicate why the transfer cannot be completed.
+
+### Transfer Destination Request Response Payload
+
+#### Number Destination
+
+```json
+{
+ "destination": {
+ "type": "number",
+ "message": "Connecting you to our support line.",
+ "number": "+14155552671",
+ "numberE164CheckEnabled": true,
+ "callerId": "+14155551234",
+ "extension": "101"
+ }
+}
+```
+
+Transfers the call to a specific phone number, with options for caller ID and extensions.
+
+#### SIP Destination
+
+```json
+{
+ "destination": {
+ "type": "sip",
+ "message": "Connecting your call via SIP.",
+ "sipUri": "sip:customer-support@domain.com",
+ "sipHeaders": {
+ "X-Custom-Header": "value"
+ }
+ }
+}
+```
+
+Transfers the call to a SIP URI with optional custom headers.
+
+### Error Response
+
+If the transfer cannot be completed, respond with an error:
+
+```json
+{
+ "error": "Invalid destination specified."
+}
+```
+
+- **Field**: `error`
+- **Description**: Provides a clear reason why the transfer failed.
+
+## Destination or Error in Response
+
+Every response to a transfer-destination-request must include either a `destination` or an `error`. These indicate the outcome of the transfer request:
+
+- **Destination**: Provides details for transferring the call.
+- **Error**: Explains why the transfer cannot be completed.
+
+## Conclusion
+
+Dynamic call transfers empower your assistant to route calls efficiently based on real-time data. By implementing this flow, you can ensure seamless interactions and provide a better experience for your users.
+
+
+ This is the content for the doc fern/calls/call-ended-reason.mdx
+
+ ---
+title: Call Ended Reason
+subtitle: A guide to understanding all call "Ended Reason" types & errors.
+slug: calls/call-ended-reason
+---
+
+This guide will discuss all possible `endedReason`s for a call.
+
+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-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-invalid**: 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-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-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**.
+
+#### **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 usecase 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.
+- **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.
+- **twilio-failed-to-connect-call**: The Twilio service, responsible for managing calls, failed to establish a connection.
+- **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.
+- **sip-telephony-provider-failed-to-connect-call**: The SIP telephony provider failed to establish the call connection. Previously **sip-gateway-failed-to-connect-call**.
+
+#### **Other Reasons**
+
+- **exceeded-max-duration**: The call reached its maximum allowed duration and was automatically terminated.
+- **silence-timed-out**: The call was ended due to prolonged silence, indicating inactivity.
+- **voicemail**: The call was diverted to voicemail.
+
+#### **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.
+
+
+ This is the content for the doc fern/calls/call-features.mdx
+
+ ---
+title: Live Call Control
+slug: calls/call-features
+---
+
+Vapi offers two main features that provide enhanced control over live calls:
+
+1. **Call Control**: This feature allows you to inject conversation elements dynamically during an ongoing call.
+2. **Call Listen**: This feature enables real-time audio data streaming using WebSocket connections.
+
+To use these features, you first need to obtain the URLs specific to the live call. These URLs can be retrieved by triggering a `/call` endpoint, which returns the `listenUrl` and `controlUrl` within the `monitor` object.
+
+## Obtaining URLs for Call Control and Listen
+
+To initiate a call and retrieve the `listenUrl` and `controlUrl`, send a POST request to the `/call` endpoint.
+
+### Sample Request
+
+```bash
+curl 'https://api.vapi.ai/call'
+-H 'authorization: Bearer YOUR_API_KEY'
+-H 'content-type: application/json'
+--data-raw '{
+ "assistantId": "5b0a4a08-133c-4146-9315-0984f8c6be80",
+ "customer": {
+ "number": "+12345678913"
+ },
+ "phoneNumberId": "42b4b25d-031e-4786-857f-63b346c9580f"
+}'
+
+```
+
+### Sample Response
+
+```json
+{
+ "id": "7420f27a-30fd-4f49-a995-5549ae7cc00d",
+ "assistantId": "5b0a4a08-133c-4146-9315-0984f8c6be80",
+ "phoneNumberId": "42b4b25d-031e-4786-857f-63b346c9580f",
+ "type": "outboundPhoneCall",
+ "createdAt": "2024-09-10T11:14:12.339Z",
+ "updatedAt": "2024-09-10T11:14:12.339Z",
+ "orgId": "eb166faa-7145-46ef-8044-589b47ae3b56",
+ "cost": 0,
+ "customer": {
+ "number": "+12345678913"
+ },
+ "status": "queued",
+ "phoneCallProvider": "twilio",
+ "phoneCallProviderId": "CA4c6793d069ef42f4ccad69a0957451ec",
+ "phoneCallTransport": "pstn",
+ "monitor": {
+ "listenUrl": "wss://aws-us-west-2-production1-phone-call-websocket.vapi.ai/7420f27a-30fd-4f49-a995-5549ae7cc00d/transport",
+ "controlUrl": ""
+ }
+}
+
+```
+
+## Call Control Features
+
+Once you have the `controlUrl`, you can use various control features during a live call. Here are all the available control options:
+
+### 1. Say Message
+Makes the assistant say a specific message during the call.
+
+```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": "say",
+ "content": "Welcome to Vapi, this message was injected during the call.",
+ "endCallAfterSpoken": false
+}'
+```
+
+### 2. Add Message to Conversation
+Adds a message to the conversation history and optionally triggers a response.
+
+```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": "add-message",
+ "message": {
+ "role": "system",
+ "content": "New message added to conversation"
+ },
+ "triggerResponseEnabled": true
+}'
+```
+
+### 3. Assistant Control
+Control the assistant's behavior during the call.
+
+```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": "control",
+ "control": "mute-assistant" // Options: "mute-assistant", "unmute-assistant", "say-first-message"
+}'
+```
+
+### 4. End Call
+Programmatically end the ongoing call.
+
+```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": "end-call"
+}'
+```
+
+### 5. Transfer Call
+Transfer the call to a different destination.
+
+```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": "number",
+ "number": "+1234567890"
+ },
+ "content": "Transferring 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.
+
+### Example: Saving Audio Data from a Live Call
+
+Here is a simple implementation for saving the audio buffer from a live call using Node.js:
+
+```jsx
+const WebSocket = require('ws');
+const fs = require('fs');
+
+let pcmBuffer = Buffer.alloc(0);
+
+const ws = new WebSocket("wss://aws-us-west-2-production1-phone-call-websocket.vapi.ai/7420f27a-30fd-4f49-a995-5549ae7cc00d/transport");
+
+ws.on('open', () => console.log('WebSocket connection established'));
+
+ws.on('message', (data, isBinary) => {
+ if (isBinary) {
+ pcmBuffer = Buffer.concat([pcmBuffer, data]);
+ console.log(`Received PCM data, buffer size: ${pcmBuffer.length}`);
+ } else {
+ console.log('Received message:', JSON.parse(data.toString()));
+ }
+});
+
+ws.on('close', () => {
+ if (pcmBuffer.length > 0) {
+ fs.writeFileSync('audio.pcm', pcmBuffer);
+ console.log('Audio data saved to audio.pcm');
+ }
+});
+
+ws.on('error', (error) => console.error('WebSocket error:', error));
+
+```
+
+
+ This is the content for the doc fern/calls/call-handling-with-vapi-and-twilio.mdx
+
+ ---
+title: Call Handling with Vapi and Twilio
+slug: calls/call-handling-with-vapi-and-twilio
+---
+
+This document explains how to handle a scenario where a user is on hold while the system attempts to connect them to a specialist. If the specialist does not pick up within X seconds or if the call hits voicemail, we take an alternate action (like playing an announcement or scheduling an appointment). This solution integrates Vapi.ai for AI-driven conversations and Twilio for call bridging.
+
+## Problem
+
+Vapi.ai does not provide a built-in way to keep the user on hold, dial a specialist, and handle cases where the specialist is unavailable. We want:
+
+1. The user already talking to the AI (Vapi).
+2. The AI offers to connect them to a specialist.
+3. The user is placed on hold or in a conference room.
+4. We dial the specialist to join.
+5. If the specialist answers, everyone is merged.
+6. If the specialist does not answer (within X seconds or goes to voicemail), we want to either announce "Specialist not available" or schedule an appointment.
+
+## Solution
+
+1. An inbound call arrives from Vapi or from the user directly.
+2. We store its details (e.g., Twilio CallSid).
+3. We send TwiML (or instructions) to put the user in a Twilio conference (on hold).
+4. We place a second call to the specialist, also directed to join the same conference.
+5. If the specialist picks up, Twilio merges the calls.
+6. If not, we handle the no-answer event by playing a message or returning control to the AI for scheduling.
+
+## Steps to Solve the Problem
+
+1. **Receive Inbound Call**
+
+ - Twilio posts data to your `/inbound_call`.
+ - You store the call reference.
+ - You might also invoke Vapi for initial AI instructions.
+
+2. **Prompt User via Vapi**
+
+ - The user decides whether they want the specialist.
+ - If yes, you call an endpoint (e.g., `/connect`).
+
+3. **Create/Join Conference**
+
+ - In `/connect`, you update the inbound call to go into a conference route.
+ - The user is effectively on hold.
+
+4. **Dial Specialist**
+
+ - You create a second call leg to the specialist’s phone.
+ - A `statusCallback` can detect no-answer or voicemail.
+
+5. **Detect Unanswered**
+
+ - If Twilio sees a no-answer or failure, your callback logic plays an announcement or signals the AI to schedule an appointment.
+
+6. **Merge or Exit**
+
+ - If the specialist answers, they join the user.
+ - If not, the user is taken off hold and the call ends or goes back to AI.
+
+7. **Use Ephemeral Call (Optional)**
+ - If you need an in-conference announcement, create a short-lived Twilio call that `` the message to everyone, then ends the conference.
+
+## Code Example
+
+Below is a minimal Express.js server aligned for On-Hold Specialist Transfer with Vapi and Twilio.
+
+1. **Express Setup and Environment**
+
+```js
+const express = require("express");
+const bodyParser = require("body-parser");
+const axios = require("axios");
+const twilio = require("twilio");
+
+const app = express();
+app.use(bodyParser.urlencoded({ extended: true }));
+app.use(bodyParser.json());
+
+// Load important env vars
+const {
+ TWILIO_ACCOUNT_SID,
+ TWILIO_AUTH_TOKEN,
+ FROM_NUMBER,
+ TO_NUMBER,
+ VAPI_BASE_URL,
+ PHONE_NUMBER_ID,
+ ASSISTANT_ID,
+ PRIVATE_API_KEY,
+} = process.env;
+
+// Create a Twilio client
+const client = twilio(TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN);
+
+// We'll store the inbound call SID here for simplicity
+let globalCallSid = "";
+```
+
+2. **`/inbound_call` - Handling the Inbound Call**
+
+```js
+app.post("/inbound_call", async (req, res) => {
+ try {
+ globalCallSid = req.body.CallSid;
+ const caller = req.body.Caller;
+
+ // Example: We call Vapi.ai to get initial TwiML
+ const response = await axios.post(
+ `${VAPI_BASE_URL || "https://api.vapi.ai"}/call`,
+ {
+ phoneNumberId: PHONE_NUMBER_ID,
+ phoneCallProviderBypassEnabled: true,
+ customer: { number: caller },
+ assistantId: ASSISTANT_ID,
+ },
+ {
+ headers: {
+ Authorization: `Bearer ${PRIVATE_API_KEY}`,
+ "Content-Type": "application/json",
+ },
+ }
+ );
+
+ const returnedTwiml = response.data.phoneCallProviderDetails.twiml;
+ return res.type("text/xml").send(returnedTwiml);
+ } catch (err) {
+ return res.status(500).send("Internal Server Error");
+ }
+});
+```
+
+3. **`/connect` - Putting User on Hold and Dialing Specialist**
+
+```js
+app.post("/connect", async (req, res) => {
+ try {
+ const protocol =
+ req.headers["x-forwarded-proto"] === "https" ? "https" : "http";
+ const baseUrl = `${protocol}://${req.get("host")}`;
+ const conferenceUrl = `${baseUrl}/conference`;
+
+ // 1) Update inbound call to fetch TwiML from /conference
+ await client.calls(globalCallSid).update({
+ url: conferenceUrl,
+ method: "POST",
+ });
+
+ // 2) Dial the specialist
+ const statusCallbackUrl = `${baseUrl}/participant-status`;
+
+ await client.calls.create({
+ to: TO_NUMBER,
+ from: FROM_NUMBER,
+ url: conferenceUrl,
+ method: "POST",
+ statusCallback: statusCallbackUrl,
+ statusCallbackMethod: "POST",
+ });
+
+ return res.json({ status: "Specialist call initiated" });
+ } catch (err) {
+ return res.status(500).json({ error: "Failed to connect specialist" });
+ }
+});
+```
+
+4. **`/conference` - Placing Callers Into a Conference**
+
+```js
+app.post("/conference", (req, res) => {
+ const VoiceResponse = twilio.twiml.VoiceResponse;
+ const twiml = new VoiceResponse();
+
+ // Put the caller(s) into a conference
+ const dial = twiml.dial();
+ dial.conference(
+ {
+ startConferenceOnEnter: true,
+ endConferenceOnExit: true,
+ },
+ "my_conference_room"
+ );
+
+ return res.type("text/xml").send(twiml.toString());
+});
+```
+
+5. **`/participant-status` - Handling No-Answer or Busy**
+
+```js
+app.post("/participant-status", async (req, res) => {
+ const callStatus = req.body.CallStatus;
+ if (["no-answer", "busy", "failed"].includes(callStatus)) {
+ console.log("Specialist did not pick up:", callStatus);
+ // Additional logic: schedule an appointment, ephemeral call, etc.
+ }
+ return res.sendStatus(200);
+});
+```
+
+6. **`/announce` (Optional) - Ephemeral Announcement**
+
+```js
+app.post("/announce", (req, res) => {
+ const VoiceResponse = twilio.twiml.VoiceResponse;
+ const twiml = new VoiceResponse();
+ twiml.say("Specialist is not available. Ending call now.");
+
+ // Join the conference, then end it.
+ twiml.dial().conference(
+ {
+ startConferenceOnEnter: true,
+ endConferenceOnExit: true,
+ },
+ "my_conference_room"
+ );
+
+ return res.type("text/xml").send(twiml.toString());
+});
+```
+
+7. **Starting the Server**
+
+```js
+app.listen(3000, () => {
+ console.log("Server running on port 3000");
+});
+```
+
+## How to Test
+
+1. **Environment Variables**
+ Set `TWILIO_ACCOUNT_SID`, `TWILIO_AUTH_TOKEN`, `FROM_NUMBER`, `TO_NUMBER`, `VAPI_BASE_URL`, `PHONE_NUMBER_ID`, `ASSISTANT_ID`, and `PRIVATE_API_KEY`.
+
+2. **Expose Your Server**
+
+ - Use a tool like `ngrok` to create a public URL to port 3000.
+ - Configure your Twilio phone number to call `/inbound_call` when a call comes in.
+
+3. **Place a Real Call**
+
+ - Dial your Twilio number from a phone.
+ - Twilio hits `/inbound_call`, and run Vapi logic.
+ - Trigger `/connect` to conference the user and dial the specialist.
+ - If the specialist answers, they join the same conference.
+ - If they never answer, Twilio eventually calls `/participant-status`.
+
+4. **Use cURL for Testing**
+ - **Simulate Inbound**:
+ ```bash
+ curl -X POST https:///inbound_call \
+ -F "CallSid=CA12345" \
+ -F "Caller=+15551112222"
+ ```
+ - **Connect**:
+ ```bash
+ curl -X POST https:///connect \
+ -H "Content-Type: application/json" \
+ -d "{}"
+ ```
+
+## Note on Replacing "Connect" with Vapi Tools
+
+Vapi offers built-in functions or custom tool calls for placing a second call or transferring, you can replace the manual `/connect` call with that Vapi functionality. The flow remains the same: user is put in a Twilio conference, the specialist is dialed, and any no-answer events are handled.
+
+## Notes & Limitations
+
+1. **Voicemail**
+ If a phone’s voicemail picks up, Twilio sees it as answered. Consider advanced detection or a fallback.
+
+2. **Concurrent Calls**
+ Multiple calls at once require storing separate `CallSid`s or similar references.
+
+3. **Conference Behavior**
+ `startConferenceOnEnter: true` merges participants immediately; `endConferenceOnExit: true` ends the conference when that participant leaves.
+
+4. **X Seconds**
+ Decide how you detect no-answer. Typically, Twilio sets a final `callStatus` if the remote side never picks up.
+
+With these steps and code, you can integrate Vapi Assistant while using Twilio’s conferencing features to hold, dial out to a specialist, and handle an unanswered or unavailable specialist scenario.
+
+
+ This is the content for the doc fern/calls/call-outbound.mdx
+
+ ---
+title: Outbound Calling
+subtitle: Learn how to send outbound calls from Vapi.
+slug: calls/outbound-calling
+---
+
+## Introduction to Outbound Calling
+
+Vapi’s outbound calling API lets you programmatically initiate single or batch calls to any phone number. You can schedule calls for specific dates and times, ideal for time-sensitive communications. Easily integrate outbound calling into your app for appointment reminders, automated surveys, and call campaigns.
+
+## Prerequisites
+
+- **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).
+- **Customer's Phone Number**: The phone number that you want to call.
+
+## Outbound Calls
+
+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.
+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!
+
+```jsx
+{
+ "assistantId": "assistant-id",
+ "phoneNumberId": "phone-number-id",
+ "customer": {
+ "number": "+11231231234"
+ }
+}
+```
+
+## 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.
+
+When you schedule a call, we will save the Assistant, Phone Number, and Customer Number resources and refetch them at the time of the call. If you choose to provide a saved assistant through `assistantId`, we will pick up the most up-to-date version of your assistant at the call time. Likewise, if you delete your saved assistant, the call will fail! To ensure the call is issued with a static version of an assistant, pass it as a transient assistant through the `assistant` parameter.
+
+```jsx
+{
+ "assistantId": "assistant-id",
+ "phoneNumberId": "phone-number-id",
+ "customer": {
+ "number": "+11231231234"
+ },
+ "schedulePlan": {
+ "earliestAt": "2025-05-30T00:00:00Z"
+ }
+}
+```
+
+## Batch Calling [#batch-calling]
+
+To call more than one number at a time, use the [`customers`](/api-reference/calls/create#request.body.customers) parameter to pass an array of `customer`. To provide customer specific assistant overrides, please call the endpoint separately for each destination number.
+
+Use both `customers` and `schedulePlan` together to schedule batched calls.
+
+```jsx
+{
+ "assistantId": "assistant-id",
+ "phoneNumberId": "phone-number-id",
+ "customers": [
+ {
+ "number": "+11231231234"
+ },
+ {
+ "number": "+12342342345"
+ }
+ ],
+ "schedulePlan": {
+ "earliestAt": "2025-05-30T00:00:00Z"
+ }
+}
+```
+
+Note: Vapi free numbers have limited number of outbound calls per day. Import a number from Twilio, Vonage, or Telnyx to scale without limits.
+
+
+ It is a violation of FCC law to dial phone numbers without consent in an
+ automated manner. See [Telemarketing Sales
+ Rule](/glossary#telemarketing-sales-rule) to learn more.
+
+
+ This is the content for the doc fern/calls/voicemail-detection.mdx
+
+ ---
+title: Voicemail Detection
+slug: calls/voicemail-detection
+---
+
+Voicemail is basically a digital answering machine. When you can’t pick up, callers can leave a message so you don’t miss anything important. It’s especially handy if you’re in a meeting, driving, or just can’t get to the phone in time.
+
+### **The Main Problem**
+
+If a lot of your calls are landing in voicemail, you could be spending too much time and money on calls that never connect to a real person. This leads to wasted resources, and sometimes missed business opportunities.
+
+### **The Solution: Early Voicemail Detection**
+
+By detecting voicemail right away, your Vapi Assistant can either hang up (if leaving a message isn’t necessary) or smoothly play a recorded message. This cuts down on useless call time and makes your entire call flow more efficient.
+
+## **Two Ways to Detect Voicemail**
+
+### **1. Using Twilio’s Voicemail Detection**
+
+Twilio has built-in features to detect when a machine picks up. You configure these settings in your Vapi Assistant so it knows when a voicemail system has answered instead of a live person.
+
+```jsx
+voicemailDetection: {
+ provider: "twilio",
+ voicemailDetectionTypes: [
+ "machine_start",
+ "machine_end_beep",
+ "machine_end_silence",
+ "unknown",
+ "machine_end_other"
+ ],
+ enabled: true,
+ machineDetectionTimeout: 15,
+ machineDetectionSpeechThreshold: 2500,
+ machineDetectionSpeechEndThreshold: 2050,
+ machineDetectionSilenceTimeout: 2000
+}
+
+```
+
+- **provider**: Tells Vapi to use Twilio’s system.
+- **voicemailDetectionTypes**: Defines the events that mean “voicemail.”
+- **machineDetectionTimeout**: How many seconds to wait to confirm a machine.
+- The other settings let you fine-tune how quickly or accurately Twilio identifies a machine based on speech or silence.
+
+#### Quick Reference
+
+| Setting | Type | Valid Range | Default |
+| ---------------------------------- | ------ | ------------- | -------- |
+| machineDetectionTimeout | number | 3 – 59 (sec) | 30 (sec) |
+| machineDetectionSpeechThreshold | number | 1000–6000 ms | 2400 ms |
+| machineDetectionSpeechEndThreshold | number | 500–5000 ms | 1200 ms |
+| machineDetectionSilenceTimeout | number | 2000–10000 ms | 5000 ms |
+
+### **2. Using VAPI’s Built-In Voicemail Tool**
+
+Vapi also has an LLM-powered tool that listens for typical voicemail greetings or prompts in the call’s audio transcription. If you prefer an approach that relies more on phrasing and context clues, this is a great option.
+
+```jsx
+{
+ ...yourExistingSettings,
+ "model": {
+ "tools": [{ type: "voicemail" }]
+ }
+}
+
+```
+
+Here, `tools: [{ type: "voicemail" }]` signals that your Vapi Assistant should look for keywords or patterns indicating a voicemail greeting.
+
+## **Combining Both Approaches**
+
+For the best of both worlds, you can enable Twilio’s detection **and** the built-in voicemail tool at the same time:
+
+```jsx
+{
+ ...yourExistingSettings,
+ voicemailDetection: {
+ provider: "twilio",
+ voicemailDetectionTypes: [
+ "machine_start",
+ "machine_end_beep",
+ "unknown"
+ ],
+ enabled: true,
+ machineDetectionTimeout: 15
+ },
+ model: {
+ tools: [{ type: "voicemail" }]
+ }
+}
+
+```
+
+When one method doesn’t catch it, the other might—boosting your overall detection accuracy.
+
+## **Tips for Better Voicemail Handling**
+
+1. **Adjust Detection Timing**
+
+ Lower `machineDetectionTimeout` (e.g., to 5 seconds) if you want the system to decide faster. But remember, shorter timeouts can lead to occasional false positives.
+
+2. **Fine-Tune Speech and Silence Thresholds**
+
+ For example:
+
+ ```jsx
+ {
+ "provider": "twilio",
+ "enabled": true,
+ "machineDetectionTimeout": 5,
+ "machineDetectionSpeechThreshold": 2400,
+ "machineDetectionSpeechEndThreshold": 1000,
+ "machineDetectionSilenceTimeout": 3000
+ }
+
+ ```
+
+ These values tweak how quickly Twilio “listens” for human speech or background silence.
+
+3. **Think Through Your Call Flow**
+ - **Give It Time**: If you’re leaving a message, you might want to increase `startSpeakingPlan.waitSeconds` so the detection has enough time before the tone.
+ - **firstMessageMode**: Setting it to `assistant-waits-for-user` can also give you smoother call handling—your assistant won’t barge in if someone unexpectedly picks up late
+
+## **What Happens When a Call Ends?**
+
+- **Detected Voicemail + No Message**: The call will end, and you’ll see a reason like `customer-did-not-answer`.
+- **Detected Voicemail + Have a Message**: Your assistant leaves the recorded message, and the call ends with a reason like `voicemail`.
+
+## **Testing and Next Steps**
+
+1. **Make a Test Call**: Dial a known voicemail number and watch how quickly (and accurately) your Vapi Assistant identifies the machine.
+2. **Tweak Settings**: Adjust your timeout and threshold values based on real-world performance.
+3. **Repeat**: Keep testing until you’re confident your configuration is catching voicemail reliably without cutting off real people.
+
+By following these steps, you’ll save time, improve call-handling efficiency, and ensure your system feels more professional. If you need to fine-tune or add new features later, you can always revisit these settings and make quick adjustments.
+
+
+ This is the content for the doc fern/calls/websocket-transport.mdx
+
+ ---
+title: WebSocket Transport
+description: Stream audio directly via WebSockets for real-time, bidirectional communication
+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
+
+- **Low Latency**: Direct streaming ensures minimal delays.
+- **Bidirectional Streaming**: Real-time audio flow in both directions.
+- **Easy Integration**: Compatible with any environment supporting WebSockets.
+- **Flexible Audio Formats**: Customize audio parameters such as sample rate.
+- **Automatic Sample Rate Conversion**: Seamlessly handles various audio rates.
+
+## Creating a WebSocket Call
+
+To initiate a call using WebSocket transport:
+
+```bash
+curl 'https://api.vapi.ai/call' \
+ -H 'authorization: Bearer YOUR_API_KEY' \
+ -H 'content-type: application/json' \
+ --data-raw '{
+ "assistant": { "assistantId": "YOUR_ASSISTANT_ID" },
+ "transport": {
+ "provider": "vapi.websocket",
+ "audioFormat": {
+ "format": "pcm_s16le",
+ "container": "raw",
+ "sampleRate": 16000
+ }
+ }
+ }'
+```
+
+### Sample API Response
+
+```json
+{
+ "id": "7420f27a-30fd-4f49-a995-5549ae7cc00d",
+ "assistantId": "5b0a4a08-133c-4146-9315-0984f8c6be80",
+ "type": "vapi.websocketCall",
+ "createdAt": "2024-09-10T11:14:12.339Z",
+ "updatedAt": "2024-09-10T11:14:12.339Z",
+ "orgId": "eb166faa-7145-46ef-8044-589b47ae3b56",
+ "cost": 0,
+ "status": "queued",
+ "transport": {
+ "provider": "vapi.websocket",
+ "websocketCallUrl": "wss://api.vapi.ai/7420f27a-30fd-4f49-a995-5549ae7cc00d/transport"
+ }
+}
+```
+
+## Audio Format Configuration
+
+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) |
+
+Currently, Vapi supports only raw PCM (`pcm_s16le` with `raw` container). Additional formats may be supported in future updates.
+
+
+Vapi automatically converts sample rates as needed. You can stream audio at 8kHz, 44.1kHz, etc., and Vapi will handle conversions seamlessly.
+
+
+## Connecting to the WebSocket
+
+Use the WebSocket URL from the response to establish a connection:
+
+```javascript
+const socket = new WebSocket("wss://api.vapi.ai/7420f27a-30fd-4f49-a995-5549ae7cc00d/transport");
+
+socket.onopen = () => console.log("WebSocket connection opened.");
+socket.onclose = () => console.log("WebSocket connection closed.");
+socket.onerror = (error) => console.error("WebSocket error:", error);
+```
+
+## Sending and Receiving Data
+
+The WebSocket supports two types of messages:
+
+- **Binary audio data** (PCM, 16-bit signed little-endian)
+- **Text-based JSON control messages**
+
+### Sending Audio Data
+
+```javascript
+function sendAudioChunk(audioBuffer) {
+ if (socket.readyState === WebSocket.OPEN) {
+ socket.send(audioBuffer);
+ }
+}
+
+navigator.mediaDevices.getUserMedia({ audio: true }).then(stream => {
+ const audioContext = new AudioContext();
+ const source = audioContext.createMediaStreamSource(stream);
+ const processor = audioContext.createScriptProcessor(1024, 1, 1);
+
+ processor.onaudioprocess = (event) => {
+ const pcmData = event.inputBuffer.getChannelData(0);
+ const int16Data = new Int16Array(pcmData.length);
+
+ for (let i = 0; i < pcmData.length; i++) {
+ int16Data[i] = Math.max(-32768, Math.min(32767, pcmData[i] * 32768));
+ }
+
+ sendAudioChunk(int16Data.buffer);
+ };
+
+ source.connect(processor);
+ processor.connect(audioContext.destination);
+});
+```
+
+### Receiving Data
+
+```javascript
+socket.onmessage = (event) => {
+ if (event.data instanceof Blob) {
+ event.data.arrayBuffer().then(buffer => {
+ const audioData = new Int16Array(buffer);
+ playAudio(audioData);
+ });
+ } else {
+ try {
+ const message = JSON.parse(event.data);
+ handleControlMessage(message);
+ } catch (error) {
+ console.error("Failed to parse message:", error);
+ }
+ }
+};
+```
+
+### Sending Control Messages
+
+```javascript
+function sendControlMessage(messageObj) {
+ if (socket.readyState === WebSocket.OPEN) {
+ socket.send(JSON.stringify(messageObj));
+ }
+}
+
+// Example: hangup call
+function hangupCall() {
+ sendControlMessage({ type: "hangup" });
+}
+```
+
+## Ending the Call
+
+To gracefully end the WebSocket call:
+
+```javascript
+sendControlMessage({ type: "hangup" });
+socket.close();
+```
+
+## Comparison: WebSocket Transport vs. Call Listen Feature
+
+Vapi provides two WebSocket options:
+
+| WebSocket Transport | Call Listen Feature |
+|-------------------------------------|------------------------------------|
+| Primary communication method | Secondary, monitoring-only channel |
+| Bidirectional audio streaming | Unidirectional (listen-only) |
+| Replaces phone/web as transport | Supplements existing calls |
+| Uses `provider: "vapi.websocket"` | Accessed via `monitor.listenUrl` |
+
+Refer to [Live Call Control](/calls/call-features) for more on the Call Listen feature.
+
+
+When using WebSocket transport, phone-based parameters (`phoneNumber` or `phoneNumberId`) are not permitted. These methods are mutually exclusive.
+
+
+
+
+ This is the content for the doc fern/changelog/2024-10-07.mdx
+
+ 1. **Add Structured Outputs for OpenAI Functions in Assistant Tools**: You can use [OpenAI Structured Outputs](https://platform.openai.com/docs/guides/structured-outputs) by specifying a new parameter called `strict` as true or false when creating or using `OpenAIFunction`s in `assistant.model.tools[type=function]`. Set the `name`, provide a `description` (up to 1000 characters), and specify `parameters` as a [JSON Schema object](https://json-schema.org/understanding-json-schema). See the [OpenAI guide](https://platform.openai.com/docs/guides/function-calling) for examples.
+
+2. **Secure Incoming SIP Phone Calls to Vapi Provided SIP Numbers**: You can now specify a `username`, `password`, and optional `realm` in SIP Invite AuthZ header, through digest authentication. Create this secure SIP number by specifying an "authentication" object with the username and password fields inside `POST /phone-number` request body. Example:
+```bash
+curl --location 'https://api.vapi.ai/phone-number' \
+--header 'Content-Type: application/json' \
+--header 'Authorization: Bearer {}API_KEY}}' \
+--data-raw '{
+ "provider": "vapi",
+ "sipUri": "sip:{{USERNAME}}@sip.vapi.ai",
+ "assistantId": "{{ASSISTANT_ID}}",
+ "name": "example phone number label for your reference",
+ "authentication": {
+ "realm": "sip.vapi.ai",
+ "username": "test@example.com",
+ "password": "example_password"
+ }
+}'
+```
+
+3. **Use Updated `handoff`, `callback` Steps in Blocks**: You can now use `assistant.model.steps[type=handoff]` and `assistant.model.steps[type=callback]` to control conversation flow in your assistant. Use `HandoffStep` to move to the next step linearly without returning to the previous step, ideal for sequential tasks like forms. Use `CallbackStep` to spawn a new conversation thread and return to the previous step once done, good for handling interruptions or sub-tasks within a conversation.
+
+4. **Use Step Destinations and Assignment Mutation in Blocks**: Specify destination nodes for each step with `assistant.model.steps[type=handoff].destinations[type=step]` to direct the workflow to specific steps based on certain conditions. Update context variables in each callback step with `mutations[type=assignment]`, for example: `assistant.model.steps[type=callback].mutations[type=assignment]`
+
+ This is the content for the doc fern/changelog/2024-10-08.mdx
+
+ 1. **New GPT-4o Model Support for Azure OpenAI**: You can now specify the `gpt-4o-2024-08-06` model in the `models` field when configuring Azure OpenAI credentials. Use this model to access the latest GPT-4 operational capabilities in your applications.
+
+2. **Specify Timestamps as Strings in `/logs`**: We now expect timestamps as strings when working with logs. Please make sure to handle this accordingly in your applications.
+
+ This is the content for the doc fern/changelog/2024-10-09.mdx
+
+ 1. **Call Cost Information**: You can now use `call.costs[type=vapi].subType` to determine if a Vapi cost is `normal` or an `overage`.
+
+2. **Updated Billing Page**: Your payments are now returned inside a table with pages on the [billing page](https://dashboard.vapi.ai/org/billing).
+
+ This is the content for the doc fern/changelog/2024-10-10.mdx
+
+ 1. **Purchase Reserved Concurrency and Scale Infinitely**: You can now reserve more concurrent calls with Vapi and scale infinitely by switching to our new top up payment system on the [billing page](https://dashboard.vapi.ai/org/billing). To migrate, click "Switch to Credit Based Billing" and make a payment. Advantages include:
+
+ - **Support More Users Without Limits**: You don't need to worry about getting throttled or staying under usage limits on the conversations you can have with Vapi.
+ - **Predictable Budgets**: You know exactly how much you will spend on Vapi each month, and you can top up at any time as your needs grow.
+ - **Select Add-Ons You Need**: The credit based billing page allows you to select HIPAA compliance, dedicated Slack support, and the maximum number of concurrent calls you expect.
+
+This will require human input to login and migrate your account. You will not be able to revert back to the old billing system.
+
+ This is the content for the doc fern/changelog/2024-10-13.mdx
+
+ 1. **New Call Transfer Modes Added**: you can now wait for an operator to speak first before providing a transfer message or summary when transferring calls to a new destination with `TransferPlan`. Configure this through *transferPlan.mode=`'warm-transfer-wait-for-operator-to-speak-first-and-then-say-message'`* or *transferPlan.mode=`'warm-transfer-wait-for-operator-to-speak-first-and-then-say-summary'`* inside the request body of `POST /assistant` or `PATCH /assistant`.
+
+2. **Unified Server Configuration in Assistants**: You can now use the `server` property in `Assistant.server`, `AssistantOverrides.server`, and when creating or updating assistants to specify webhook settings, including URL, secret, custom headers, and timeout. This replaces the old `serverUrl` and `serverUrlSecret` properties of `Assistant`.
+
+ Include custom headers in your webhook requests by using the `headers` property within the `server` object when creating or updating assistants.
+
+3. **Configure PlayHT Voice Engines**: You can now configure which PlayHT voice `model` generates voices for your application between `PlayHT2.0`, `PlayHT2.0-turbo`, and `Play3.0-mini`.
+
+ This is the content for the doc fern/changelog/2024-10-16.mdx
+
+ 1. **Apply Coupons to Subscriptions**: You can now apply coupons by specifying a `couponId` to add to a subscription.
+
+2. **Detect Custom Transcriber Failures in Call End Reasons**: You can now handle cases where a custom transcriber fails during a call with `'pipeline-error-custom-transcriber-failed'`, a new `endedReason` option. This is now accessible in `Call`, `ServerMessageStatusUpdate`, and `ServerMessageEndOfCallReport`.
+
+3. **Corrected Typo in Example Custom Voice Request**: We fixed a typo in `CustomVoice.server`, where the example request now shows how to use the `"message"` parameter instead of the misspelled `"messsage"`.
+
+ This is the content for the doc fern/changelog/2024-10-19.mdx
+
+ 1. **Custom Transcriber Support**: You can now integrate your own transcription service by using `CustomTranscriber` at `assistant.transcriber`, `call.squad.members.assistant.transcriber`, and `call.squad.members.assistantOverrides.transcriber`. Provide your custom transcription server details via `server.url` to receive real-time transcriptions during calls.
+
+2. **Increased Maximum Call Duration**: The maximum allowed value for `maxDurationSeconds` has increased from 21,600 to 43,200 seconds when creating or updating `Assistant` or `AssistantOverrides`. You can now configure your assistant to handle calls lasting up to 12 hours.
+
+3. **New Voice Provider 'tavus'**: You can now specify `tavus` as a voice provider in `Assistant.voice`, `AssistantOverrides.voice`, `Call.voice` and in the Voice Library.
+
+4. **Subscription Status 'frozen' Added**: A new status `frozen` has been added to `Subscription.status`, indicating when a subscription is temporarily inactive.
+
+5. **Added Subscription Coupon Codes**: You can now apply coupon codes to your subscription. Visit the [billing page](https://dashboard.vapi.ai/org/billing) to apply coupons to specific organizations within a subscription.
+
+ This is the content for the doc fern/changelog/2024-10-22.mdx
+
+ 1. **Invite Multiple Users via Email**: You can now invite up to 100 users at once by providing a list of email addresses inside your [org users page](https://dashboard.vapi.ai/org/users). Click `'+'` after entering an email address, select the role as *Editor* or *Admin*, and click `'Invite'`.
+
+2. **Simplified Subscription Status Handling**: Your subscription status no longer includes the `past-due` status, so you can streamline your subscription management without handling 'past-due' scenarios.
+
+ This is the content for the doc fern/changelog/2024-10-25.mdx
+
+ 1. **Specify API Traffic Channel for Organizations**: You can now configure which `channel` (cluster) your API traffic will be routed to. Select between *daily* or *weekly* in your [organization settings page](https://dashboard.vapi.ai/org/settings)
+
+2. **Customize Tavus Voice Properties**: You can now use Tavus as a voice provider under `assistant.voice`. Configure additional properties like language, recording options, and transcriptions via `assistant.voice.properties`.
+
+3. **Multilingual Support in Tool Messages**: You can now use the `contents` property in `ToolMessageStart`, `ToolMessageFailed`, `ToolMessageDelayed`, and `ToolMessageComplete` to provide message variants for different languages. If you don't provide content for a language, the first item will be automatically translated to the active language during the conversation.
+
+4. **Automatic Translation of Message Contents**: For `CustomMessage`, `BlockStartMessage`, and `BlockCompleteMessage`, if specific content isn't provided for a language in `contents`, Vapi automatically translates the first item to the active language by default.
+
+5. **Removed Backchanneling Configuration**: The `backchannelingEnabled` property has been removed from when creating or updating `Assistant` or `AssistantOverrides`. Backchanneling is no longer configurable in assistant settings.
+
+ This is the content for the doc fern/changelog/2024-10-29.mdx
+
+ 1. **Gemini Model Support and Credential Management**: You can now use Google Gemini models for your assistant (*gemini-1.5-flash-8b*, *gemini-1.5-flash-002*, *gemini-1.5-pro*, *gemini-1.0-pro*). Create and update your Google credentials by providing your `apiKey` from [Google AI Studio](https://aistudio.google.com/app/apikey) and setting your provider to `'google'` in Vapi.
+
+
+
+
+
+2. **New Anthropic Model `claude-3-5-sonnet-20241022`**: You can now include Computer Use tools in the `toolWithToolCallList` of `ClientMessageToolCalls` or `ServerMessageToolCalls`. Select `'anthropic'` as your provider, `claude-3-5-sonnet-20241022`, and [create](https://api.vapi.ai/api#/Tools/ToolController_create) or [update](https://api.vapi.ai/api#/Tools/ToolController_update) newly supported computer use tools like `BashTool`, `ComputerTool`, or `TextEditorTool`.
+
+
+
+
+
+3. **Enhanced Email Regex Support in Replacements**: The email matching regex pattern in `RegexReplacement` now supports top-level domains with two or more characters (`{2,}`). This improvement allows you to replace email addresses with placeholders like `[EMAIL]`, even for longer TLDs.
+
+4. **Paginated Phone Number Responses**: [`GET /phone-numbers`](https://api.vapi.ai/api#/Phone%20Numbers/PhoneNumberController_findAll) now includes a `results` array of phone numbers and pagination metadata for easier handling of large datasets.
+
+ This is the content for the doc fern/changelog/2024-10-30.mdx
+
+ 1. **Auto-reload Credits in Billing Page**: You can now auto-reload credits and check credits remaining for subscriptions within the [updated billing page](https://dashboard.vapi.ai/org/billing).
+
+
+
+
+
+2. **Expanded Language Options in `CartesiaVoice`**: You can now specify additional languages in `CartesiaVoice.language` (optional), including 'hi' (Hindi), 'it' (Italian), 'ko' (Korean), 'nl' (Dutch), 'pl' (Polish), 'ru' (Russian), 'sv' (Swedish), and 'tr' (Turkish). Refer to the [CartesiaVoice](https://api.vapi.ai/api) schema for more details.
+
+
+
+
+
+3. **Enhanced Template Variables in `AssistantOverrides`**: The `AssistantOverrides.variableValues` now supports LiquidJS syntax for replacing template variables. You can customize assistant messages using expressions like `{{ name }}` for dynamic content, or format dates with `{{"now" | date: "%b %d, %Y, %I:%M %p", "America/New_York"}}`.
+
+ This is the content for the doc fern/changelog/2024-11-03.mdx
+
+ 1. **Access Transport Details and Costs**: You can now use `call.transport` to access details about the provider used for a call (`twilio`, `vonage`, `vapi`, or `daily`), and whether the assistant's video is enabled for web calls (`assistantVideoEnabled`). Additionally, transport costs in `call.costs[type=transport]` now include a `provider` field, allowing you to see which provider contributed to the transport cost.
+
+2. **Manage Tavus Credentials**: You can now create and update Tavus credentials in the [updated Provider Credentials page](https://dashboard.vapi.ai/keys).
+
+
+
+
+
+ This is the content for the doc fern/changelog/2024-11-04.mdx
+
+ 1. **XAi Model Support**: You can now use xAI's `grok-beta` model when creating or updating an assistant, and specify your API credentials from the [xAI console](https://console.x.ai/) in the [updated Provider Credentials page](https://dashboard.vapi.ai/keys). The list of call ended reasons has been updated to include xAI-specific errors.
+
+
+
+
+
+ This is the content for the doc fern/changelog/2024-11-06.mdx
+
+ 1. **New Anthropic model `claude-3-5-haiku-20241022` added**: You can now use `claude-3-5-haiku-20241022` in your assistants. Specify `anthropic` in `Assistant.model.provider` and `claude-3-5-haiku-20241022` in `Assistant.model`.
+
+2. **Payment `cost`, Subscription `credits` and `couponUsageLeft` are now strings**: These properties are now strings to avoid floating point precision errors. Please update your applications to handle these values as strings.
+
+3. **Advanced call logging improvements**: You can now access detailed call logs through the [updated call logs page](https://dashboard.vapi.ai/calls) or [`GET /logs?type=Call`](https://api.vapi.ai/api#/Logs/LoggingController_queryLogs) endpoint. Refer to `CallLogPrivileged` or `CallLogsPaginatedResponse` schemas in the [updated API reference](https://api.vapi.ai/api) to learn more.
+
+ This is the content for the doc fern/changelog/2024-11-11.mdx
+
+ 1. **Subscription Updates**: You can now check the number of minutes used in a subscription with `Subscription.minutesUsed` (Enterprise only).
+
+2. **Updates to Concurrency Limits in your Subscription**: `Subscription.concurrencyLimit` now shows both the included and purchased limits, which better represents the total concurrency limit. Refer to the [Subscription schema](https://api.vapi.ai/api/) for more details.
+ - Use `Subscription.concurrencyLimitIncluded` to get the default concurrency limit provided with the subscription.
+ - Use `Subscription.concurrencyLimitPurchased` to get any additional purchased concurrency limit.
+
+
+
+
+
+ This is the content for the doc fern/changelog/2024-11-14.mdx
+
+ 1. **Langfuse Credential Management**: You can now send traces to Langfuse by providing your "Secret Key", "Public Key", and "Host URL" for better telemetry monitoring. Create and update these credentials in the [updated Provider Credentials page](https://dashboard.vapi.ai/keys), under `Observability Providers`.
+
+
+
+
+
+ This is the content for the doc fern/changelog/2024-11-15.mdx
+
+ 1. **New Voices for `gpt-4o-realtime-preview-2024-10-01`**: You can now use new voice IDs: `ash`, `ballad`, `coral`, `sage`, and `verse` with the `voiceId` parameter when configuring `OpenAIVoice`. Please note that these voices are only available with the `gpt-4o-realtime-preview-2024-10-01` model.
+
+ This is the content for the doc fern/changelog/2024-11-21.mdx
+
+ 1. **Voice Fallback Plan**: You can now define a `fallbackPlan` in your assistant's voice settings in `assistant.voice.fallbackPlan` or `call.squad.members.assistant.voice.fallbackPlan` to specify alternative voices if your primary voice provider fails.
+
+2. **AssemblyAI Credential Management**: You can now specify your AssemblyAI API keys in the updated "Transcriber Providers" page. Create your API key in the [AssemblyAI dashboard](https://www.assemblyai.com/app/account). AssemblyAI errors are now surfaced in the `endedReason` of `Call`, `ServerMessageEndOfCallReport`, and `ServerMessageStatusUpdate`.
+
+
+
+
+
+3. **Enhanced BYO SIP Trunk Configuration**: When configuring BYO SIP trunk credentials, you can now specify a `techPrefix` for outbound SIP calls and enable `sipDiversionHeader` for authenticating the calling number (if supported). Refer to the `ByoSipTrunkCredential` schema in the [API reference](https://api.vapi.ai/api) to learn more.
+
+
+
+
+
+4. **File Name Length Constraints**: The maximum file `name` length has been reduced from 100 to 40 characters. The required minimum length is still 1 character.
+
+5. **Increased Server Timeout Limit**: The maximum value of `server.timeoutSeconds` has increased from 60 to 120 seconds, allowing longer timeouts for server responses.
+
+7. **Extended Delay for Tool Messages**: The `timingMilliseconds` maximum in `ToolMessageDelayed` has increased from 20,000 to 120,000 milliseconds, enabling a longer delay for tool messages.
+
+
+ This is the content for the doc fern/changelog/2024-11-22.mdx
+
+ 1. **Support for 'uaenorth' Region in Azure OpenAI Credentials**: When configuring Azure OpenAI credentials, you can now set `region` to use the UAE North region by specifying `'uaenorth'`.
+
+ This is the content for the doc fern/changelog/2024-11-24.mdx
+
+ 1. **Voice Fallback Plan Introduced**: You can now enhance your assistant's reliability by defining fallback voice providers using `assistant.voice.fallbackPlan.voices`. This allows your assistant to switch to alternative voices or providers like `FallbackLMNTVoice`, `FallbackAzureVoice`, `FallbackNeetsVoice`, `FallbackTavusVoice`, `FallbackOpenAIVoice`, and others if the primary voice provider fails.
+
+
+
+
+
+2. **Language Selection for PlayHTVoice**: The `language` property has been added to `PlayHTVoice`. You can now specify the desired language for speech synthesis using `assistant.voice.language`.
+
+3. **AssemblyAI Transcriber Available**: You can now use AssemblyAI for transcribing by setting `Assistant.transcriber` to `AssemblyAITranscriber`. This provides a new option for converting speech to text in your assistant.
+
+4. **Updated OpenAI Model Support**: The `gpt-4o-2024-11-20` model has been added to `OpenAIModel.model` and `OpenAIModel.fallbackModels`. You can now configure your assistant to use this latest OpenAI model.
+
+5. **Removal of 'fillerInjectionEnabled' Property**: The `fillerInjectionEnabled` property has been removed from voice configurations like `LMNTVoice`, `AzureVoice`, etc. You no longer need to include this property when configuring these voices.
+
+
+ This is the content for the doc fern/changelog/2024-11-25.mdx
+
+ 1. **No length limit for assistant's first message**: You can now set `assistant.firstMessage` or `call.assistant.firstMessage` to any length; the previous maximum length restriction has been removed. This allows you to provide longer initial messages for the assistant's greeting.
+
+
+
+
+
+
+
+ This is the content for the doc fern/changelog/2024-11-27.mdx
+
+ 1. **New Knowledge Base API Endpoints**: You can now create a knowledge base with [`POST /knowledge-base`](https://api.vapi.ai/api#/Knowledge%20Base/KnowledgeBaseController_create), list knowledge bases with [`GET /knowledge-base`](https://api.vapi.ai/api#/Knowledge%20Base/KnowledgeBaseController_findAll) or [`GET /knowledge-base/{id}`](https://api.vapi.ai/api#/Knowledge%20Base/KnowledgeBaseController_findOne) for a specific knowledge base, update a knowledge base with [`PATCH /knowledge-base/{id}`](https://api.vapi.ai/api#/Knowledge%20Base/KnowledgeBaseController_update), or delete a knowledge base with [`DELETE /knowledge-base/{id}`](https://api.vapi.ai/api#/Knowledge%20Base/KnowledgeBaseController_remove). Refer to the [Vapi API endpoints](https://api.vapi.ai/api#/) for more details.
+
+
+
+
+
+
+2. **Configure Custom Knowledge Bases for your Assistant**: Configure a custom knowledge base for your assistant in three steps by first uploading a file [through the dashboard](https://dashboard.vapi.ai/files) or [the API](https://api.vapi.ai/api#/Files/FileController_create), then [create a knowledge base](https://docs.vapi.ai/knowledgebase#step-2-create-a-knowledge-base), and lastly [updating your assistant](https://docs.vapi.ai/knowledgebase#step-3-create-an-assistant) with the knowledge base id. You can also assign a knowledge base to models like `GroqModel`, `VapiModel`, `GoogleModel`, and others using the new `knowledgeBaseId` property.
+
+
+3. **Integration with Trieve Knowledge Base**: Vapi now supports [Trieve](https://trieve.ai/) as our first knowledge base provider. Refer to [our docs](https://docs.vapi.ai/knowledgebase#step-2-create-a-knowledge-base) for an example of how to use Trieve.
+
+
+4. **Inflection AI Credential Management**: You can now manage Inflection AI credentials through the [updated providers credentials](https://dashboard.vapi.ai/keys) page. `Call.endedReason` also now enumerates new values like `'pipeline-error-inflection-ai-llm-failed'` to indicate specific Inflection AI errors.
+
+
+
+
+
+
+5. **New Transfer Mode with Summary in SIP Header**: You can now configure `TransferPlan.mode` to `'blind-transfer-add-summary-to-sip-header'` to forward calls and include a summary in the SIP header called `X-Transfer-Summary`. You can also add custom SIP headers during a transfer call using the `sipHeaders` property in `TransferDestinationSip`.
+
+
+6. **Azure Credential Service Default**: When creating or updating Azure credentials in the [updated providers credentials](https://dashboard.vapi.ai/keys), the `service` field now defaults to `'speech'`.
+
+
+7. **Support for Cantonese in Deepgram Transcriber**: The `DeepgramTranscriber.language` option now includes `'zh-HK'` for Cantonese (Hong Kong).
+
+ This is the content for the doc fern/changelog/2024-11-30.mdx
+
+ 1. **Extended Silence Timeout for Assistants**: You can now set `silenceTimeoutSeconds` up to 3600 seconds (previously 600 seconds) when creating or updating assistants and assistant overrides. This allows for longer periods of silence before an assistant session times out.
+
+2. **New Credits Purchase Option**: You can now purchase credits to your subscription by navigating to the [updated billing page](https://dashboard.vapi.ai/org/billing/credits). Specify the dollar amount of your credits in the `credits` field to complete the purchase.
+
+
+
+
+
+ This is the content for the doc fern/changelog/2024-12-03.mdx
+
+ 1. **New xAI and Inflection AI models**: You can now set `Assistant.model` to use `XAI` (e.g., model `grok-beta`) or `Inflection AI` (e.g., model `inflection_3_pi`) by specifying these providers in your assistant configuration. Specify these providers in `assistant.model`, `call.squad.members.assistant.model`, or `call.squad.members.assistantOverrides.model`.
+
+2. **Integrate Existing Trieve Vector Stores in Your Knowledge Base**: When you create a knowledge base with [`POST /knowledge-base`](https://api.vapi.ai/api#/Knowledge%20Base/KnowledgeBaseController_create), you can now specify `vectorStoreProviderId` to use an existing vector store from your Trieve account.
+
+3. **Create Vector Stores with Uploaded Files**: You can first upload files using the [`POST /files`](https://api.vapi.ai/api#/Files/FileController_create) endpoint, and then use the `fileIds` to specify the IDs of previously uploaded files to create a new Trieve vector store. You can customize how your files are ingested, chunked, then rebalanced to ensure correct knowledge is served by your assistant:
+
+- *Split delimiters*: Specify `splitDelimiters` to control how files are split before chunking (default is `[.!?\n]`).
+- *Splits per chunk*: Set `targetSplitsPerChunk` to specify the desired number of splits per chunk when creating a vector store (default is 20 splits per chunk).
+- *Chunk rebalancing*: Set `rebalanceChunks` to `true` to evenly distribute remainder splits across chunks when creating a vector store to ensure balanced chunk sizes; for example, 66 splits with `targetSplitsPerChunk` of 20 will result in 3 chunks with 22 splits each.
+
+4. **Customize Search Heuristics**: You can filter or remove search results from your knowledge base:
+
+- *Filter by Score threshold*: Set `scoreThreshold` to filter out chunks during searches based on their score. For cosine similarity, chunks below the threshold are filtered out; for other distance metrics, chunks above the threshold are filtered.
+- *Remove stop words*: Set `removeStopWords` to `true` to remove stop words during searches. The stop words list is specified in `server/src/stop-words.txt`, and queries that are entirely stop words will still be preserved.
+
+5. **Updated Analytics Endpoint**: The `/analytics` endpoint has changed—use `GET /analytics` to retrieve analytics data instead of `POST /analytics`.
+
+
+ This is the content for the doc fern/changelog/2024-12-05.mdx
+
+ 1. **OAuth2 Support for Custom LLM Credentials and Webhooks**: You can now authorize access to your [custom LLMs](https://docs.vapi.ai/customization/custom-llm/using-your-server#step-2-configuring-vapi-with-custom-llm) and [server urls (aka webhooks)](https://docs.vapi.ai/server-url) using OAuth2 (RFC 6749).
+
+For example, create a webhook credential with `CreateWebhookCredentialDTO` with the following payload:
+
+```json
+{
+ "provider": "webhook",
+ "authenticationPlan": {
+ "type": "oauth2",
+ "url": "https://your-url.com/your/path/token",
+ "clientId": "your-client-id",
+ "clientSecret": "your-client-secret"
+ },
+ "name": "your-credential-name-between-1-and-40-characters"
+}
+```
+
+This returns a [`WebhookCredential`](https://api.vapi.ai/api) object as follows:
+
+
+
+
+
+3. **Removal of Canonical Knowledge Base**: The ability to create, update, and use canoncial knowledge bases in your assistant has been removed from the API(as custom knowledge bases and the Trieve integration supports as superset of this functionality). Please update your implementations as endpoints and models referencing canoncial knowledge base schemas are no longer available.
+
+ This is the content for the doc fern/changelog/2024-12-06.mdx
+
+ 1. **OAuth 2 Authentication for Custom LLM Models and Webhooks**: In addition to (AuthZ)[https://www.okta.com/identity-101/authentication-vs-authorization/], you can now now authenticate users accessing your [custom LLMs](https://docs.vapi.ai/customization/custom-llm/using-your-server#step-2-configuring-vapi-with-custom-llm) and [server urls (aka webhooks)](https://docs.vapi.ai/server-url) using OAuth2 (RFC 6749). Use the `authenticationSession` dictionary which contains an `accessToken` and `expiresAt` datetime to authenticate further requests to your custom LLM or server URL.
+
+For example, create a webhook credential with `CreateCustomLLMCredentialDTO` with the following payload:
+```json
+{
+ "provider": "custom-llm",
+ "apiKey": "your-api-key-max-10000-characters",
+ "authenticationPlan": {
+ "type": "oauth2",
+ "url": "https://your-url.com/your/path/token",
+ "clientId": "your-client-id",
+ "clientSecret": "your-client-secret"
+ },
+ "name": "your-credential-name-between-1-and-40-characters"
+}
+```
+
+This returns a [`CustomLLMCredential`](https://api.vapi.ai/api) object as follows:
+
+
+
+
+
+This can be used to authenticate successive requests to your custom LLM or server URL.
+
+
+ This is the content for the doc fern/changelog/2024-12-09.mdx
+
+ 1. **Improved Tavus Video Processing Error Messages**: Your call `endedReason` now includes detailed error messages for `pipeline-error-tavus-video-failed`. Use this to detect and manage scenarios where the Tavus video processing pipeline fails during a call.
+
+ This is the content for the doc fern/changelog/2024-12-10.mdx
+
+ 1. **Claude Computer Use Tools Available**: You can now use [Claude computer use tools](https://www.anthropic.com/news/3-5-models-and-computer-use) like `BashTool`, `ComputerTool`, and `TextEditorTool` when building your Vapi assistant. Create these tools with `CreateBashToolDTO` (enables shell command execution), `CreateComputerToolDTO` (use desktop functionality with customizable display dimensions using `displayWidthPx`, `displayHeightPx`), and `CreateTextEditorToolDTO` (text editing operations), respectively.
+
+Refer to our [API docs](https://api.vapi.ai/api) to learn more about how to use Claude computer use tools.
+
+ This is the content for the doc fern/changelog/2024-12-11.mdx
+
+ 1. **Use OpenAI Chat Completions in your Assistant**: you can now more easily integrate your Assistant with OpenAI's [chat completions sessions](https://platform.openai.com/docs/api-reference/chat) by specifying `messages` (an array of `OpenAIMessage` objects) and an `assistantId` (a string). Each `OpenAIMessage` in turn consists of a `content` (a string between 1 and 100,000,000 characters) and a role (between *assistant*, *function*, *user*, *system*, *tool*). This makes it easier to manage chat sessions associated with a specific assistant. Refer to the `ChatDTO`, `OpenAIMessage` schemas in [our API docs](https://api.vapi.ai/api) to learn more.
+
+2. **Update Subscription Email on Billing Page**: you can now customize which email address appears on your Vapi invoices through the updated billing page > [under payment history](https://dashboard.vapi.ai/org/billing). You can specify an email address (in addition through physical address and tax id) - read more in [our docs](https://docs.vapi.ai/quickstart/billing#how-do-i-download-invoices-for-my-credit-purchases).
+
+ This is the content for the doc fern/changelog/2024-12-13.mdx
+
+ 1. **Azure Speech Transcriber Support**: You can now use Azure's speech-to-text service by specifying `AzureSpeechTranscriber` as an option for `transcriber`. This allows you to leverage Azure's speech to text capabilities when creating or updating your assistant.
+
+Refer to our [api docs](lhttps://api.vapi.ai/api) to learn more.
+
+ This is the content for the doc fern/changelog/2024-12-14.mdx
+
+ 1. **Removal of `'gemma-7b-it'` from `GroqModel` Options:** The `'gemma-7b-it'` model is no longer available when selecting Groq as a model provider. Update your applications to use other valid options provided by the API.
+
+Refer to the [`GroqModel` schema](https://api.vapi.ai/api) or the [vapi dashboard](https://dashboard.vapi.ai/assistants) for Groq for a list of supported models.
+
+ This is the content for the doc fern/changelog/2024-12-19.mdx
+
+ 1. **Azure Region Renamed to `swedencentral` (from *sweden*)**: Azure Speech Services customers using the Sweden data center should now specify `swedencentral` as your Azure Speech Services region instead of `sweden`. Update your region in your code and the updated [provider keys page](https://dashboard.vapi.ai/keys) > *Azure Speech*.
+
+ This is the content for the doc fern/changelog/2024-12-21.mdx
+
+ **Expanded Voice Compatibility with Realtime Models**: You can use the voices ash, ballad, coral, sage, and verse with any realtime models, giving you more flexibility in voice synthesis options.
+
+**Access to New OpenAI Models**:
+ You can now specify the new models `gpt-4o-realtime-preview-2024-12-17` and `gpt-4o-mini-realtime-preview-2024-12-17` when configuring `OpenAIModel.model` and `OpenAIModel.fallbackModels`.
+
+**New ElevenLabs Voice Models Available**:
+ The new voice models `eleven_flash_v2` and `eleven_flash_v2_5` are now available for use in `ElevenLabsVoice` and `FallbackElevenLabsVoice`, offering potential improvements in voice performance.
+
+ This is the content for the doc fern/changelog/2024-12-30.mdx
+
+ 1. **Addition of *AzureSpeechTranscriber*:**
+ You can now configure assistants to use Azure's speech transcription service by setting
+`AzureSpeechTranscriber.provider` to `azure`. Additionally, you will receive azure transcriber errors like `pipeline-error-azure-speech-transcriber-failed` in `Call.endReason`, `ServerMessageEndOfCallReport.endReason`, and `ServerMessageStatusUpdate.endReason`.
+
+2. **Combined `serverUrl` and `serverUrlSecret` into `server` Property**:
+ The `serverUrl` and `serverUrlSecret` properties have been replaced by a new `server` property in multiple schemas. This lets you configure webhook endpoints using the `server` object, allowing for more detailed and flexible setup, including URL and authentication, in a single place. These schemas include:
+- ByoPhoneNumber
+- BuyPhoneNumberDTO
+- CreateByoPhoneNumberDTO
+- CreateOrgDTO
+- CreateTwilioPhoneNumberDTO
+- CreateVapiPhoneNumberDTO
+- CreateVonagePhoneNumberDTO
+- ImportTwilioPhoneNumberDTO
+- ImportVonagePhoneNumberDTO
+- Org
+- OrgWithOrgUser
+- TwilioPhoneNumber
+- UpdateOrgDTO
+- UpdatePhoneNumberDTO
+- VapiPhoneNumber
+- VonagePhoneNumber
+
+3. **Introduction of New OpenAI Models**:
+You can now use `o1-preview`, `o1-preview-2024-09-12`, `o1-mini`, and `o1-mini-2024-09-12`. in `OpenAIModel.model`.
+
+4. **Introduction of *'sonic' Voice Models* in Voice Schemas:**
+ You can now use `sonic` and `sonic-preview` models in `CartesiaVoice.model` and `FallbackCartesiaVoice.model` configurations.
+
+5. **Removal of Deprecated *GroqModel* Models:**
+ The models `llama3-groq-8b-8192-tool-use-preview` and `llama3-groq-70b-8192-tool-use-preview` have been removed from `GroqModel.model`. You should switch to supported models to avoid any disruptions.
+
+
+ This is the content for the doc fern/changelog/2025-01-05.mdx
+
+ 1. **New Transfer Plan Mode Added**: You can now include call summaries in the SIP header during blind transfers without assistant involvement with `blind-transfer-add-summary-to-sip-header` (a new `TransferPlan.mode` option). Doing so will make `ServerMessageStatusUpdate` include a `summary` when the call status is `forwarding` - which means you can access call summaries for real-time display or logging purposes in your SIP calls.
+
+2. **Azure Speech Transcription Support**: You can now specify a new property called `AzureSpeechTranscriber.language` in Azure's Speech-to-Text service to improve the accuracy of processing spoken input.
+
+3. **New Groq Model Available**: You can now use `'llama-3.3-70b-versatile'` in `GroqModel.model`.
+
+
+
+
+
+
+ This is the content for the doc fern/changelog/2025-01-07.mdx
+
+ # New Gemini 2.0 Models, Realtime Updates, and Configuration Options
+
+1. **New Gemini 2.0 Models**: You can now use two new models in `Assistant.model[model='GoogleModel']`: `gemini-2.0-flash-exp` and `gemini-2.0-flash-realtime-exp`, which give you access to the latest real-time capabilities and experimental features.
+
+2. **Support for Real-time Configuration with Gemini 2.0 Models**: Developers can now fine-tune real-time settings for the Gemini 2.0 Multimodal Live API using `Assistant.model[model='GoogleModel'].realtimeConfig`, enabling more control over text generation and speech output.
+
+3. **Customize Speech Output for Gemini Multimodal Live APIs**: You can now customize the assistant's voice using the `speechConfig` and `voiceConfig` properties, with options like `"Puck"`, `"Charon"`, and more.
+
+4. **Advanced Gemini Text Generation Parameters**: You can also tune advanced hyperparameters such as `topK`, `topP`, `presencePenalty`, and `frequencyPenalty` to control how the assistant generates responses, leading to more natural and dynamic conversations.
+
+ This is the content for the doc fern/changelog/2025-01-11.mdx
+
+ 1. **Integration of Smallest AI Voices**: Assistants can now utilize voices from Smallest AI by setting the voice provider to `Assistant.voice[provider="smallest-ai"]`, allowing selection from a variety of 25 preset voices and customization of voice attributes.
+
+2. **Support for DeepSeek Language Models**: Developers can now configure assistants to use DeepSeek LLMs by setting the `Assistant.model[provider="deep-seek"]` and `Assistant.model[model="deepseek-chat"]`. You can also specify custom credentials by passing the following payload:
+
+```json
+{
+ "credentials": [
+ {
+ "provider": "deep-seek",
+ "apiKey": "YOUR_API_KEY",
+ "name": "YOUR_CREDENTIAL_NAME"
+ }
+ ],
+ "model": {
+ "provider": "deep-seek",
+ "model": "deepseek-chat"
+ }
+}
+```
+
+3. **Additional Call Ended Reasons for DeepSeek and Cerebras**: New `Call.endedReason` have been added to handle specific DeepSeek and Cerebras call termination scenarios, allowing developers to better manage error handling.
+
+4. **New API Endpoint to Delete Logs**: A new `DELETE /logs` endpoint has been added, enabling developers to programmatically delete logs and manage log data.
+
+5. **Enhanced Call Transfer Options with SIP Verb**: You can now specify a `sipVerb` when defining a `TransferPlan` with `Assistant.model.tools[type=transferCall].destinations[type=sip].transferPlan` giving you the ability to specify the SIP verb (`refer` or `bye`) used during call transfers for greater control over call flow.
+
+6. **Azure Credentials and Blob Storage Support**: You can now configure Azure credentials with support for AzureCredential.service[service=blob_storage] service and use AzureBlobStorageBucketPlan withAzureCredential.bucketPlan, enabling you to store call artifacts directly in Azure Blob Storage.
+
+7. **Add Authentication Support for Azure OpenAI API Management with the 'Ocp-Apim-Subscription-Key' Header**: When configuring Azure OpenAI credentials, you can now include the AzureOpenAICredential.ocpApimSubscriptionKey to authenticate with Azure's OpenAI services for the API Management proxy in place of an API Key.
+
+8. **New CloudflareR2BucketPlan**: You can now use CloudflareR2BucketPlan to configure storage with Cloudflare R2 buckets, enabling you to store call artifacts directly.
+
+9. **Enhanced Credential Support**: It is now simpler to configure provider credentials in `Assistant.credentials`. Additionally, credentials can be overridden with `AssistantOverride.credentials` enables granular credential management per assistant. Our backend improvements add type safety and autocompletion for all supported credential types in the SDKs, making it easier to configure and maintain credentials for the following providers:
+
+- S3Credential
+- GcpCredential
+- XAiCredential
+- GroqCredential
+- LmntCredential
+- MakeCredential
+- AzureCredential
+- TavusCredential
+- GladiaCredential
+- GoogleCredential
+- OpenAICredential
+- PlayHTCredential
+- RimeAICredential
+- RunpodCredential
+- TrieveCredential
+- TwilioCredential
+- VonageCredential
+- WebhookCredential
+- AnyscaleCredential
+- CartesiaCredential
+- DeepgramCredential
+- LangfuseCredential
+- CerebrasCredential
+- DeepSeekCredential
+- AnthropicCredential
+- CustomLLMCredential
+- DeepInfraCredential
+- SmallestAICredential
+- AssemblyAICredential
+- CloudflareCredential
+- ElevenLabsCredential
+- OpenRouterCredential
+- TogetherAICredential
+- AzureOpenAICredential
+- ByoSipTrunkCredential
+- GoHighLevelCredential
+- InflectionAICredential
+- PerplexityAICredential
+
+10. **Specify Type When Updating Tools, Blocks, Phone Numbers, and Knowledge Bases**: You should now specify the type in the request body when [updating tools](https://api.vapi.ai/api#/Tools/ToolController_update), [blocks](https://api.vapi.ai/api#/Blocks/BlockController_update), [phone numbers](https://api.vapi.ai/api#/Phone%20Numbers/PhoneNumberController_update), or [knowledge bases](https://api.vapi.ai/api#/Knowledge%20Base/KnowledgeBaseController_update) using the appropriate payload for each type. Specifying the type now provides type safety and autocompletion in the SDKs. Refer to [the schemas](https://api.vapi.ai/api) to see the expected payload for the following types:
+
+- UpdateBashToolDTO
+- UpdateComputerToolDTO
+- UpdateDtmfToolDTO
+- UpdateEndCallToolDTO
+- UpdateFunctionToolDTO
+- UpdateGhlToolDTO
+- UpdateMakeToolDTO
+- UpdateOutputToolDTO
+- UpdateTextEditorToolDTO
+- UpdateTransferCallToolDTO
+- BashToolWithToolCall
+- ComputerToolWithToolCall
+- TextEditorToolWithToolCall
+- UpdateToolCallBlockDTO
+- UpdateWorkflowBlockDTO
+- UpdateConversationBlockDTO
+- UpdateByoPhoneNumberDTO
+- UpdateTwilioPhoneNumberDTO
+- UpdateVonagePhoneNumberDTO
+- UpdateVapiPhoneNumberDTO
+- UpdateCustomKnowledgeBaseDTO
+- UpdateTrieveKnowledgeBaseDTO
+
+
+
+ This is the content for the doc fern/changelog/2025-01-14.mdx
+
+ **End Call Message Support in ClientInboundMessage**: Developers can now programmatically end a call by sending an `end-call` message type within `ClientInboundMessage`. To use this feature, include a message with the `type` property set to `"end-call"` when sending inbound messages to the client.
+
+ This is the content for the doc fern/changelog/2025-01-15.mdx
+
+ 1. **Updated Log Endpoints:**
+Both the `GET /logs` and `DELETE /logs` endpoints have been simplified by removing the `orgId` parameter.
+
+2. **Updated Log Schema:**
+The following fields in the Log schema are no longer required: `requestDurationSeconds`, `requestStartedAt`, `requestFinishedAt`, `requestBody`, `requestHttpMethod`, `requestUrl`, `requestPath`, and `responseHttpCode`.
+
+ This is the content for the doc fern/changelog/2025-01-20.mdx
+
+ # Workflow Steps, Trieve Knowledge Base Updates, and Concurrent Calls Tracking
+
+1. **Use Workflow Blocks to Simplify Blocks Steps:** You can now compose complicated Blocks steps with smaller, resuable [Workflow blocks](https://api.vapi.ai/api#:~:text=Workflow) that manage conversations and take actions in external systems.
+
+In addition to normal operations inside [Block steps](https://docs.vapi.ai/blocks/steps) - you can now [Say messages](https://api.vapi.ai/api#:~:text=Say), [Gather information](https://api.vapi.ai/api#:~:text=Gather), or connect to other workflow [Edges](https://api.vapi.ai/api#:~:text=Edge) based on a [LLM evaluating a condition](https://api.vapi.ai/api#:~:text=SemanticEdgeCondition), or a more [logic-based condition](https://api.vapi.ai/api#:~:text=ProgrammaticEdgeCondition). Workflows can be used through `Assistant.model["VapiModel"]` to create custom call workflows.
+
+2. **Trieve Knowledge Base Integration Improvements:** You should now configure [Trieve knowledge bases](https://api.vapi.ai/api#:~:text=TrieveKnowledgeBase) using the new `createPlan` and `searchPlan` fields instead of specifying the raw vector plans directly. The new plans allow you to create or import trieve plans directly, and specify the type of search more precisely than before.
+
+3. **Updated Concurrency Tracking:** Your subscriptions now track active calls with `concurrencyCounter`, replacing `concurrencyLimit`. This does not affect how you reserve concurrent calls through [billing add-ons](https://dashboard.vapi.ai/org/billing/add-ons).
+
+
+
+
+
+4. **Define Allowed Values with `type` using `JsonSchema`:** You can restrict model outputs to specific values inside Blocks or tool calls using the new `type` property in [JsonSchema](https://api.vapi.ai/api#:~:text=JsonSchema). Supported types include `string`, `number`, `integer`, `boolean`, `array` (which also needs `items` to be defined), and `object` (which also needs `properties` to be defined).
+
+
+
+ This is the content for the doc fern/changelog/2025-01-21.mdx
+
+ # Updated Azure Regions for Credentials
+
+1. **Updated Azure Regions for Credentials**: You can now specify `canadacentral`, `japaneast`, and `japanwest` as valid regions when specifying your Azure credentials. Additionally, the region `canada` has been renamed to `canadaeast`, and `japan` has been replaced with `japaneast` and `japanwest`; please update your configurations accordingly.
+
+
+
+
+
+
+ This is the content for the doc fern/changelog/2025-01-22.mdx
+
+ # Tool Calling Updates, Final Transcripts, and DeepSeek Reasoner
+1. **Migrate `ToolCallFunction` to `ToolCall`**: You should update your client and server tool calling code to use the [`ToolCall` schema](https://api.vapi.ai/api#:~:text=ToolCall) instead of `ToolCallFunction`, which includes properties like `name`, `tool`, and `toolBody` for more detailed tool call specifications. ToolCallFunction has been removed.
+
+2. **Include `ToolCall` Nodes in Workflows**: You can now incorporate [`ToolCall` nodes](https://api.vapi.ai/api#:~:text=ToolCall) directly into workflow block steps, enabling tools to be invoked as part of the workflow execution.
+
+3. **New Model Option `deepseek-reasoner`**: You can now select `deepseek-reasoner` as a model option inside your assistants with `Assistant.model["deep-seek"].model["deepseek-reasoner"]`, offering enhanced reasoning capabilities for your applications.
+
+4. **Support for Final Transcripts in Server Messages**: The API now supports `'transcript[transcriptType="final"]'` in server messages, allowing your application to handle and process end of conversation transcripts.
+
+ This is the content for the doc fern/changelog/2025-01-29.mdx
+
+ # New workflow nodes, improved call handling, better phone number management, and expanded tool calling capabilities
+
+1. **New Hangup Workflow Node**: You can now include a [`Hangup`](https://api.vapi.ai/api#:~:text=Hangup) node in your workflows to end calls programmatically.
+
+2. **New HttpRequest Workflow Node**: Workflows can now make HTTP requests using the new [`HttpRequest`](https://api.vapi.ai/api#:~:text=HttpRequest) node, enabling integration with external APIs during workflow execution.
+
+3. **Updates to Tool Calls**: The [`ToolCall`](https://api.vapi.ai/api#:~:text=ToolCall) schema has been revamped; you should update your tool calls to use the new `function` property with `id` and `function` details (instead of older `tool` and `toolBody` properties).
+
+4. **Improvements to [Say](https://api.vapi.ai/api#:~:text=Say), [Edge](https://api.vapi.ai/api#:~:text=Edge), [Gather](https://api.vapi.ai/api#:~:text=Gather), and [Workflow](https://api.vapi.ai/api#:~:text=Workflow) Nodes**:
+- The `name`, `to`, and `from` properties in these nodes now support up to 80 characters, letting you use more descriptive identifiers.
+- A `metadata` property has been added to these nodes, allowing you to store additional information.
+- The [`Gather`](https://api.vapi.ai/api#:~:text=Gather) node now supports a `confirmContent` option to confirm collected data with users.
+
+5. **Regex Validation with Json Outputs**: You can now validate inputs and outputs from your conversations, tool calls, and OpenAI structured outputs against regular expressions using the `regex` property in [`JSON outputs`](https://api.vapi.ai/api#:~:text=JsonSchema) node.
+
+6. **New Assistant Transfer Mode**: A new [transfer mode](https://api.vapi.ai/api#:~:text=TransferPlan) `swap-system-message-in-history-and-remove-transfer-tool-messages` allows more control over conversation history during assistant transfers.
+
+7. **Area Code Selection for Vapi Phone Numbers**: You can now specify a desired area code when creating Vapi phone numbers using `numberDesiredAreaCode`.
+
+8. **Chat Completions Support**: You can now handle chat messages and their metadata within your applications using familiar chat completion messages in your workflow nodes.
+
+
+ This is the content for the doc fern/changelog/2025-02-01.mdx
+
+ # API Request Node, Improved Retries, and Enhanced Message Controls
+
+1. **HttpRequest Node Renamed to ApiRequest**: The `HttpRequest` workflow node has been renamed to [`ApiRequest`](https://api.vapi.ai/api#:~:text=ApiRequest), and can be accessed through `Assistant.model.workflow.nodes[type="api-request"]`. Key changes:
+ - New support for POST requests with customizable headers and body
+ - New async request support with `isAsync` flag
+ - Task status messages for waiting, starting, failure and success states
+The `HttpRequest` node is now deprecated and will be removed in a future release. Please migrate to the new `ApiRequest` node.
+
+2. **New Backoff and Retry Controls**: You can now configure [`Assistant.model.tools[type=dtmf].server.backoffPlan`](https://api.vapi.ai/api#:~:text=BackoffPlan) to handle failed requests with customizable retry strategies and delays.
+ - Supports fixed or exponential backoff strategies
+ - Configure `maxRetries` (up to 10) and `baseDelaySeconds` (up to 10 seconds)
+ - Available in server configurations via `backoffPlan` property
+
+3. **Enhanced Gather Node**: The [`Assistant.model.workflow.nodes[type=gather]`](https://api.vapi.ai/api#:~:text=Gather) node has been improved with the following changes:
+ - Added `maxRetries` property to control retry attempts
+ - Now accepts a single JsonSchema instead of an array
+ - Removed default value for `confirmContent` property
+
+4. **Improved Message Controls**: [`Assistant.messagePlan`](https://api.vapi.ai/api#:~:text=MessagePlan) has been improved with the following changes:
+ - Increased `idleTimeoutSeconds` maximum from 30 to 60 seconds
+ - Added `silenceTimeoutMessage` to customize call ending due to silence
+
+5. **New Distilled Deepseek Model with Groq**: You can now select `deepseek-r1-distill-llama-70b` when using [Groq](https://api.vapi.ai/api#:~:text=Groq) as the provider in [`Assistant.model[provider='groq']`](https://api.vapi.ai/api#:~:text=UpdateCallDTO-,Assistant,-UpdateAssistantDTO)
+
+6. **Edge Condition Updates**: Edge conditions now require explicit matching criteria to improve workflow control and readability. Semantic edges must specify a `matches` property while programmatic edges require a `booleanExpression` property to define transition logic.
+
+
+ This is the content for the doc fern/changelog/2025-02-04.md
+
+ # Hooks, PCI Compliance, and Blocking Messages
+
+1. **Introduction of `Hook`s in Workflows**: You can now use [`Hooks`](https://api.vapi.ai/api#:~:text=Hook) in your workflows to automatically execute actions when specific events occur, like task start or confirmation. Hooks are now available in [`ApiRequest`](https://api.vapi.ai/api#:~:text=ApiRequest) and [`Gather`](https://api.vapi.ai/api#:~:text=Gather) workflow nodes.
+
+2. **Make your Assistant PCI Compliant**: You can now configure [`Assistant.pciEnabled`](https://api.vapi.ai/api#:~:text=UpdateCallDTO-,Assistant,-UpdateAssistantDTO) to indicate if your assistant deals with sensitive cardholder data that requires PCI compliance, helping you meet security standards for financial information.
+
+3. **Blocking Messages before Tool Calls**: You can now configure your tool calls to wait until a message is fully spoken before starting with [`ToolMessageStart.blocking=true`](https://api.vapi.ai/api#:~:text=ToolMessageStart) (default is `false`).
+
+
+
+ This is the content for the doc fern/changelog/2025-02-10.mdx
+
+ # API Enhancements, Call Features, and Workflow Improvements
+
+1. **`POST` requests to `/analytics` (migrate from `GET`)**: You should now make `POST` requests (instead of `GET`) to the [`/analytics`](https://api.vapi.ai/api#/Analytics/AnalyticsController_query) endpoint. Structure your analytics query as a JSON payload using [`AnalyticsQuery`](https://api.vapi.ai/api#/Analytics/AnalyticsQuery) in the request body.
+
+2. **Use `SayHook` to Intercept and Modify Text for Assistant Speech**: You can use [`SayHook`](https://api.vapi.ai/api#/Hooks/SayHook) to intercept and modify text before it's spoken by your assistant. Specify the text to be spoken using the `exact` or `prompt` properties.
+
+3. **Call Transfer Support**: The `Transfer` node type is now available in workflows. Configure the `destination` property to define the transfer target.
+
+4. **Workflow Edge Condition Updates**: [`AIEdgeCondition`](https://api.vapi.ai/api#:~:text=AIEdgeCondition) (which replaces `SemanticEdgeCondition`) enables AI-powered routing decisions by analyzing conversation context and intent, while [`LogicEdgeCondition`](https://api.vapi.ai/api#:~:text=LogicEdgeCondition) (which replaces `ProgrammaticEdgeCondition`) allows for rule-based routing using custom logical expressions. The previous `SemanticEdgeCondition` and `ProgrammaticEdgeCondition` are now deprecated, and a new `FailedEdgeCondition` has been added to handle node failures in workflows.
+
+5. **`Gather` Node: Data Collection Refactor**: The [`Gather` node](https://api.vapi.ai/api#:~:text=Gather) now requires an `output` property to define the expected data schema. The `instruction` and `schema` properties have been removed.
+
+6. **Call Packet Capture (PCAP) Configuration**: Your call [`Artifact`](https://api.vapi.ai/api#:~:text=Artifact)s now support links to download a call's network packet capture (PCAP) file, providing you with detailed network traffic analysis and troubleshooting for calls. PCAP is only supported by `vapi` and `byo-phone-number` providers. Enable PCAP through `pcapEnabled`, automatically upload to S3 bucket with `pcapS3PathPrefix`, and access via `pcapUrl`.
+
+7. **`ApiRequest` Node Improvements**: [`ApiRequest`](https://api.vapi.ai/api#:~:text=ApiRequest) now supports `GET` requests. You can also define the expected response schema. You can make API requests as `blocking` or run in the `background` with `ApiRequest.mode`.
+
+8. **`Call` and `ServerMessage` `endedReason` Updates**: The `assistant-not-invalid` `Call.endedReason` has been corrected to `"assistant-not-valid"`. Also added `"assistant-ended-call-with-hangup-task"` to the `Call.endedReason`.
+
+9. **New Azure OpenAI Model `gpt-4o-2024-08-06-ptu`**: You can now use `gpt-4o-2024-08-06-ptu` from Azure OpenAI inside your [Assistant](https://dashboard.vapi.ai/assistants/2ec63711-f867-4066-8c54-7833346783b1).
+
+
+
+
+
+
+10. **Deprecated Schemas and Properties**: The following properties and schemas are now deprecated in the [API reference](https://api.vapi.ai/api/):
+ * `SemanticEdgeCondition`
+ * `ProgrammaticEdgeCondition`
+ * `Workflow.type`
+ * `ApiRequest.waitTaskMessage`
+ * `ApiRequest.startTaskMessage`
+ * `ApiRequest.failureTaskMessage`
+ * `ApiRequest.successTaskMessage`
+ * `OpenAIModel.semanticCachingEnabled`
+ * `CreateWorkflowDTO.type`
+
+
+ This is the content for the doc fern/changelog/2025-02-17.mdx
+
+ ## What's New
+
+### Compliance & Security Enhancements
+- **New [CompliancePlan](https://api.vapi.ai/api#:~:text=CompliancePlan) Consolidates HIPAA and PCI Compliance Settings**: You should now enable HIPAA and PCI compliance settings with `Assistant.compliancePlan.hipaaEnabled` and `Assistant.compliancePlan.pciEnabled` which both default to `false` (replacing the old HIPAA and PCI flags on `Assistant` and `AssistantOverrides`).
+
+- **Phone Number Status Tracking**: You can now view your phone number `status` with `GET /phone-number/{id}` for all phone number types ([Bring Your Own Number](https://api.vapi.ai/api#:~:text=ByoPhoneNumber), [Vapi](https://api.vapi.ai/api#:~:text=VapiPhoneNumber), [Twilio](https://api.vapi.ai/api#:~:text=TwilioPhoneNumber), [Vonage](https://api.vapi.ai/api#:~:text=VonagePhoneNumber)) for better monitoring.
+
+### Advanced Call Control
+
+- **Assistant Hooks System**: You can now use [`AssistantHooks`](https://api.vapi.ai/api#:~:text=AssistantHooks) to support `call.ending` events with customizable filters and actions
+ - Enable transfer actions through [`TransferAssistantHookAction`](https://api.vapi.ai/api#:~:text=TransferAssistantHookAction). For example:
+```javascript
+{
+ "hooks": [{
+ "on": "call.ending",
+ "do": [{
+ "type": "transfer",
+ "destination": {
+ // Your transfer configuration
+ }
+ }]
+ }]
+}
+```
+
+ - Conditionally execute hooks with `Assistant.hooks.filter`. For example, trigger different hooks for call completed, system errors, or customer hangup / transfer:
+
+```json
+{
+ "assistant": {
+ "hooks": [{
+ "filters": [{
+ "type": "oneOf",
+ "key": "call.endedReason",
+ "oneOf": ["pipeline-error-custom-llm-500-server-error", "pipeline-error-custom-llm-llm-failed"]
+ }]
+ }
+ ]
+ }
+}
+```
+
+### Model & Voice Updates
+
+- **New Models Added**: You can now use new models inside `Assistant.model[provider="google", "openai", "xai"]` and `Assistant.fallbackModels[provider="google", "openai", "xai"]`
+ - Google: Gemini 2.0 series (`flash-thinking-exp`, `pro-exp-02-05`, `flash`, `flash-lite-preview`)
+ - OpenAI: o3 mini `o3-mini`
+ - xAI: Grok 2 `grok-2`
+
+
+
+
+
+- **New `PlayDialog` Model for [PlayHT Voices](https://api.vapi.ai/api#:~:text=PlayHTVoice)**: You can now use the `PlayDialog` model in `Assistant.voice[provider="playht"].model["PlayDialog"]`.
+
+- **New `nova-3` and `nova-3-general` Models for [Deepgram Transcriber](https://api.vapi.ai/api#:~:text=DeepgramTranscriber)**: You can now use the `nova-3` and `nova-3-general` models in `Assistant.transcriber[provider="deepgram"].model["nova-3", "nova-3-general"]`
+
+### API Improvements
+
+- **Workflow Updates**: You can now send a [`workflow.node.started`](https://api.vapi.ai/api#:~:text=ClientMessageWorkflowNodeStarted) message to track the start of a workflow node for better call flow tracking
+
+- **Analytics Enhancement**: Added subscription table and concurrency columns in [POST /analytics](https://api.vapi.ai/api#/Analytics/AnalyticsController_query) for richer queries about your subscriptions and concurrent calls.
+
+### Deprecations
+
+The `/logs` endpoints are now marked as deprecated - plan to update your implementation accordingly.
+
+
+ This is the content for the doc fern/changelog/2025-02-20.mdx
+
+ ## What's New
+1. **Configure 16 text normalization processors in [FormatPlan](https://api.vapi.ai/api#:~:text=FormatPlan)**: You can now control how text is transcribed and spoken for currency, dates, etc. by setting the `formattersEnabled` array in `Assistant.voice.chunkPlan.formatPlan` (not specifying `formattersEnabled` defaults to all formatters being enabled). See all available formatters in the [FormatPlan.formattersEnabled reference](https://api.vapi.ai/api#:~:text=FormatPlan).
+
+2. **Deepgram [Keyterm Prompting](https://developers.deepgram.com/docs/keyterm)**: The `keyterm` array in [DeepgramTranscriber](https://api.vapi.ai/api#:~:text=DeepgramTranscriber) implements Deepgram's [Keyterm Prompting](https://developers.deepgram.com/docs/keyterm) technology, boosting recall for domain-specific terminology. Compared to the existing `keywords` field:
+
+| Feature | `keywords` | `keyterm` |
+|------------------|--------------------|--------------------|
+| Recall Boost | 15-20% | Up to 90% |
+| Format | Word:Weight | Raw phrases |
+| Use Case | General vocabulary | Critical terms |
+
+You should reserve `keyterm` for compliance-sensitive terms like medical codes while using `keywords` for proper nouns / brand names.
+
+3. **Subscription usage tracking improvements**: The `minutesUsedNextResetAt` timestamp now appears in all subscription tiers (not just enterprise), exposed at `subscription.minutesUsedNextResetAt` for predictable billing cycle integration. Combine with existing `minutesUsed` and `minutesIncluded` metrics to build custom usage dashboards, regardless of subscription tier.
+
+4. **Neuphonic voice synthesis**: You can now configure Neuphonic as a voice provider with `Assistant.voice[provider="neuphonic"]`. Handle appropriate errors with `pipeline-error-neuphonic-voice-failed`. Test latency thresholds as Neuphonic requires 200ms additional processing time compared to ElevenLabs.
+
+
+
+
+
+5. **Support for pre-transfer announcements in [ClientInboundMessageTransfer](https://api.vapi.ai/api#:~:text=ClientInboundMessageTransfer)**: The `content` field in `ClientInboundMessageTransfer` now supports pre-transfer announcements ("Connecting you to billing...") before SIP/number routing. Implement via WebSocket messages using type: "transfer" with destination object.
+
+### Deprecation Notice
+**OrgWithOrgUser** is now deprecated, and impacts endpoints returning organization-user composites. This has been replaced with separate [`Org`](https://api.vapi.ai/api#:~:text=Org) and [`User`](https://api.vapi.ai/api#:~:text=User) schemas for better clarity and consistency.
+
+ This is the content for the doc fern/changelog/2025-02-25.mdx
+
+ ## Test Suite APIs, Enhanced Call Transfers, Voice Model Enhancements
+
+1. **Introducing Test Suite Management APIs:** You can now test your assistant conversations before deploying them by creating [end-to-end tests](https://docs.vapi.ai/test/voice-testing#step-1-create-a-new-test-suite), [adding test cases](https://docs.vapi.ai/test/voice-testing#step-3-add-test-cases), and [running and reviewing test suites](https://docs.vapi.ai/test/voice-testing#step-5-run-and-review-tests). You can configure these tests through the [Test Suites dashboard page](https://dashboard.vapi.ai/test-suites) and [Test Suite APIs](https://docs.vapi.ai/api-reference/test-suites/test-suite-controller-find-all-paginated), and learn more in the [docs](https://docs.vapi.ai/test/voice-testing).
+
+
+
+
+
+
+2. **Enhanced Call Transfers with TwiML Control:** You can now use `twiml` ([Twilio Markup Language](https://www.twilio.com/docs/voice/twiml)) in [`Assistant.model.tools[type=transferCall].destinations[].transferPlan[mode=warm-transfer-twiml]`](https://api.vapi.ai/api#:~:text=TransferPlan) to execute TwiML instructions before connecting the call, allowing for pre-transfer announcements or data collection with Twilio.
+
+3. **New Voice Models and Experimental Controls:**
+ * **`mistv2` Rime AI Voice:** You can now use the `mistv2` model in [`Assistant.voice[provider="rime-ai"].model[model="mistv2"]`](https://api.vapi.ai/api#:~:text=RimeAIVoice).
+ * **OpenAI Models:** You can now use `chatgpt-4o-latest` model in [`Assistant.model[provider="openai"].model[model="chatgpt-4o-latest"]`](https://api.vapi.ai/api#:~:text=OpenAIModel).
+
+4. **Experimental Controls for Cartesia Voices:** You can now specify your Cartesia voice speed (string) and emotional range (array) with [`Assistant.voice[provider="cartesia"].experimentalControls`](https://api.vapi.ai/api#:~:text=CartesiaExperimentalControls). For example:
+
+```json
+{
+ "speed": "fast",
+ "emotion": [
+ "anger:lowest",
+ "curiosity:high"
+ ]
+}
+```
+
+| Property | Option |
+|----------|--------|
+| speed | slowest |
+| | slow |
+| | normal (default) |
+| | fast |
+| | fastest |
+| emotion | 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 |
+
+
+ This is the content for the doc fern/changelog/2025-02-27.mdx
+
+ # Phone Keypad Input Support, OAuth2 and Analytics Improvements
+
+1. **Keypad Input Support for Phone Calls:** A new [`keypadInputPlan`](https://api.vapi.ai/api#:~:text=KeypadInputPlan) feature has been added to enable handling of DTMF (touch-tone) keypad inputs during phone calls. This allows your voice assistant to collect numeric input from callers, like account numbers, menu selections, or confirmation codes.
+
+Configuration options:
+```json
+{
+ "keypadInputPlan": {
+ "enabled": true, // Default: false
+ "delimiters": "#", // Options: "#", "*", or "" (empty string)
+ "timeoutSeconds": 2 // Range: 0.5-10 seconds, Default: 2
+ }
+}
+```
+
+The feature can be configured in:
+- `assistant.keypadInputPlan`
+- `call.squad.members.assistant.keypadInputPlan`
+- `call.squad.members.assistantOverrides.keypadInputPlan`
+
+2. **OAuth2 Authentication Enhancement:** The [`OAuth2AuthenticationPlan`](https://api.vapi.ai/api#:~:text=OAuth2AuthenticationPlan) now includes a `scope` property to specify access scopes when authenticating. This allows more granular control over permissions when integrating with OAuth2-based services.
+
+```json
+{
+ "credentials": [
+ {
+ "authenticationPlan": {
+ "type": "oauth2",
+ "url": "https://example.com/oauth2/token",
+ "clientId": "your-client-id",
+ "clientSecret": "your-client-secret",
+ "scope": "read:data" // New property, max length: 1000 characters
+ }
+ }
+ ]
+}
+```
+
+The scope property can be configured at:
+- `assistant.credentials.authenticationPlan`
+- `call.squad.members.assistant.credentials.authenticationPlan`
+
+3. **New Analytics Metric: Minutes Used** The [`AnalyticsOperation`](https://api.vapi.ai/api#:~:text=AnalyticsOperation) schema now includes a new column option: `minutesUsed`. This metric allows you to track and analyze the duration of calls in your usage reports and analytics dashboards.
+
+
+4. **Removed TrieveKnowledgeBaseCreate Schema:** Removed `TrieveKnowledgeBaseCreate` schema from
+- `TrieveKnowledgeBase.createPlan`
+- `CreateTrieveKnowledgeBaseDTO.createPlan`
+- `UpdateTrieveKnowledgeBaseDTO.createPlan`
+
+
+ This is the content for the doc fern/changelog/2025-03-02.mdx
+
+ ## Claude 3.7 Sonnet and GPT 4.5 preview, New Hume AI Voice Provider, New Supabase Storage Provider, Enhanced Call Transfer Options
+
+1. **Claude 3.7 Sonnet with Thinking Configuration Support**:
+You can now use the latest claude-3-7-sonnet-20250219 model with a new "thinking" feature via the [`AnthropicThinkingConfig`](https://api.vapi.ai/api#:~:text=AnthropicThinkingConfig) schema.
+Configure it in `assistant.model` or `call.squad.members.assistant.model`:
+```json
+{
+ "model": "claude-3-7-sonnet-20250219",
+ "provider": "anthropic",
+ "thinking": {
+ "type": "enabled",
+ "budgetTokens": 5000 // min 1024, max 100000
+ }
+}
+```
+
+2. **OpenAI GPT-4.5-Preview Support**:
+You can now use the latest gpt-4.5-preview model as a primary model or fallback option via the [`OpenAIModel`](https://api.vapi.ai/api#:~:text=OpenAIModel) schema.
+Configure it in `assistant.model` or `call.squad.members.assistant.model`:
+```json
+{
+ "model": "gpt-4.5-preview",
+ "provider": "openai"
+}
+```
+
+3. **New Hume Voice Provider**:
+Integrated Hume AI as a new voice provider with the "octave" model for text-to-speech synthesis.
+
+
+
+
+
+4. **Supabase Storage Integration**:
+New Supabase S3-compatible storage support for file operations. This integration lets developers configure buckets and paths across 16 regions, enabling structured file storage with proper authentication.
+Configure [`SupabaseBucketPlan`](https://api.vapi.ai/api#:~:text=SupabaseBucketPlan) in `assistant.credentials.bucketPlan`,`call.squad.members.assistant.credentials.bucketPlan`
+
+5. **Voice Speed Control**
+Added a speed parameter to ElevenLabs voices ranging from 0.7 (slower) to 1.2 (faster) [`ElevenLabsVoice`](https://api.vapi.ai/api#:~:text=ElevenLabsVoice). This enhancement gives developers more control over speech cadence for more natural-sounding conversations.
+
+6. **Enhanced Call Transfer Options in TransferPlan**
+Added a new dial option to the sipVerb parameter for call transfers. This complements the existing refer (default) and bye options, providing more flexibility in call handling.
+- 'dial': Uses SIP DIAL to transfer the call
+
+7. **Zero-Value Minumum Subscription Minutes**
+Changed the minimum value for minutesUsed and minutesIncluded from 1 to 0. This supports tracking of new subscriptions and free tiers with no included minutes.
+
+8. **Zero-Value Minimum KeypadInputPlan Timeout**
+Adjusted the KeypadInputPlan.timeoutSeconds minimum from 0.5 to 0.
+
+
+ This is the content for the doc fern/changelog/2025-03-06.mdx
+
+ ## New Query Tool and Vapi Voice Provider, Updates to Language Support and Error Handling
+
+1. **New Query Tool Feature and Knowledge Base Integration**
+
+* The API now supports a new query tool that allows assistants to search through knowledge bases. Add this tool to any assistant model by configuring it at `assistant.model.tools[type=query]` path.
+* You can now link knowledge bases to query tools, providing structured information sources for assistants to access. Define knowledge bases with a name, model, provider, description, and associated file IDs.
+
+
+```json
+{
+ "type": "query",
+ "async": false,
+ "server": {
+ "url": "https://api.example.com/query-handler"
+ },
+ "function": {
+ "name": "query_knowledge",
+ "description": "Query knowledge bases for information",
+ "parameters": {
+ "type": "object",
+ "properties": {
+ "query": {
+ "type": "string",
+ "description": "The query to search for"
+ }
+ },
+ "required": ["query"]
+ }
+ },
+ "knowledgeBases": [
+ {
+ "name": "Product Documentation",
+ "model": "gemini-1.5-flash",
+ "provider": "google",
+ "description": "Contains all product manuals",
+ "fileIds": ["file-123", "file-456"]
+ }
+ ]
+}
+```
+
+
+
+2. **New Voice Provider Support**
+
+A new voice provider "vapi" has been added with support for a voice called "Jordan" in [`FallbackVapiVoice`](https://api.vapi.ai/api#:~:text=FallbackVapiVoice). Configure it in our assistant fallback plans at `assistant.voice.fallbackPlan.voices`.
+
+
+
+
+
+3. **Language Support Updates**
+
+Myanmar language ("my") has been added to supported languages, while "jp" and "mymr" codes have been removed. Use "ja" for Japanese language and "my" for Myanmar. Reference [`GladiaTranscriber`](https://api.vapi.ai/api#:~:text=GladiaTranscriber) for more language codes.
+
+4. **Error Handling Improvements**
+
+Added new error code `pipeline-error-11labs-transcriber-failed` for `ServerMessageStatusUpdate.endedReason` and `ServerMessageEndOfCallReport.endedReason`. Also added an explicit `failed` status for test suite runs in [`TestSuiteRun`](https://api.vapi.ai/api#:~:text=TestSuiteRun). These additions provide more detailed error reporting.
+
+5. **Azure OpenAI Model Update**
+
+The model `gpt-4o-2024-08-06-ptu` has been removed from Azure OpenAI credential schemas. Update any credential configurations that were using this model.
+
+ This is the content for the doc fern/changelog/2025-03-09.mdx
+
+ ## Enhanced Voicemail Detection, File Processing, Knowledge Base Integration, and Invoicing Updates
+
+1. **Track Voicemail Detection Cost, Configure Google and Twilio Voicemail Detection Plans**
+
+* You can now configure provider-specific settings and track voicemail detection costs through the new `VoicemailDetectionCost` schema at `call.costs[type=voicemail-detection]`.
+* Configure Google or Twilio voicemail detection settings using the new [`GoogleVoicemailDetectionPlan`](https://api.vapi.ai/api#:~:text=GoogleVoicemailDetectionPlan) and [`TwilioVoicemailDetectionPlan`](https://api.vapi.ai/api#:~:text=TwilioVoicemailDetectionPlan) schemas.
+
+```json
+// Google configuration example
+{
+ "provider": "google",
+ "voicemailExpectedDurationSeconds": 15 // Range: 5-60 seconds
+}
+```
+
+```json
+// Twilio configuration example
+{
+ "provider": "twilio",
+ "enabled": true,
+ "machineDetectionTimeout": 30, // Range: 3-59 seconds
+ "voicemailDetectionTypes": ["machine_end_beep", "machine_end_silence"]
+}
+```
+
+2. **Improved File Processing Statuses and Parsed Text Content**
+
+* File processing statuses have been renamed to better reflect their purpose: `processing` → `done` → `failed`.
+* Two new properties have been added to the [`File`](https://api.vapi.ai/api#:~:text=File) schema: `parsedTextUrl` and `parsedTextBytes`, providing direct access to parsed text content from processed files.
+
+3. **Google Gemini Models for Knowledge Base Integration**
+
+* The [`KnowledgeBase`](https://api.vapi.ai/api#:~:text=KnowledgeBase) schema now fully supports Google's Gemini models with specific model options.
+* You can use Gemini models in your knowledge bases at `assistant.model.tools[type=query].knowledgeBases`.
+
+```json
+"model": {
+ "enum": [
+ "gemini-2.0-flash-thinking-exp",
+ "gemini-2.0-pro-exp-02-05",
+ "gemini-2.0-flash",
+ "gemini-2.0-flash-lite-preview-02-05",
+ "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"
+ ]
+}
+```
+
+4. **New Invoicing Features**
+
+* You can now use [`InvoicePlan`](https://api.vapi.ai/api#:~:text=InvoicePlan) schema for customizing invoice information with company details.
+* This can be accessed via the new `invoicePlan` property on the [`Subscription`](https://api.vapi.ai/api#:~:text=Subscription) schema.
+* Customize company name, email, tax ID, and address for your invoices.
+
+5. **Additional Voice Options**
+
+* Five new voice options have been added to the [`FallbackVapiVoice`](https://api.vapi.ai/api#:~:text=FallbackVapiVoice) schema: `Adi`, `Julia`, `Maibri (Web)`, `Maibri (Phone)`, and `Ashley`.
+* Configure these voices in your assistant fallback plans at `assistant.voice.fallbackPlan.voices`.
+
+
+
+
+ This is the content for the doc fern/changelog/2025-03-13.mdx
+
+ ## New Workflows API, Telnyx Phone Number Support, Voice Options, and much more
+
+1. **Workflows Replace Blocks**: The API has migrated from blocks to workflows with new `/workflow` endpoints. [Introduction to Workflows](https://docs.vapi.ai/workflows)
+You can now use [`UpdateWorkflowDTO`](https://api.vapi.ai/api#:~:text=UpdateWorkflowDTO) where conversation components (`Say`, `Gather`, `ApiRequest`, `Hangup`, `Transfer` nodes) are explicitly connected via edges to create directed conversation flows.
+
+
+ ```json
+ {
+ "name": "Customer Support Workflow",
+ "nodes": [
+ {
+ "id": "greeting",
+ "type": "Say",
+ "text": "Hello, welcome to customer support. Do you need help with billing or technical issues?"
+ },
+ {
+ "id": "menu",
+ "type": "Gather",
+ "options": ["billing", "technical", "other"]
+ },
+ {
+ "id": "billing",
+ "type": "Say",
+ "text": "I'll connect you with our billing department."
+ },
+ {
+ "id": "technical",
+ "type": "Say",
+ "text": "I'll connect you with our technical support team."
+ },
+ {
+ "id": "transfer_billing",
+ "type": "Transfer",
+ "destination": {
+ "type": "number",
+ "number": "+1234567890"
+ }
+ },
+ {
+ "id": "transfer_technical",
+ "type": "Transfer",
+ "destination": {
+ "type": "number",
+ "number": "+1987654321"
+ }
+ }
+ ],
+ "edges": [
+ {
+ "from": "greeting",
+ "to": "menu"
+ },
+ {
+ "from": "menu",
+ "to": "billing",
+ "condition": {
+ "type": "logic",
+ "liquid": "{% if input == 'billing' %} true {% endif %}"
+ }
+ },
+ {
+ "from": "menu",
+ "to": "technical",
+ "condition": {
+ "type": "logic",
+ "liquid": "{% if input == 'technical' %} true {% endif %}"
+ }
+ },
+ {
+ "from": "billing",
+ "to": "transfer_billing"
+ },
+ {
+ "from": "technical",
+ "to": "transfer_technical"
+ }
+ ]
+ }
+ ```
+
+
+2. **Telnyx Phone Number Support**: Telnyx is now available as a phone number provider alongside Twilio and Vonage.
+ - Use the [`TelnyxPhoneNumber`](https://api.vapi.ai/api#:~:text=TelnyxPhoneNumber), [`CreateTelnyxPhoneNumberDTO`](https://api.vapi.ai/api#:~:text=CreateTelnyxPhoneNumberDTO), and [`UpdateTelnyxPhoneNumberDTO`](https://api.vapi.ai/api#:~:text=UpdateTelnyxPhoneNumberDTO) schemas with [`/phone-number`](https://api.vapi.ai/api#/Phone%20Numbers) endpoints to create and update Telnyx phone numbers.
+ - The `Call.phoneCallProviderId` now includes Telnyx's `callControlId` alongside Twilio's `callSid` and Vonage's `conversationUuid`.
+
+3. **New Voice Options**:
+ - **Vapi Voices**: New Vapi voices - `Elliot`, `Rohan`, `Lily`, `Savannah`, and `Hana`
+ - **Hume Voice**: New provider with `octave` model and customizable voice settings
+ - **Neuphonic Voice**: New provider with `neu_hq` (higher quality) and `neu_fast` (faster) models
+
+4. **New Cerebras Model**: [`CerebrasModel`](https://api.vapi.ai/api#:~:text=CerebrasModel) Supports `llama3.1-8b` and `llama-3.3-70b` models
+
+5. **Enhanced Transcription**:
+ - **New Providers**: [ElevenLabs](https://api.vapi.ai/api#:~:text=ElevenLabsTranscriber) and [Speechmatics](https://api.vapi.ai/api#:~:text=SpeechmaticsTranscriber) transcribers now available.
+ - **DeepgramTranscriber Numerals**: New `numerals` option converts spoken numbers to digits (e.g., "nine-seven-two" → "972")
+
+6. **Improved Voicemail Detection**: You can now use multiple provider implementations for `assistant.voicemailDetection` (Google, OpenAI, Twilio). OpenAI implementation allows configuring detection duration (5-60 seconds, default: 15).
+
+7. **Smart Endpointing Upgrade**: Now supports LiveKit as an alternative to Vapi's custom-trained model in [`StartSpeakingPlan.smartEndpointingEnabled`](https://api.vapi.ai/api#:~:text=StartSpeakingPlan). LiveKit only supports English but may offer different endpointing characteristics.
+
+8. **Observability with Langfuse**: New `assistant.observabilityPlan` property allows integration with Langfuse for tracing and monitoring of assistant calls. Configure with [LangfuseObservabilityPlan](https://api.vapi.ai/api#:~:text=LangfuseObservabilityPlan).
+
+9. **More Credential Support**: Added support for Cerebras, Google, Hume, InflectionAI, Mistral, Trieve, and Neuphonic credentials in `assistant.credentials`
+
+ This is the content for the doc fern/changelog/2025-03-14.mdx
+
+ ## Blocks Schema Deprecations, Scheduling Enhancements, and New Voice Options for Vapi Voice
+
+
+2. **'scheduled' Status Added to Calls and Messages**: You can now set the status of a call or message to `scheduled`, allowing it to be executed at a future time. This enables scheduling functionality within your application for calls and messages.
+
+3. **New Voice Options for Text-to-Speech**: Four new voices—`Neha`, `Cole`, `Harry`, and `Paige`—have been added for text-to-speech services. You can enhance user experience by setting the `voiceId` to one of these options in your configurations.
+
+3. **Removal of Step and Block Schemas**:
+Blocks and Steps are now officially deprecated. Developers should update their applications to adapt to these changes, possibly by using new or alternative schemas provided.
+
+ This is the content for the doc fern/changelog/2025-03-15.mdx
+
+ # Enhancements in Assistant Responses, New Gemini Model, and Call Handling
+
+1. **Introduction of 'gemini-2.0-flash-lite' Model Option**: You can now use `gemini-2.0-flash-lite` in [`Assistant.model[provider="google"].model[model="gemini-2.0-flash-lite"]`](https://api.vapi.ai/api#:~:text=GoogleModel) for a reduced latency, lower cost Gemini model with a 1 million token context window.
+
+
+
+
+
+2. **New Assistant Paginated Response**: All [`Assistant`](https://api.vapi.ai/api#:~:text=Assistants) endpoints now return paginated responses. Each response specifies `itemsPerPage`, `totalItems`, and `currentPage`, which you can use to navigate through a list of assistants.
+
+ This is the content for the doc fern/changelog/2025-03-17.mdx
+
+ # New `timeoutSeconds` Property in Custom LLM Model
+
+1. **New `timeoutSeconds` Property in [`Custom LLM Model`](https://api.vapi.ai/api#:~:text=CustomLLMModel):** Developers can now specify a custom timeout duration (between 20 and 600 seconds) for connections to their [custom language model provider](https://api.vapi.ai/api#:~:text=CustomLLMModel) using the new `timeoutSeconds` property. This enhancement allows for better control over response waiting times, accommodating longer operations or varying network conditions.
+
+
+ This is the content for the doc fern/changelog/2025-03-19.mdx
+
+
+# Test Suite, Smart Endpointing, and Compliance Plans, Chat Completion Message Workflows, and Voicemail Detection
+
+1. **Test Suite Enhancements**: Developers can now define `targetPlan` and `testerPlan` when creating or updating [test suites](https://api.vapi.ai/api#:~:text=TestSuite), allowing for customized testing configurations without importing phone numbers to Vapi.
+
+2. **Smart Endpointing Updates**: You can now select between [`Vapi`](https://api.vapi.ai/api#:~:text=VapiSmartEndpointingPlan) and [`Livekit`](https://api.vapi.ai/api#:~:text=LivekitSmartEndpointingPlan) smart endpointing providers using the `Assistant.startSpeakingPlan.smartEndpointingPlan`; the `customEndpointingRules` property is deprecated and should no longer be used.
+
+3. **Compliance Plan Enhancements**: Organizations can now specify compliance settings using the new `compliancePlan` property, enabling features like PCI compliance at the org level.
+
+4. **Chat Completion Message Updates**: When working with OpenAI chat completions, you should now use [`ChatCompletionMessageWorkflows`](https://api.vapi.ai/api#:~:text=ChatCompletionMessageWorkflows) instead of the deprecated `ChatCompletionMessage`.
+
+5. **Voicemail Detection Defaults Updated**: The default `voicemailExpectedDurationSeconds` for voicemail detection plans has increased from 15 to 25 seconds, affecting how voicemail detection timings are handled.
+
+ This is the content for the doc fern/changelog/2025-03-20.mdx
+
+ # Introducing Google Calendar Integration, and Chat Test Suite / Rime AI Voice Enhancements
+
+1. **Integration with Google Calendar**: You can now create and manage Google Calendar events directly within your tools. Configure OAuth2 credentials through the [dashboard > Build > Provider Keys](https://dashboard.vapi.ai/keys#:~:text=Google%20Calendar) to authenticate and interact with Google Calendar APIs.
+
+
+
+
+
+2. **Enhanced Voice Customization for RimeAIVoice**: Gain more control over [Rime AI voice](https://api.vapi.ai/api#:~:text=RimeAIVoice) properties with new options like `reduceLatency`, `inlineSpeedAlpha`, `pauseBetweenBrackets`, and `phonemizeBetweenBrackets`. These settings let you optimize voice streaming and adjust speech delivery to better suit your assistant's needs.
+
+3. **Chat Test Suite Enhancements**: You can now create and run chat-based tests in your test suites using the new [`TestSuiteTestChat`](https://api.vapi.ai/api#:~:text=TestSuiteTestChat) to more comprehensively test conversational interactions in your assistant.
+
+4. **Maximum Length for Test Suite Chat Scripts**: When creating or updating chat tests, note that the `script` property now has a maximum length of 10,000 characters. Ensure your test scripts conform to this limit to avoid any validation errors.
+
+ This is the content for the doc fern/changelog/2025-03-21.mdx
+
+
+1. **OpenAI Voice Enhancements**: When using [OpenAI Voice models in `Assistant.voice`](https://api.vapi.ai/api#:~:text=OpenAIVoice), you can now use specific text to speech models and add custom instructions to control your assistant's voice output
+
+2. **Improved Call Error Reporting**: You can now use new [`Call.endedReason`](https://api.vapi.ai/api#:~:text=Call,-CallBatchError) codes when a call fails to start or ends unexpectedly due to failing to retrieve Vapi objects. Refer to [Call.endedReason](https://api.vapi.ai/api#:~:text=Call,-CallBatchError) for more details.
+
+ This is the content for the doc fern/changelog/2025-03-22.mdx
+
+
+1. **Customizable Background Sound**: You can now use a custom audio file as the background sound in calls by providing a URL in the `backgroundSound` property. This allows you to enhance the call experience with personalized ambient sounds or music.
+
+2. **New Recording Format Options in `ArtifactPlan`**: You can specify the recording format as either `'wav;l16'` or `'mp3'` in `Assistant.artifactPlan` or `Call.artifactPlan`. This gives you control over the audio format of call recordings to suit your storage and playback preferences.
+
+3. **Integrate with Langfuse for Enhanced Observability**: You can now integrate with Langfuse by setting `assistant.observabilityPlan` to `langfuse`. Add `tags` and `metadata` to your traces to improve monitoring, categorization, and debugging of your application's behavior.
+
+ This is the content for the doc fern/changelog/2025-03-23.mdx
+
+ 1. **Multi-Structured Data Extraction with `StructuredDataMultiPlan`:** You can now extract multiple sets of structured data from calls by configuring `assistant.analysisPlan.structuredDataMultiPlan`. This allows you to define various extraction plans, each producing structured outputs accessible via `call.analysis.structuredDataMulti`.
+
+2. **Customizable Voice Speed and Language Settings:** You can now adjust the speech speed and language for your assistant's voice by using the new `speed` and `language` properties in `Assistant.voice`. This enables you to fine-tune the voice output to better match your user's preferences and localize the experience.
+
+3. **Integration of OpenAI Transcriber:** The `transcriber` property in assistants now supports `OpenAITranscriber`, allowing you to utilize OpenAI's transcription services. A corresponding `Call.endedReason` value, `pipeline-error-openai-transcriber-failed`, has been added to help you identify when a call ends due to an OpenAI transcriber error.
+
+ This is the content for the doc fern/changelog/2025-03-27.mdx
+
+ 1. **Batch Call Operations**: You can now place multiple calls to different customers at once by providing a list of `customer`s as an array in [`POST /call`](https://api.vapi.ai/api#/Calls/CallController_create).
+
+2. **Google Sheets Row Append Tool Added**: You can now append rows to Google Sheets directly from your assistant using [`GoogleSheetsRowAppendTool`](https://api.vapi.ai/api#/Tools/GoogleSheetsRowAppendTool). This allows integration with Google Sheets via the API for automating data entry tasks.
+
+3. **Call Control and Scheduling**: You can now schedule calls using the new `SchedulePlan` feature, specifying earliest and latest times for calls to occur. This gives you more control over call timing and scheduling.
+
+4. **New Transcriber Options and Fallback Plans**: New transcribers like `GoogleTranscriber` and `OpenAITranscriber` have been added, along with the ability to set `fallbackPlan` for transcribers. This provides more choices and reliability for speech recognition in your applications.
+
+ This is the content for the doc fern/changelog/2025-03-28.mdx
+
+ 1. **New Slack and Google Calendar Tools Added**: You can now use the built-in [Slack tool](https://docs.vapi.ai/tools/slack) to send messages and use the [Google Calendar tool](https://docs.vapi.ai/tools/google-calendar) to check calendar availability directly from your assistant, with full CRUD operations available via the [`/tool` API endpoint](https://docs.vapi.ai/api-reference/tools/list). You can authenticate the [Slack tool](https://dashboard.vapi.ai/keys#:~:text=Slack) and the [Google Calendar tool](https://dashboard.vapi.ai/keys#:~:text=Google%20Calendar) using OAuth2 from the [Vapi provider keys page](https://dashboard.vapi.ai/keys).
+
+
+
+
+
+
+
+
+
+2. **Select LLM Model in Workflow Nodes**: You can now select and update which LLM model you want to use within workflow nodes, allowing more precise control over the assistant's behavior in different workflow nodes and easier configuration updates.
+
+4. **Enhanced Call Monitoring and Reporting**: We've improved call monitoring with conversation turn tracking, millisecond-precision timestamps, and provided more detailed call end reasons. These enhancements make it easier to track conversation flow, perform precise time calculations, and diagnose specific call termination issues like server overloads or database errors.
+
+5. **Enable Background Denoising**: You can now filter out background noise during calls by setting `Assistant.backgroundDenoisingEnabled` to `true`.
+
+ This is the content for the doc fern/changelog/2025-03-30.mdx
+
+ 1. **TestSuiteRunTestAttempt now accepts `callId` and `metadata`**: You can now include a `callId` and `metadata` when creating a test suite run attempt, allowing you to reference calls by ID and attach session-related information.
+
+2. **`call` property in [TestSuiteRunTestAttempt](https://api.vapi.ai/api#:~:text=TestSuiteRunTestAttemptMetadata) is no longer required**: It's now optional to include the full `call` object in a test attempt, providing flexibility for cases where call details are unnecessary or already known.
+
+3. **Attach Metadata to Test Suite Run Attempts**: You can now attach [metadata](https://api.vapi.ai/api#:~:text=TestSuiteRunTestAttemptMetadata) like `sessionId` to test attempts for better tracking and analysis.
+
+
+ This is the content for the doc fern/changelog/2025-04-03.mdx
+
+ 1. **Introducing `SmsSendTool` for SMS messaging support**: You can now create and manage tools of type `sms` using the new [SMS Send Tool](https://api.vapi.ai/api#:~:text=SmsSendTool), allowing you to send SMS messages via defined servers. The `sms` tool type is also now recognized in API endpoints, ensuring that SMS send tools are correctly processed during CRUD operations.
+
+2. **New configuration options for voice and transcriber settings**: The `autoMode` property has been added to [Eleven Labs Voice Settings](https://api.vapi.ai/api#:~:text=ElevenLabsVoice), letting developers control automatic voice settings. Additionally, `confidenceThreshold` has been introduced in transcriber settings, allowing developers to set thresholds to discard low-confidence transcriptions and improve accuracy.
+
+3. **Enhanced speed control in `CartesiaExperimentalControls`**: The `speed` property now accepts both predefined speeds (`'slowest'`, `'slow'`, `'normal'`, `'fast'`, `'fastest'`) and numeric values between -1 and 1. This gives you more precise control over speed settings for better customization.
+
+ This is the content for the doc fern/changelog/2025-04-04.mdx
+
+ 1. **Addition of `assistantId` to `TargetPlan` settings**: You can now specify an `assistantId` when testing [target plans](https://api.vapi.ai/api#:~:text=TargetPlan), allowing you to test scenarios involving specific assistants directly.
+
+ This is the content for the doc fern/changelog/2025-04-05.mdx
+
+ 1. **Introducing `SmsSendTool` for SMS messaging support**: You can now create and send `sms` text messages using the new `[Send Text`](https://api.vapi.ai/api#:~:text=SmsSendTool) tool, enabling assistants to send SMS messages via defined servers.
+
+
+
+
+
+2. **[Eleven Labs Voice](https://api.vapi.ai/api#:~:text=ElevenLabsVoice) Auto Mode and Confidence Threshold configuration options**: When using [`Eleven Labs Voice`](https://api.vapi.ai/api#:~:text=ElevenLabsVoice) in your Assistant, you can now configure `autoMode` (default: false) to automatically manage manage chunking strategies for long texts; Eleven Labs automatically determines the best way to process and generate audio, optimizing for latency and efficiency. Additionally, `confidenceThreshold` has been introduced in transcriber schemas, allowing developers to set thresholds to discard low-confidence transcriptions and improve accuracy.
+
+3. **Changes to `CartesiaExperimentalControls` Speed property**: The `speed` property now accepts both predefined speeds (`'slowest'`, `'slow'`, `'normal'`, `'fast'`, `'fastest'`) and numeric values between -1 and 1. This simplifies the process of controlling the speed of the generated audio with Cartesia.
+
+ This is the content for the doc fern/changelog/2025-04-08.mdx
+
+ 1. **Simplified `transport` property in `Call` configuration**: You should now configure the `transport` property in [`Call`](https://api.vapi.ai/api#:~:text=Call) as an object when creating or updating a [`Call`](https://api.vapi.ai/api#:~:text=Call), since the separate `Transport` schema has been deprecated. This simplification makes it easier to work with transport details without referencing a separate transport configuration.
+
+
+ The `Transport` schema is now deprecated and will be removed in a future release.
+
+
+2. **New call type `vapi.websocketCall`**: You can now make [phone calls over WebSockets](https://docs.vapi.ai/calls/websocket-transport) with Vapi. The `Call` schema now supports a new `type` value: `vapi.websocketCall`.
+
+ This is the content for the doc fern/changelog/2025-04-11.mdx
+
+ 1. **Updated AI Edge Condition with Prompt**: When defining an AI edge condition, the `matches` property has been renamed to `prompt`. The `prompt` allows you to provide a natural language condition (up to 1000 characters) that guides AI decision-making in workflows.
+
+
+
+
+
+2. **Assistant Overrides per Customer**: You can now customize assistant settings for individual customers using `assistantOverrides` when [creating customers](https://api.vapi.ai/api#:~:text=CreateCustomerDTO). This enables personalized assistant interactions for each customer in batch calls.
+
+3. **New Call Ended Reasons**: New error codes have been added to `endedReason` enums, providing more detailed insights into call terminations related to providers like Anthropic Bedrock and Vertex. This helps in better error handling and debugging of call issues.
+
+ This is the content for the doc fern/changelog/2025-04-12.mdx
+
+
+1. **Expanded Voice Selection for Assistant Voices**: You can now specify any valid `voiceId` for assistant voices without being limited to a predefined list. This provides greater flexibility to use different voices in `Assistant.voice`, and related configurations.
+
+ This is the content for the doc fern/changelog/2025-04-15.mdx
+
+ 1. **New GPT-4.1 Models Available**: You can now use `'gpt-4.1'`, `'gpt-4.1-mini'`, and `'gpt-4.1-nano'` as options for the `model` and `fallbackModels` with your [OpenAI models](https://api.vapi.ai/api#:~:text=OpenAIModel). These models may offer improved performance or features over previous versions.
+
+
+
+
+
+
+ This is the content for the doc fern/changelog/2025-04-16.mdx
+
+ 1. **Assistant Overrides in Testing (`TargetPlan.assistantOverrides`)**: You can now apply `assistantOverrides` when testing an assistant with a [Target Plan](https://api.vapi.ai/api#:~:text=TargetPlan), allowing modifications to the assistant's configuration specifically for tests without changing the original assistant. This helps in testing different configurations or behaviors of an assistant without affecting the live version.
+
+2. **Specify Voice Model with Deepgram**: You can now specify the `model` to be used by Deepgram voices by setting the `model` property to `"aura"` or `"aura-2"` (default: `"aura-2"`).
+
+3. **Expanded Deepgram Voice Options (`voiceId` in `DeepgramVoice` and `FallbackDeepgramVoice`)**: The list of available deepgram voice options has been greatly expanded, providing a wider selection of voices for assistants. This allows you to customize the assistant's voice to better match your desired persona with `Assistant.voice["DeepgramVoice"].voiceId`.
+
+
+
+
+
+
+4. **Control Text Replacement Behavior (`replaceAllEnabled` in `ExactReplacement`)**: A new property `replaceAllEnabled` allows you to decide whether to replace all instances of a specified text (`key`) or just the first occurrence in [`ExactReplacement`](https://api.vapi.ai/api#:~:text=ExactReplacement) configurations. Setting `replaceAllEnabled` to `true` ensures that all instances are replaced.
+
+ This is the content for the doc fern/changelog/2025-04-17.mdx
+
+ **1. **Custom Hooks When a Call is Ringing**: You can now define custom hooks on your phone numbers to automatically perform actions when a call is ringing. This enables you to play messages or transfer calls without additional server-side code by using the new `hooks` property in `Call.phoneNumber.hooks["phoneNumberHookCallRinging"]`.
+
+**2. **Say and Transfer Actions in Hooks**: The new [phone number hook call ringing](https://api.vapi.ai/api#:~:text=PhoneNumberHookCallRinging) allows you to specify actions that trigger when a call is ringing (`on: 'call.ringing'`). like [redirecting calls](https://api.vapi.ai/api#:~:text=TransferPhoneNumberHookAction) or [playing a message](https://api.vapi.ai/api#:~:text=SayPhoneNumberHookAction). Include these actions in the `do` array of your hook.
+
+**3. **Enhanced Call Tracking with endedReason**: When implementing call analytics, you can now track calls that ended due to hook actions through new `endedReason` values:
+- `'call.ringing.hook-executed-say'`: Call ended after playing a message via hook
+- `'call.ringing.hook-executed-transfer'`: Call ended after being transferred via hook
+These values let you distinguish between different automated call handling outcomes in your reporting.
+
+ This is the content for the doc fern/changelog/2025-04-18.mdx
+
+ 1. **Idle Message Count Reset in `Assistant.messagePlan`**: You can now enable `Assistant.messagePlan.idleMessageResetCountOnUserSpeechEnabled` (default: false) to allow the idle message count to reset whenever the user speaks. This means the assistant can repeatedly remind an idle user throughout the conversation.
+
+
+ This is the content for the doc fern/changelog/overview.mdx
+
+ ---
+slug: changelog
+---
+ document.querySelector('input[type="email"]').focus()}>Get the (almost) daily changelog}
+ icon="envelope"
+ iconType="solid"
+>
+
+
+
+ This is the content for the doc fern/community/appointment-scheduling.mdx
+
+ ---
+title: Appointment Scheduling
+subtitle: Videos showcasing Vapi out in the wild.
+slug: community/appointment-scheduling
+---
+
+
+Here are some videos made by people in our community showcasing what Vapi can do:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Send Us Your Video
+
+Have a video showcasing Vapi that you want us to feature? Let us know:
+
+
+
+ Send us your video showcasing what Vapi can do, we'd like to feature it.
+
+
+
+
+ This is the content for the doc fern/community/comparisons.mdx
+
+ ---
+title: Comparisons
+subtitle: Videos showcasing Vapi out in the wild.
+slug: community/comparisons
+---
+
+
+Here are some videos made by people in our community showcasing what Vapi can do:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Send Us Your Video
+
+Have a video showcasing Vapi that you want us to feature? Let us know:
+
+
+
+ Send us your video showcasing what Vapi can do, we'd like to feature it.
+
+
+
+
+ This is the content for the doc fern/community/conferences.mdx
+
+ ---
+title: Conferences
+subtitle: Videos showcasing Vapi out in the wild.
+slug: community/conferences
+---
+
+
+Here are some videos made by people in our community showcasing what Vapi can do:
+
+
+
+
+
+## Send Us Your Video
+
+Have a video showcasing Vapi that you want us to feature? Let us know:
+
+
+
+ Send us your video showcasing what Vapi can do, we'd like to feature it.
+
+
+
+
+ This is the content for the doc fern/community/demos.mdx
+
+ ---
+title: Demos
+subtitle: Videos showcasing Vapi out in the wild.
+slug: community/demos
+---
+
+
+Here are some videos made by people in our community showcasing what Vapi can do:
+
+
+
+
+
+
+
+
+## Send Us Your Video
+
+Have a video showcasing Vapi that you want us to feature? Let us know:
+
+
+
+ Send us your video showcasing what Vapi can do, we'd like to feature it.
+
+
+
+
+ This is the content for the doc fern/community/expert-directory.mdx
+
+ ---
+title: Expert Directory
+subtitle: Certified Voice AI Expert - Vapi
+slug: community/expert-directory
+---
+
+
+Want to maximize your Voice AI? Vapi, a certified consultant, specializes in building Voice AI bots.
+
+Whether you need help deciding what to automate or assistance in building it, Vapi Experts have proven their expertise by supporting users and creating valuable video content for the community. Find the right fit here.
+
+
+
+
+
+
Qonvo
+
Qonvo is the best way to stop wasting your time on the phone for repetitive tasks and low-value added inbound requests. Allow your self to better invest your time thanks custom-build Vocal AI agents.
+
+
+
+
+
+
+
6omb
+
Voice agents and custom product development.
+
+
+
+
+
+
+
Aitoflo
+
+ At Aitoflo, we specialize in Voice AI and RPA services, seamlessly flowing
+ to streamline business operations and enhance customer interactions with
+ Realistic Voice AI.
+
+
+
+
+
+
+
+
Amplify Voice
+
+ Our hyper-focus on User Experience will WOW your customers. Click to Book
+ a Strategy Session.
+
+
+
+
+
+
+
+
Arose AI
+
+ Arose AI creates custom Inbound Voice AI solutions for small businesses.
+ Our founder Tommy Chryst also provides 1-on-1 coaching.
+
+
+
+
+
+
+
+
AIP
+
+ Created debt collector, appointment book, customer service, website
+ assistant, etc. I, Valentino M., offer full integration and/or
+ consultation services.
+
+
+
+
+
+
+
+
Boldwave
+
+ We implement voice agents to streamline appointment booking, enhance lead
+ conversion, and provide superior 24/7 customer service.
+
+
+
+
+
+
+
+
Brisk Logic
+
+ We are a AI Automation Agency that specializes in designing advanced AI
+ voice assistants capable of automating various tasks through phone
+ calls.{" "}
+
+
+
+
+
+
+
+
Cold-Calls.AI
+
+ We specialize in helping companies within the German market integrate
+ Voice Agents for both inbound and outbound calls.
+
+
+
+
+
+
+
+
Don't Run Off AI
+
Telephone voice AI systems, prompt engineering, integrations
+
+
+
+
+
+
+
Flowzen
+
+ Our agency offers Voice AI solutions using Vapi, in English and Spanish,
+ integrated with platforms like GoHighLevel, Airtable, and Make.com.
+
+
+
+
+
+
+
+
Globe AI
+
+ I'm Aryan, founder of Globe AI. We build Inbound Voice Assistants for any
+ industry at any scale.
+
+
+
+
+
+
+
+
INFLATE AI Automation Development Services
+
Building voice systems for any industry from $3k USD minimum.
+
+
+
+
+
+
+
Integraticus
+
+ We build AI appointment setters for Real Estate Agencies to qualify more
+ leads, handle tailored outreach, and make sure you have higher margins
+ than ever before.
+
+
+
+
+
+
+
+
Klen AI
+
+ Custom AI voice assistants to handle calls, pre-qualify leads, schedule
+ appointments, etc. Utilizing Vapi for seamless integration and
+ productivity
+
+
+
+
+
+
+
+
Lunaris AI
+
We create Voice Agents for all types of businesses.
+
+
+
+
+
+
Martech Studios
+
+ We are a US based B2B tech and marketing consultancy focused on building superior user experiences. We also love all things Audio AI (TTS)
+
+
+
+
+
+
+
NukyLabs.AI
+
All Services for Vapi.ai Automation
+
+
+
+
+
+
+
Otaku Solutions
+
+ Handle the creation of voice assistants, automations, tracking, and
+ training.
+
+
+
+
+
+
+
+
Shadow AI
+
+ Specializing in AI-powered inbound and outbound calling operations for all
+ types of businesses using industry expertise.
+
+
+
+
+
+
+
+
Synthiq
+
+ Multilingual AI Voice Agents (20+ countries). Any industry. Use your
+ existing number. Expert AI consulting available.
+
+
+
+
+
+
+
+
Temporal Labs LLC
+
+ Temporal Labs LLC offers a unique solution through our parametrized,
+ development community, with industry specific solutions and engagement.
+
+
+
+
+
+
+
+
Value Added Tech
+
+ Top-notch automation company. We specialise in Make.com (Silver partner),
+ multiple CRMs and Vapi.
+
+
+
+
+
+
+
+
Saidwell
+
+ Saidwell develops custom voice AI solutions for enterprises, offering bespoke software and high-quality human voice models.
+
+
+
+
+
+
+
iffort.ai
+
+ We revolutionize your business communication with our conversational agents, turning traditional chats and calls into effortless conversations.
+
+
+
+
+
+
+
Msquare Automation
+
+ Experts in AI voice assistants and business automation. Affordable, quality service from India. Gold partners of Make.com
+
+
+
+
+
+
+ This is the content for the doc fern/community/ghl.mdx
+
+ ---
+title: GoHighLevel
+subtitle: Videos showcasing Vapi out in the wild.
+slug: community/ghl
+---
+
+
+Here are some videos made by people in our community showcasing what Vapi can do:
+
+
+
+
+
+
+
+## Send Us Your Video
+
+Have a video showcasing Vapi that you want us to feature? Let us know:
+
+
+
+ Send us your video showcasing what Vapi can do, we'd like to feature it.
+
+
+
+
+ This is the content for the doc fern/community/guide.mdx
+
+ ---
+title: Guide
+subtitle: Videos showcasing Vapi out in the wild.
+slug: community/guide
+---
+
+
+Here are some videos made by people in our community showcasing what Vapi can do:
+
+
+
+## Send Us Your Video
+
+Have a video showcasing Vapi that you want us to feature? Let us know:
+
+
+
+ Send us your video showcasing what Vapi can do, we'd like to feature it.
+
+
+
+
+ This is the content for the doc fern/community/inbound.mdx
+
+ ---
+title: Inbound
+subtitle: Videos showcasing Vapi out in the wild.
+slug: community/inbound
+---
+
+
+Here are some videos made by people in our community showcasing what Vapi can do:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Send Us Your Video
+
+Have a video showcasing Vapi that you want us to feature? Let us know:
+
+
+
+ Send us your video showcasing what Vapi can do, we'd like to feature it.
+
+
+
+
+ This is the content for the doc fern/community/knowledgebase.mdx
+
+ ---
+title: Creating Custom Knowledge Bases for Your Voice AI Assistants
+subtitle: >-
+ Learn how to create and integrate custom knowledge bases into your voice AI
+ assistants.
+slug: knowledgebase
+---
+
+## **What is Vapi's Knowledge Base?**
+
+A Knowledge Base is a collection of custom files that contain information on specific topics or domains. By integrating a Knowledge Base into your voice AI assistant, you can enable it to provide more accurate and informative responses to user queries. This is currently available in Vapi via the API, and will be on the dashboard soon.
+
+### **Why Use a Knowledge Base?**
+
+Using a Knowledge Base with your voice AI assistant offers several benefits:
+
+- **Improved accuracy**: By integrating custom files into your assistant, you can ensure that it provides accurate and up-to-date information to users.
+- **Enhanced capabilities**: A Knowledge Base enables your assistant to answer complex queries and provide detailed responses to user inquiries.
+- **Customization**: With a Knowledge Base, you can tailor your assistant's responses to specific domains or topics, making it more effective and informative.
+
+## **How to Create a Knowledge Base**
+
+To create a Knowledge Base, follow these steps:
+
+### **Step 1: Upload Your Files**
+
+Navigate to Platform > Files and upload your custom files in Markdown, PDF, plain text, or Microsoft Word (.doc and .docx) format to Vapi's Knowledge Base.
+
+
+
+
+
+Alternatively you can upload your files via the API.
+
+```bash
+curl --location 'https://api.vapi.ai/file' \
+--header 'Authorization: Bearer ' \
+--form 'file=@""'
+```
+
+### **Step 2: Create a Knowledge Base**
+
+Use the ID of the uploaded file to create a Knowledge Base along with the KB configurations.
+
+1. Provider: [trieve](https://trieve.ai)
+
+```bash
+curl --location 'http://localhost:3001/knowledge-base' \
+--header 'Content-Type: text/plain' \
+--header 'Authorization: Bearer ' \
+--data '{
+ "name": "v2",
+ "provider": "trieve",
+ "searchPlan": {
+ "searchType": "semantic",
+ "topK": 3,
+ "removeStopWords": true,
+ "scoreThreshold": 0.7
+ },
+ "createPlan": {
+ "type": "create",
+ "chunkPlans": [
+ {
+ "fileIds": ["", ""],
+ "websites": ["", ""],
+ "targetSplitsPerChunk": 50,
+ "splitDelimiters": [".!?\n"],
+ "rebalanceChunks": true
+ }
+ ]
+ }
+}'
+```
+
+#### Configuration Options
+
+##### Search Plan Options
+
+- **searchType** (required): The search method used for finding relevant chunks. Available options:
+ - `fulltext`: Traditional text search
+ - `semantic`: Semantic similarity search
+ - `hybrid`: Combines fulltext and semantic search
+ - `bm25`: BM25 ranking algorithm
+- **topK** (optional): Number of top chunks to return. Default varies by implementation
+- **removeStopWords** (optional): When true, removes common stop words from the search query. Default: `false`
+- **scoreThreshold** (optional): Filters out chunks based on their similarity score:
+ - For cosine distance: Excludes chunks below the threshold
+ - For Manhattan Distance, Euclidean Distance, and Dot Product: Excludes chunks above the threshold
+ - Set to 0 or omit for no threshold
+
+##### Chunk Plan Options
+
+- **fileIds** (optional): Array of file IDs to include in the vector store
+- **websites** (optional): Array of website URLs to crawl and include in the vector store
+- **targetSplitsPerChunk** (optional): Number of splits per chunk. Default: `20`
+- **splitDelimiters** (optional): Array of delimiters used to split text before chunking. Default: `[".!?\n"]`
+- **rebalanceChunks** (optional): When true, evenly distributes remainder splits across chunks. For example, 66 splits with `targetSplitsPerChunk: 20` will create 3 chunks with 22 splits each. Default: `true`
+
+### **Step 3: Create an Assistant**
+
+Create a new assistant in Vapi and, on the right sidebar menu. Add the Knowledge Base to your assistant via the PATCH endpoint. Also make sure you customize your assistant's system prompt to utilize the Knowledge Base for responding to user queries.
+
+```bash
+curl --location --request PATCH 'https://api.vapi.ai/assistant/' \
+--header 'Content-Type: text/plain' \
+--header 'Authorization: Bearer ' \
+--data '{
+ "model": {
+ "knowledgeBaseId": "",
+ "temperature": 0.2,
+ "provider": "openai",
+ "model": "gpt-4o",
+ "messages": [
+ {
+ "content": "You are a smart assistant who responds to user queries using the information you know, or information supplied by outside context.",
+ "role": "system"
+ }
+ ]
+ }
+}'
+```
+
+## **Best Practices for Creating Effective Knowledge Bases**
+
+- **Organize Your files**: Organize your files by topic or category to ensure that your assistant can quickly retrieve relevant information.
+- **Use Clear and concise language**: Use clear and concise language in your files to ensure that your assistant can accurately understand and respond to user queries.
+- **Keep your files up-to-date**: Regularly update your files to ensure that your assistant provides the most accurate and up-to-date information.
+
+
+ For more information on creating effective Knowledge Bases, check out our
+ tutorial on [Best Practices for Knowledge Base
+ Creation](https://youtu.be/i5mvqC5sZxU).
+
+
+By following these guidelines, you can create a comprehensive Knowledge Base that enhances the capabilities of your voice AI assistant and provides valuable information to users.
+
+
+ This is the content for the doc fern/community/myvapi.mdx
+
+ ---
+title: My Vapi
+slug: community/myvapi
+---
+
+
+Here is the updated MyVapi User Guide, including the customer endpoints and noting that MyVapi uses 27 out of the 33 available Vapi APIs:
+# MyVapi User Guide
+
+Welcome to MyVapi! This guide will help you get started with using MyVapi, your custom GPT, to enhance your productivity and streamline your tasks. Follow the steps below to make the most out of this powerful tool.
+
+## Table of Contents
+- [Introduction to MyVapi](#introduction-to-myvapi)
+- [Getting Started](#getting-started)
+- [Accessing MyVapi](#accessing-myvapi)
+- [Using MyVapi](#using-myvapi)
+ - [Basic Commands](#basic-commands)
+- [Tips and Best Practices](#tips-and-best-practices)
+- [Troubleshooting](#troubleshooting)
+- [FAQ](#faq)
+
+## Introduction to MyVapi
+
+### What is MyVapi?
+MyVapi is a custom GPT designed to allow users to manage their Vapi accounts with ease. While the Vapi Dashboard provides limited functionality and using PostMan can be cumbersome, MyVapi offers a streamlined solution to interact with the Vapi API directly. This eliminates the back-and-forth usually associated with manual API interactions and JSON validation, making the process more efficient and user-friendly. The reason MyVapi was created is to help users understand the power of using Vapi's API. MyVapi uses 27 out of the 33 available Vapi APIs.
+
+### Key Features
+- **Full API Access:** Leverage the full power of the Vapi API without the limitations of the Dashboard.
+- **Efficient Workflow:** Avoid the tedious back-and-forth of using PostMan and JSON validators.
+- **Voice Assistant Creation:** Simplify the process of creating voice assistants with the Vapi API.
+- **Troubleshooting:** Get real-time help and troubleshooting advice from ChatGPT.
+
+### Benefits of Using MyVapi
+- **Streamlined Management:** Manage your Vapi account more effectively and efficiently.
+- **Increased Productivity:** Save time and reduce effort in creating and managing voice assistants.
+- **Enhanced Support:** Receive guidance and support directly from ChatGPT to resolve any issues you encounter.
+
+### Additional Information
+MyVapi is not connected to a user's account but will help with almost anything you need help with. This includes creating transient assistants, creating tools, getting information about a call, and more.
+
+## Getting Started
+
+### Accessing MyVapi
+MyVapi can be accessed in the following ways:
+- Visit [https://chatgpt.com/g/g-3luI9WIdj-myvapi](https://chatgpt.com/g/g-3luI9WIdj-myvapi)
+- Search for "MyVapi" in the GPT Store
+
+MyVapi is available to both free and paid ChatGPT accounts.
+
+## Using MyVapi
+
+### Basic Commands
+MyVapi provides a range of commands to interact with your Vapi account efficiently. Below are the basic commands and their functions:
+
+#### Assistant Management
+- **Get Assistants**
+ - **Method:** GET
+ - **Endpoint:** /assistant
+ - **Description:** Retrieve a list of all assistants.
+
+- **Create Assistant**
+ - **Method:** POST
+ - **Endpoint:** /assistant
+ - **Description:** Create a new assistant.
+
+- **Get Assistant by ID**
+ - **Method:** GET
+ - **Endpoint:** /assistant/{id}
+ - **Description:** Retrieve details of a specific assistant using its ID.
+
+- **Update Assistant by ID**
+ - **Method:** PATCH
+ - **Endpoint:** /assistant/{id}
+ - **Description:** Update details of a specific assistant using its ID.
+
+- **Delete Assistant by ID**
+ - **Method:** DELETE
+ - **Endpoint:** /assistant/{id}
+ - **Description:** Delete a specific assistant using its ID.
+
+#### Phone Call Management
+- **Get Phone Calls**
+ - **Method:** GET
+ - **Endpoint:** /call
+ - **Description:** Retrieve a list of all phone calls.
+
+- **Get Phone Call by ID**
+ - **Method:** GET
+ - **Endpoint:** /call/{id}
+ - **Description:** Retrieve details of a specific phone call using its ID.
+
+- **Create Phone Call**
+ - **Method:** POST
+ - **Endpoint:** /call/phone
+ - **Description:** Create a new phone call.
+
+- **Update Phone Call by ID**
+ - **Method:** PATCH
+ - **Endpoint:** /call/{id}
+ - **Description:** Update the details of a specific phone call by its ID.
+
+- **Delete Phone Call by ID**
+ - **Method:** DELETE
+ - **Endpoint:** /call/{id}
+ - **Description:** Delete a specific phone call by its ID.
+
+- **Get Call Logs**
+ - **Method:** GET
+ - **Endpoint:** /log
+ - **Description:** Retrieve call logs.
+
+#### Squad Management
+- **Get Squads**
+ - **Method:** GET
+ - **Endpoint:** /squad
+ - **Description:** Retrieve a list of all squads.
+
+- **Create Squad**
+ - **Method:** POST
+ - **Endpoint:** /squad
+ - **Description:** Create a new squad.
+
+- **Get Squad by ID**
+ - **Method:** GET
+ - **Endpoint:** /squad/{id}
+ - **Description:** Retrieve details of a specific squad using its ID.
+
+- **Update Squad by ID**
+ - **Method:** PATCH
+ - **Endpoint:** /squad/{id}
+ - **Description:** Update details of a specific squad using its ID.
+
+- **Delete Squad by ID**
+ - **Method:** DELETE
+ - **Endpoint:** /squad/{id}
+ - **Description:** Delete a specific squad using its ID.
+
+#### Metrics Management
+- **Get Metrics**
+ - **Method:** GET
+ - **Endpoint:** /metrics
+ - **Description:** Retrieve metrics data.
+
+#### Tool Management
+- **List Tools**
+ - **Method:** GET
+ - **Endpoint:** /tool
+ - **Description:** Retrieve a list of all tools.
+
+- **Create Tool**
+ - **Method:** POST
+ - **Endpoint:** /tool
+ - **Description:** Create a new tool.
+
+- **Get Tool by ID**
+ - **Method:** GET
+ - **Endpoint:** /tool/{id}
+ - **Description:** Retrieve details of a specific tool using its ID.
+
+- **Update Tool by ID**
+ - **Method:** PATCH
+ - **Endpoint:** /tool/{id}
+ - **Description:** Update details of a specific tool using its ID.
+
+- **Delete Tool by ID**
+ - **Method:** DELETE
+ - **Endpoint:** /tool/{id}
+ - **Description:** Delete a specific tool using its ID.
+
+#### Customer Management
+- **Get Customers**
+ - **Method:** GET
+ - **Endpoint:** /customer
+ - **Description:** Retrieve a list of all customers.
+
+- **Create Customer**
+ - **Method:** POST
+ - **Endpoint:** /customer
+ - **Description:** Create a new customer.
+
+- **Get Customer by ID**
+ - **Method:** GET
+ - **Endpoint:** /customer/{id}
+ - **Description:** Retrieve details of a specific customer using its ID.
+
+- **Update Customer by ID**
+ - **Method:** PATCH
+ - **Endpoint:** /customer/{id}
+ - **Description:** Update details of a specific customer using its ID.
+
+- **Delete Customer by ID**
+ - **Method:** DELETE
+ - **Endpoint:** /customer/{id}
+ - **Description:** Delete a specific customer using its ID.
+
+## Tips and Best Practices
+- **Be Specific:** The more specific your request, the better MyVapi can assist you.
+- **Explore Features:** Take time to explore all the features and find what works best for you.
+- **Regular Updates:** Keep your account information and settings up-to-date for the best experience.
+
+## Troubleshooting
+If you encounter any issues while using MyVapi, try the following steps:
+1. **Check Internet Connection:** Ensure you have a stable internet connection.
+2. **Clear Cache:** Sometimes clearing your browser cache can resolve issues.
+3. **Restart Browser:** Close and reopen your browser to refresh the session.
+
+## FAQ
+**Q:** Is MyVapi free to use?
+**A:** MyVapi is available to both free and paid ChatGPT accounts.
+
+**Q:** How secure is my data?
+**A:** We prioritize your data security and use advanced encryption methods to protect your information.
+
+
+ This is the content for the doc fern/community/outbound.mdx
+
+ ---
+title: Outbound
+subtitle: Videos showcasing Vapi out in the wild.
+slug: community/outbound
+---
+
+
+Here are some videos made by people in our community showcasing what Vapi can do:
+
+
+
+
+
+
+{" "}
+
+
+
+
+
+
+
+
+
+
+## Send Us Your Video
+
+Have a video showcasing Vapi that you want us to feature? Let us know:
+
+
+
+ Send us your video showcasing what Vapi can do, we'd like to feature it.
+
+
+
+
+ This is the content for the doc fern/community/podcast.mdx
+
+ ---
+title: Podcast
+subtitle: Videos showcasing Vapi out in the wild.
+slug: community/podcast
+---
+
+
+Here are some videos made by people in our community showcasing what Vapi can do:
+
+
+
+
+
+## Send Us Your Video
+
+Have a video showcasing Vapi that you want us to feature? Let us know:
+
+
+
+ Send us your video showcasing what Vapi can do, we'd like to feature it.
+
+
+
+
+ This is the content for the doc fern/community/snippets-sdks-tutorials.mdx
+
+ ---
+title: Snippets & SDKs Tutorials
+subtitle: Videos showcasing Vapi out in the wild.
+slug: community/snippets-sdks-tutorials
+---
+
+
+Here are some videos made by people in our community showcasing what Vapi can do:
+
+
+
+
+
+
+
+
+
+
+## Send Us Your Video
+
+Have a video showcasing Vapi that you want us to feature? Let us know:
+
+
+
+ Send us your video showcasing what Vapi can do, we'd like to feature it.
+
+
+
+
+ This is the content for the doc fern/community/special-mentions.mdx
+
+ ---
+title: Special Mentions
+subtitle: Videos showcasing Vapi out in the wild.
+slug: community/special-mentions
+---
+
+
+Here are some videos made by people in our community showcasing what Vapi can do:
+
+
+
+
+
+
+
+
+
+
+## Send Us Your Video
+
+Have a video showcasing Vapi that you want us to feature? Let us know:
+
+
+
+ Send us your video showcasing what Vapi can do, we'd like to feature it.
+
+
+
+
+ This is the content for the doc fern/community/squads.mdx
+
+ ---
+title: Squads
+slug: community/squads
+---
+
+
+Here are some videos made by people in our community showcasing what Vapi can do:
+
+
+
+
+
+
+
+
+
+
+## Send Us Your Video
+
+Have a video showcasing Vapi that you want us to feature? Let us know:
+
+
+
+ Send us your video showcasing what Vapi can do, we'd like to feature it.
+
+
+
+
+ This is the content for the doc fern/community/television.mdx
+
+ ---
+title: Television
+subtitle: Videos showcasing Vapi out in the wild.
+slug: community/television
+---
+
+
+Here are some videos made by people in our community showcasing what Vapi can do:
+
+
+
+
+
+## Send Us Your Video
+
+Have a video showcasing Vapi that you want us to feature? Let us know:
+
+
+
+ Send us your video showcasing what Vapi can do, we'd like to feature it.
+
+
+
+
+ This is the content for the doc fern/community/usecase.mdx
+
+ ---
+title: Usecase
+subtitle: Videos showcasing Vapi out in the wild.
+slug: community/usecase
+---
+
+
+Here are some videos made by people in our community showcasing what Vapi can do:
+
+
+
+
+
+
+
+
+
+
+## Send Us Your Video
+
+Have a video showcasing Vapi that you want us to feature? Let us know:
+
+
+
+ Send us your video showcasing what Vapi can do, we'd like to feature it.
+
+
+
+
+ This is the content for the doc fern/customization/custom-keywords.mdx
+
+ ---
+title: Custom Keywords
+subtitle: Enhanced transcription accuracy guide
+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.
+
+### Why Use Keyword Boosting?
+
+Keyword boosting is beneficial for:
+
+- Enhancing the recognition of specialized terms and proper nouns.
+- Improving transcription accuracy without the need for a custom-trained model.
+- Quickly updating the model's vocabulary with new or uncommon words.
+
+### 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.
+
+## Enabling Keyword Boosting in Vapi
+
+### API Call Integration
+
+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.
+
+### 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 ' \
+ --header 'Content-Type: application/json' \
+ --data '{
+ "name": "Emma",
+ "model": {
+ "model": "gpt-4o",
+ "provider": "openai"
+ },
+ "voice": {
+ "voiceId": "emma",
+ "provider": "azure"
+ },
+ "transcriber": {
+ "provider": "deepgram",
+ "model": "nova-2",
+ "language": "bg",
+ "smartFormat": true,
+ "keywords": [
+ "snuffleupagus:1"
+ ]
+ },
+ "firstMessage": "Hi, I am Emma, what is your name?",
+ "firstMessageMode": "assistant-speaks-first"
+ }' \
+ https://api.vapi.ai/assistant
+
+```
+
+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.
+- **firstMessage**: The initial message the assistant will speak.
+- **firstMessageMode**: Specifies that the assistant speaks first.
+
+### 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.
+
+- **Boosting Example:** `keywords=snuffleupagus:5`
+- **Suppressing Example:** `keywords=kansas:-10`
+
+### Best Practices for Keyword Boosting
+
+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.
+
+### Additional Resources
+
+For more detailed information on Deepgram's keyword boosting feature, refer to the Deepgram Keyword Boosting Documentation.
+
+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.
+
+ This is the content for the doc fern/customization/custom-llm/fine-tuned-openai-models.mdx
+
+ ---
+title: Fine-tuned OpenAI models
+subtitle: Use Another LLM or Your Own Server
+slug: customization/custom-llm/fine-tuned-openai-models
+---
+
+
+Vapi supports using any OpenAI-compatible endpoint as the LLM. This includes services like [OpenRouter](https://openrouter.ai/), [AnyScale](https://www.anyscale.com/), [Together AI](https://www.together.ai/), or your own server.
+
+
+ - For an open-source LLM, like Mixtral
+ - To update the context during the conversation
+ - To customize the messages before they're sent to an LLM
+
+
+## Using an LLM provider
+
+You'll first want to POST your API key via the `/credential` endpoint:
+
+```json
+{
+ "provider": "openrouter",
+ "apiKey": ""
+}
+```
+
+Then, you can create an assistant with the model provider:
+
+```json
+{
+ "name": "My Assistant",
+ "model": {
+ "provider": "openrouter",
+ "model": "cognitivecomputations/dolphin-mixtral-8x7b",
+ "messages": [
+ {
+ "role": "system",
+ "content": "You are an assistant."
+ }
+ ],
+ "temperature": 0.7
+ }
+}
+```
+## Using Fine-Tuned OpenAI Models
+
+To set up your OpenAI Fine-Tuned model, you need to follow these steps:
+
+1. Set the custom llm URL to `https://api.openai.com/v1`.
+2. Assign the custom llm key to the OpenAI key.
+3. Update the model to their model.
+4. Execute a PATCH request to the `/assistant` endpoint and ensure that `model.metadataSendMode` is set to off.
+
+## Using your server
+
+To set up your server to act as the LLM, you'll need to create an endpoint that is compatible with the [OpenAI Client](https://platform.openai.com/docs/api-reference/making-requests). For best results, your endpoint should also support streaming completions.
+
+If your server is making calls to an OpenAI compatble API, you can pipe the requests directly back in your response to Vapi.
+
+If you'd like your OpenAI-compatible endpoint to be authenticated, you can POST your server's API key and URL via the `/credential` endpoint:
+
+```json
+{
+ "provider": "custom-llm",
+ "apiKey": ""
+}
+```
+
+If your server isn't authenticated, you can skip this step.
+
+Then, you can create an assistant with the `custom-llm` model provider:
+
+```json
+{
+ "name": "My Assistant",
+ "model": {
+ "provider": "custom-llm",
+ "url": "",
+ "model": "my-cool-model",
+ "messages": [
+ {
+ "role": "system",
+ "content": "You are an assistant."
+ }
+ ],
+ "temperature": 0.7
+ }
+}
+```
+
+
+ This is the content for the doc fern/customization/custom-llm/tool-calling-integration.mdx
+
+ ---
+title: Custom LLM Tool Calling Integration
+slug: customization/tool-calling-integration
+---
+## What Is a Custom LLM and Why Use It?
+
+A **Custom LLM** is more than just a text generator—it’s a conversational assistant that can call external functions, trigger processes, and handle special logic, all while chatting with your users. Think of it as your smart helper that not only answers questions but also takes actions.
+
+**Why use a Custom LLM?**
+- **Enhanced Functionality:** It mixes natural language responses with actionable functions.
+- **Flexibility:** You can combine built-in functions, attach external tools via Vapi, or even add custom endpoints.
+- **Dynamic Interactions:** The assistant can return structured instructions—like transferring a call or running a custom process—when needed.
+- **Seamless Integration:** Vapi lets you plug these custom endpoints into your assistant quickly and easily.
+
+---
+
+## Setting Up Your Custom LLM for Response Generation
+
+Before adding tool calls, let’s start with the basics: setting up your Custom LLM to simply generate conversation responses. In this mode, your LLM receives conversation details, asks the model for a reply, and streams that text back.
+
+### How It Works
+- **Request Reception:** Your endpoint (e.g., `/chat/completions`) gets a payload with the model, messages, temperature, and (optionally) tools.
+- **Content Generation:** The code builds an OpenAI API request that includes the conversation context.
+- **Response Streaming:** The generated reply is sent back as Server-Sent Events (SSE).
+
+### Sample Code Snippet
+
+```typescript
+app.post("/chat/completions", async (req: Request, res: Response) => {
+ // Log the incoming request.
+ logEvent("Request received at /chat/completions", req.body);
+ const payload = req.body;
+
+ // Prepare the API request to OpenAI.
+ const requestArgs: any = {
+ model: payload.model,
+ messages: payload.messages,
+ temperature: payload.temperature ?? 1.0,
+ stream: true,
+ tools: payload.tools || [],
+ tool_choice: "auto",
+ };
+
+ // Optionally merge in native tool definitions.
+ const modelTools = payload.tools || [];
+ requestArgs.tools = [...modelTools, ...ourTools];
+
+ logEvent("Calling OpenAI API for content generation");
+ const openAIResponse = await openai.chat.completions.create(requestArgs);
+ logEvent("OpenAI API call successful. Streaming response.");
+
+ // Set up streaming headers.
+ res.setHeader("Content-Type", "text/event-stream");
+ res.setHeader("Cache-Control", "no-cache");
+ res.setHeader("Connection", "keep-alive");
+
+ // Stream the response chunks back.
+ for await (const chunk of openAIResponse as unknown as AsyncIterable) {
+ res.write(`data: ${JSON.stringify(chunk)}\n\n`);
+ }
+ res.write("data: [DONE]\n\n");
+ res.end();
+});
+```
+
+### Attaching Custom LLM Without Tools to an Existing Assistant in Vapi
+
+If you just want response generation (without tool calls), update your Vapi model with a PATCH request like this:
+
+```bash
+curl -X PATCH https://api.vapi.ai/assistant/insert-your-assistant-id-here \
+ -H "Authorization: Bearer insert-your-private-key-here" \
+ -H "Content-Type: application/json" \
+ -d '{
+ "model": {
+ "provider": "custom-llm",
+ "model": "gpt-4o",
+ "url": "https://custom-llm-url/chat/completions",
+ "messages": [
+ {
+ "role": "system",
+ "content": "[TASK] Ask the user if they want to transfer the call; if not, continue the conversation."
+ }
+ ]
+ },
+ "transcriber": {
+ "provider": "azure",
+ "language": "en-CA"
+ }
+}'
+```
+
+---
+
+## Adding Tools Calling with Your Custom LLM
+
+Now that you’ve got response generation working, let’s expand your assistant’s abilities. Your Custom LLM can trigger external actions in three different ways.
+
+### a. Native LLM Tools
+
+These tools are built right into your LLM integration. For example, a native function like `get_payment_link` can return a payment URL.
+
+**How It Works:**
+1. **Detection:** The LLM’s streaming response includes a tool call for `get_payment_link`.
+2. **Execution:** The integration parses the arguments and calls the native function.
+3. **Response:** The result is packaged into a follow-up API call and streamed back.
+
+**Code Snippet:**
+
+```typescript
+// Variables to accumulate tool call information.
+let argumentsStr = "";
+let toolCallInfo: { name?: string; id?: string } | null = null;
+
+// Process streaming chunks.
+for await (const chunk of openAIResponse as unknown as AsyncIterable) {
+ const choice = chunk.choices && chunk.choices[0];
+ const delta = choice?.delta || {};
+ const toolCalls = delta.tool_calls;
+
+ if (toolCalls && toolCalls.length > 0) {
+ for (const toolCall of toolCalls) {
+ const func = toolCall.function;
+ if (func && func.name) {
+ toolCallInfo = { name: func.name, id: toolCall.id };
+ }
+ if (func && func.arguments) {
+ argumentsStr += func.arguments;
+ }
+ }
+ }
+
+ const finishReason = choice?.finish_reason;
+ if (finishReason === "tool_calls" && toolCallInfo) {
+ let parsedArgs = {};
+ try {
+ parsedArgs = JSON.parse(argumentsStr);
+ } catch (err) {
+ console.error("Failed to parse arguments:", err);
+ }
+ if (tool_functions[toolCallInfo.name!]) {
+ const result = await tool_functions[toolCallInfo.name!](parsedArgs);
+ const functionMessage = {
+ role: "function",
+ name: toolCallInfo.name,
+ content: JSON.stringify(result)
+ };
+
+ const followUpResponse = await openai.chat.completions.create({
+ model: requestArgs.model,
+ messages: [...requestArgs.messages, functionMessage],
+ temperature: requestArgs.temperature,
+ stream: true,
+ tools: requestArgs.tools,
+ tool_choice: "auto"
+ });
+
+ for await (const followUpChunk of followUpResponse) {
+ res.write(`data: ${JSON.stringify(followUpChunk)}\n\n`);
+ }
+ argumentsStr = "";
+ toolCallInfo = null;
+ continue;
+ }
+ }
+ res.write(`data: ${JSON.stringify(chunk)}\n\n`);
+}
+```
+
+### b. Vapi-Attached Tools
+
+These tools come pre-attached via your Vapi configuration. For example, the `transferCall` tool:
+
+**How It Works:**
+1. **Detection:** When a tool call for `transferCall` appears with a destination in the payload, the function isn’t executed.
+2. **Response:** The integration immediately sends a function call payload with the destination back to Vapi.
+
+**Code Snippet:**
+
+```typescript
+if (functionName === "transferCall" && payload.destination) {
+ const functionCallPayload = {
+ function_call: {
+ name: "transferCall",
+ arguments: {
+ destination: payload.destination,
+ },
+ },
+ };
+ logEvent("Special handling for transferCall", { functionCallPayload });
+ res.write(`data: ${JSON.stringify(functionCallPayload)}\n\n`);
+ // Skip further processing for this chunk.
+ continue;
+}
+```
+
+### c. Custom Tools
+
+Custom tools are unique to your application and are handled by a dedicated endpoint. For example, a custom function named `processOrder`.
+
+**How It Works:**
+1. **Dedicated Endpoint:** Requests for custom tools go to `/chat/completions/custom-tool`.
+2. **Detection:** The payload includes a tool call list. If the function name is `"processOrder"`, a hardcoded result is returned.
+3. **Response:** A JSON response is sent back with the result.
+
+**Code Snippet (Custom Endpoint):**
+
+```typescript
+app.post("/chat/completions/custom-tool", async (req: Request, res: Response) => {
+ logEvent("Received request at /chat/completions/custom-tool", req.body);
+ // Expect the payload to have a "message" with a "toolCallList" array.
+ const vapiPayload = req.body.message;
+
+ // Process tool call.
+ for (const toolCall of vapiPayload.toolCallList) {
+ if (toolCall.function?.name === "processOrder") {
+ const hardcodedResult = "CustomTool processOrder With CustomLLM Always Works";
+ logEvent("Returning hardcoded result for 'processOrder'", { toolCallId: toolCall.id });
+ return res.json({
+ results: [
+ {
+ toolCallId: toolCall.id,
+ result: hardcodedResult,
+ },
+ ],
+ });
+ }
+ }
+});
+```
+
+---
+
+## Testing Tool Calling with cURL
+
+Once your endpoints are set up, try testing them with these cURL commands.
+
+### a. Native Tool Calling (`get_payment_link`)
+
+```bash
+curl -X POST https://custom-llm-url/chat/completions \
+ -H "Content-Type: application/json" \
+ -d '{
+ "model": "gpt-3.5-turbo",
+ "messages": [
+ {"role": "user", "content": "I need a payment link."}
+ ],
+ "temperature": 0.7,
+ "tools": [
+ {
+ "type": "function",
+ "function": {
+ "name": "get_payment_link",
+ "description": "Get a payment link",
+ "parameters": {}
+ }
+ }
+ ]
+ }'
+```
+
+*Expected Response:*
+Streaming chunks eventually include the result (e.g., a payment link) returned by the native tool function.
+
+### b. Vapi-Attached Tool Calling (`transferCall`)
+
+```bash
+curl -X POST https://custom-llm-url/chat/completions \
+ -H "Content-Type: application/json" \
+ -d '{
+ "model": "gpt-3.5-turbo",
+ "messages": [
+ {"role": "user", "content": "Please transfer my call."}
+ ],
+ "temperature": 0.7,
+ "tools": [
+ {
+ "type": "function",
+ "function": {
+ "name": "transferCall",
+ "description": "Transfer call to a specified destination",
+ "parameters": {}
+ }
+ }
+ ],
+ "destination": "555-1234"
+ }'
+```
+
+*Expected Response:*
+Immediately returns a function call payload that instructs Vapi to transfer the call to the specified destination.
+
+### c. Custom Tool Calling (`processOrder`)
+
+```bash
+curl -X POST https://custom-llm-url/chat/completions/custom-tool \
+ -H "Content-Type: application/json" \
+ -d '{
+ "message": {
+ "toolCallList": [
+ {
+ "id": "12345",
+ "function": {
+ "name": "processOrder",
+ "arguments": {
+ "param": "value"
+ }
+ }
+ }
+ ]
+ }
+ }'
+```
+
+*Expected Response:*
+```json
+{
+ "results": [
+ {
+ "toolCallId": "12345",
+ "result": "CustomTools With CustomLLM Always Works"
+ }
+ ]
+}
+```
+
+---
+
+## Integrating Tools with Vapi
+
+After testing locally, integrate your Custom LLM with Vapi. Choose the configuration that fits your needs.
+
+### a. Without Tools (Response Generation Only)
+
+```bash
+curl -X PATCH https://api.vapi.ai/assistant/insert-your-assistant-id-here \
+ -H "Authorization: Bearer insert-your-private-key-here" \
+ -H "Content-Type: application/json" \
+ -d '{
+ "model": {
+ "provider": "custom-llm",
+ "model": "gpt-4o",
+ "url": "https://custom-llm-url/chat/completions",
+ "messages": [
+ {
+ "role": "system",
+ "content": "[TASK] Ask the user if they want to transfer the call; if not, continue chatting."
+ }
+ ]
+ },
+ "transcriber": {
+ "provider": "azure",
+ "language": "en-CA"
+ }
+}'
+```
+
+### b. With Tools (Including `transferCall` and `processOrder`)
+
+```bash
+curl -X PATCH https://api.vapi.ai/assistant/insert-your-assistant-id-here \
+ -H "Authorization: Bearer insert-your-private-key-here" \
+ -H "Content-Type: application/json" \
+ -d '{
+ "model": {
+ "provider": "custom-llm",
+ "model": "gpt-4o",
+ "url": "https://custom-llm-url/chat/completions",
+ "messages": [
+ {
+ "role": "system",
+ "content": "[TASK] Ask the user if they want to transfer the call; if they agree, trigger the transferCall tool; if not, continue the conversation. Also, if the user asks about the custom function processOrder, trigger that tool."
+ }
+ ],
+ "tools": [
+ {
+ "type": "transferCall",
+ "destinations": [
+ {
+ "type": "number",
+ "number": "+xxxxxx",
+ "numberE164CheckEnabled": false,
+ "message": "Transferring Call To Customer Service Department"
+ }
+ ]
+ },
+ {
+ "type": "function",
+ "async": false,
+ "function": {
+ "name": "processOrder",
+ "description": "it's a custom tool function named processOrder according to vapi.ai custom tools guide"
+ },
+ "server": {
+ "url": "https://custom-llm-url/chat/completions/custom-tool"
+ }
+ }
+ ]
+ },
+ "transcriber": {
+ "provider": "azure",
+ "language": "en-CA"
+ }
+}'
+```
+
+---
+
+## Conclusion
+
+A Custom LLM turns a basic conversational assistant into an interactive helper that can:
+- **Generate everyday language responses,**
+- **Call native tools** (like fetching a payment link),
+- **Use Vapi-attached tools** (like transferring a call), and
+- **Leverage custom tools** (like processing orders).
+
+By building each layer step by step and testing with cURL, you can fine-tune your integration before rolling it out in production.
+
+---
+
+## Complete Code
+
+For your convenience, you can find the complete source code for this Custom LLM integration here:
+
+**[Custom LLM with Vapi Integration – Complete Code](https://codesandbox.io/p/devbox/gfwztp)**
+```
+
+ This is the content for the doc fern/customization/custom-llm/using-your-server.mdx
+
+ ---
+title: 'Connecting Your Custom LLM to Vapi: A Comprehensive Guide'
+slug: customization/custom-llm/using-your-server
+---
+
+
+This guide provides a comprehensive walkthrough on integrating Vapi with OpenAI's gpt-3.5-turbo-instruct model using a custom LLM configuration. We'll leverage Ngrok to expose a local development environment for testing and demonstrate the communication flow between Vapi and your LLM.
+## Prerequisites
+
+- **Vapi Account**: Access to the Vapi Dashboard for configuration.
+- **OpenAI API Key**: With access to the gpt-3.5-turbo-instruct model.
+- **Python Environment**: Set up with the OpenAI library (`pip install openai`).
+- **Ngrok**: For exposing your local server to the internet.
+- **Code Reference**: Familiarize yourself with the `/openai-sse/chat/completions` endpoint function in the provided Github repository: [Server-Side Example Python Flask](https://github.com/VapiAI/server-side-example-python-flask/blob/main/app/api/custom_llm.py).
+
+## Step 1: Setting Up Your Local Development Environment
+
+**1. Create a Python Script (app.py):**
+
+```python
+from flask import Flask, request, jsonify
+import openai
+
+app = Flask(__name__)
+openai.api_key = "YOUR_OPENAI_API_KEY" # Replace with your actual API key
+
+@app.route("/chat/completions", methods=["POST"])
+def chat_completions():
+ data = request.get_json()
+ # Extract relevant information from data (e.g., prompt, conversation history)
+ # ...
+
+ response = openai.ChatCompletion.create(
+ model="gpt-3.5-turbo-instruct",
+ messages=[
+ {"role": "system", "content": "You are a helpful assistant."},
+ # ... (Add messages from conversation history and current prompt)
+ ]
+ )
+ # Format response according to Vapi's structure
+ # ...
+ return jsonify(formatted_response)
+
+if __name__ == "__main__":
+ app.run(debug=True, port=5000) # You can adjust the port if needed
+```
+**2. Run the Script:**
+Execute the Python script using python app.py in your terminal. This will start the Flask server on the specified port (5000 in this example).
+
+**3. Expose with Ngrok:**
+Open a new terminal window and run ngrok http 5000 (replace 5000 with your chosen port) to create a public URL that tunnels to your local server.
+
+## Step 2: Configuring Vapi with Custom LLM
+**1. Access Vapi Dashboard:**
+Log in to your Vapi account and navigate to the "Model" section.
+
+**2. Select Custom LLM:**
+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.
+
+**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.
+
+## Step 3: Understanding the Communication Flow
+**1. Vapi Sends POST Request:**
+When a user interacts with your Vapi application, Vapi sends a POST request containing conversation context and metadata to the configured endpoint (your ngrok URL).
+
+**2. Local Server Processes Request:**
+Your Python script receives the POST request and the chat_completions function is invoked.
+
+**3. Extract and Prepare Data:**
+The script parses the JSON data, extracts relevant information (prompt, conversation history), and builds the prompt for the OpenAI API call.
+
+**4. Call to OpenAI API:**
+The constructed prompt is sent to the gpt-3.5-turbo-instruct model using the openai.ChatCompletion.create method.
+
+**5. Receive and Format Response:**
+The response from OpenAI, containing the generated text, is received and formatted according to Vapi's expected structure.
+
+**6. Send Response to Vapi:**
+The formatted response is sent back to Vapi as a JSON object.
+
+**7. Vapi Displays Response:**
+Vapi receives the response and displays the generated text within the conversation interface to the user.
+
+By following these detailed steps and understanding the communication flow, you can successfully connect Vapi to OpenAI's gpt-3.5-turbo-instruct model and create powerful conversational experiences within your Vapi applications. The provided code example and reference serve as a starting point for you to build and customize your integration based on your specific needs.
+
+**Video Tutorial:**
+
+
+ This is the content for the doc fern/customization/custom-transcriber.mdx
+
+ ---
+title: Custom Transcriber
+slug: customization/custom-transcriber
+---
+## Introduction
+
+Vapi supports several transcription providers, but sometimes you may need to use your own transcription service. This guide shows you how to integrate Deepgram as your custom transcriber. The solution streams raw stereo PCM audio (16‑bit) from Vapi via WebSocket to your server, which then forwards the audio to Deepgram. Deepgram returns real‑time partial and final transcripts that are processed (including channel detection) and sent back to Vapi.
+
+## Why Use a Custom Transcriber?
+
+- **Flexibility:** Integrate with your preferred transcription service.
+- **Control:** Implement specialized processing that isn’t available with built‑in providers.
+- **Cost Efficiency:** Leverage your existing transcription infrastructure while maintaining full control over the pipeline.
+- **Customization:** Tailor the handling of audio data, transcript formatting, and buffering according to your specific needs.
+
+## How It Works
+
+1. **Connection Initialization:**
+ Vapi connects to your custom transcriber endpoint (e.g. `/api/custom-transcriber`) via WebSocket. It sends an initial JSON message like this:
+ ```json
+ {
+ "type": "start",
+ "encoding": "linear16",
+ "container": "raw",
+ "sampleRate": 16000,
+ "channels": 2
+ }
+ ```
+2. **Audio Streaming:**
+ Vapi then streams binary PCM audio to your server.
+
+3. **Transcription Processing:**
+ Your server forwards the audio to Deepgram(Chooseen Transcriber for Example) 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.
+
+4. **Response:**
+ The final transcript is sent back to Vapi as a JSON message:
+ ```json
+ {
+ "type": "transcriber-response",
+ "transcription": "The transcribed text",
+ "channel": "customer" // or "assistant"
+ }
+ ```
+
+## Implementation Steps
+
+### 1. Project Setup
+
+Create a new Node.js project and install the required dependencies:
+
+```bash
+mkdir vapi-custom-transcriber
+cd vapi-custom-transcriber
+npm init -y
+npm install ws express dotenv @deepgram/sdk
+```
+
+Create a `.env` file with the following content:
+
+```env
+DEEPGRAM_API_KEY=your_deepgram_api_key
+PORT=3001
+```
+
+### 2. Code Files
+
+Below are the individual code files you need for the integration.
+
+#### transcriptionService.js
+
+This service creates a live connection to Deepgram, processes incoming audio, handles transcript events (including channel detection), and emits the final transcript back to the caller.
+
+```js
+const { createClient, LiveTranscriptionEvents } = require("@deepgram/sdk");
+const EventEmitter = require("events");
+
+const PUNCTUATION_TERMINATORS = [".", "!", "?"];
+const MAX_RETRY_ATTEMPTS = 3;
+const DEBOUNCE_DELAY_IN_SECS = 3;
+const DEBOUNCE_DELAY = DEBOUNCE_DELAY_IN_SECS * 1000;
+const DEEPGRAM_API_KEY = process.env["DEEPGRAM_API_KEY"] || "";
+
+class TranscriptionService extends EventEmitter {
+ constructor(config, logger) {
+ super();
+ this.config = config;
+ this.logger = logger;
+ this.flowLogger = require("./fileLogger").createNamedLogger(
+ "transcriber-flow.log"
+ );
+ if (!DEEPGRAM_API_KEY) {
+ throw new Error("Missing Deepgram API Key");
+ }
+ this.deepgramClient = createClient(DEEPGRAM_API_KEY);
+ this.logger.logDetailed(
+ "INFO",
+ "Initializing Deepgram live connection",
+ "TranscriptionService",
+ {
+ model: "nova-2",
+ sample_rate: 16000,
+ channels: 2,
+ }
+ );
+ this.deepgramLive = this.deepgramClient.listen.live({
+ encoding: "linear16",
+ channels: 2,
+ sample_rate: 16000,
+ model: "nova-2",
+ smart_format: true,
+ interim_results: true,
+ endpointing: 800,
+ language: "en",
+ multichannel: true,
+ });
+ this.finalResult = { customer: "", assistant: "" };
+ this.audioBuffer = [];
+ this.retryAttempts = 0;
+ this.lastTranscriptionTime = Date.now();
+ this.pcmBuffer = Buffer.alloc(0);
+
+ this.deepgramLive.addListener(LiveTranscriptionEvents.Open, () => {
+ this.logger.logDetailed(
+ "INFO",
+ "Deepgram connection opened",
+ "TranscriptionService"
+ );
+ this.deepgramLive.on(LiveTranscriptionEvents.Close, () => {
+ this.logger.logDetailed(
+ "INFO",
+ "Deepgram connection closed",
+ "TranscriptionService"
+ );
+ this.emitTranscription();
+ this.audioBuffer = [];
+ });
+ this.deepgramLive.on(LiveTranscriptionEvents.Metadata, (data) => {
+ this.logger.logDetailed(
+ "DEBUG",
+ "Deepgram metadata received",
+ "TranscriptionService",
+ data
+ );
+ });
+ this.deepgramLive.on(LiveTranscriptionEvents.Transcript, (event) => {
+ this.handleTranscript(event);
+ });
+ this.deepgramLive.on(LiveTranscriptionEvents.Error, (err) => {
+ this.logger.logDetailed(
+ "ERROR",
+ "Deepgram error received",
+ "TranscriptionService",
+ { error: err }
+ );
+ this.emit("transcriptionerror", err);
+ });
+ });
+ }
+
+ send(payload) {
+ if (payload instanceof Buffer) {
+ this.pcmBuffer =
+ this.pcmBuffer.length === 0
+ ? payload
+ : Buffer.concat([this.pcmBuffer, payload]);
+ } else {
+ this.logger.warn("TranscriptionService: Received non-Buffer data chunk.");
+ }
+ if (this.deepgramLive.getReadyState() === 1 && this.pcmBuffer.length > 0) {
+ this.sendBufferedData(this.pcmBuffer);
+ this.pcmBuffer = Buffer.alloc(0);
+ }
+ }
+
+ sendBufferedData(bufferedData) {
+ try {
+ this.logger.logDetailed(
+ "INFO",
+ "Sending buffered data to Deepgram",
+ "TranscriptionService",
+ { bytes: bufferedData.length }
+ );
+ this.deepgramLive.send(bufferedData);
+ this.audioBuffer = [];
+ this.retryAttempts = 0;
+ } catch (error) {
+ this.logger.logDetailed(
+ "ERROR",
+ "Error sending buffered data",
+ "TranscriptionService",
+ { error }
+ );
+ this.retryAttempts++;
+ if (this.retryAttempts <= MAX_RETRY_ATTEMPTS) {
+ setTimeout(() => {
+ this.sendBufferedData(bufferedData);
+ }, 1000);
+ } else {
+ this.logger.logDetailed(
+ "ERROR",
+ "Max retry attempts reached, discarding data",
+ "TranscriptionService"
+ );
+ this.audioBuffer = [];
+ this.retryAttempts = 0;
+ }
+ }
+ }
+
+ handleTranscript(transcription) {
+ if (!transcription.channel || !transcription.channel.alternatives?.[0]) {
+ this.logger.logDetailed(
+ "WARN",
+ "Invalid transcript format",
+ "TranscriptionService",
+ { transcription }
+ );
+ return;
+ }
+ const text = transcription.channel.alternatives[0].transcript.trim();
+ if (!text) return;
+ const currentTime = Date.now();
+ const channelIndex = transcription.channel_index
+ ? transcription.channel_index[0]
+ : 0;
+ const channel = channelIndex === 0 ? "customer" : "assistant";
+ this.logger.logDetailed(
+ "INFO",
+ "Received transcript",
+ "TranscriptionService",
+ { channel, text }
+ );
+ if (transcription.is_final || transcription.speech_final) {
+ this.finalResult[channel] += ` ${text}`;
+ this.emitTranscription();
+ } else {
+ this.finalResult[channel] += ` ${text}`;
+ if (currentTime - this.lastTranscriptionTime >= DEBOUNCE_DELAY) {
+ this.logger.logDetailed(
+ "INFO",
+ `Emitting transcript after ${DEBOUNCE_DELAY_IN_SECS}s inactivity`,
+ "TranscriptionService"
+ );
+ this.emitTranscription();
+ }
+ }
+ this.lastTranscriptionTime = currentTime;
+ }
+
+ emitTranscription() {
+ for (const chan of ["customer", "assistant"]) {
+ if (this.finalResult[chan].trim()) {
+ const transcript = this.finalResult[chan].trim();
+ this.logger.logDetailed(
+ "INFO",
+ "Emitting transcription",
+ "TranscriptionService",
+ { channel: chan, transcript }
+ );
+ this.emit("transcription", transcript, chan);
+ this.finalResult[chan] = "";
+ }
+ }
+ }
+}
+
+module.exports = TranscriptionService;
+```
+
+---
+
+#### server.js
+
+This file creates an Express server, attaches the custom transcriber WebSocket at `/api/custom-transcriber`, and starts the HTTP server.
+
+```js
+const express = require("express");
+const http = require("http");
+const TranscriptionService = require("./transcriptionService");
+const FileLogger = require("./fileLogger");
+require("dotenv").config();
+
+const app = express();
+app.use(express.json());
+app.use(express.urlencoded({ extended: true }));
+
+app.get("/", (req, res) => {
+ res.send("Custom Transcriber Service is running");
+});
+
+const server = http.createServer(app);
+
+const config = {
+ DEEPGRAM_API_KEY: process.env.DEEPGRAM_API_KEY,
+ PORT: process.env.PORT || 3001,
+};
+
+const logger = new FileLogger();
+const transcriptionService = new TranscriptionService(config, logger);
+
+transcriptionService.setupWebSocketServer = function (server) {
+ const WebSocketServer = require("ws").Server;
+ const wss = new WebSocketServer({ server, path: "/api/custom-transcriber" });
+ wss.on("connection", (ws) => {
+ logger.logDetailed(
+ "INFO",
+ "New WebSocket client connected on /api/custom-transcriber",
+ "Server"
+ );
+ ws.on("message", (data, isBinary) => {
+ if (!isBinary) {
+ try {
+ const msg = JSON.parse(data.toString());
+ if (msg.type === "start") {
+ logger.logDetailed(
+ "INFO",
+ "Received start message from client",
+ "Server",
+ { sampleRate: msg.sampleRate, channels: msg.channels }
+ );
+ }
+ } catch (err) {
+ logger.error("JSON parse error", err, "Server");
+ }
+ } else {
+ transcriptionService.send(data);
+ }
+ });
+ ws.on("close", () => {
+ logger.logDetailed("INFO", "WebSocket client disconnected", "Server");
+ if (
+ transcriptionService.deepgramLive &&
+ transcriptionService.deepgramLive.getReadyState() === 1
+ ) {
+ transcriptionService.deepgramLive.finish();
+ }
+ });
+ ws.on("error", (error) => {
+ logger.error("WebSocket error", error, "Server");
+ });
+ transcriptionService.on("transcription", (text, channel) => {
+ const response = {
+ type: "transcriber-response",
+ transcription: text,
+ channel,
+ };
+ ws.send(JSON.stringify(response));
+ logger.logDetailed("INFO", "Sent transcription to client", "Server", {
+ channel,
+ text,
+ });
+ });
+ transcriptionService.on("transcriptionerror", (err) => {
+ ws.send(
+ JSON.stringify({ type: "error", error: "Transcription service error" })
+ );
+ logger.error("Transcription service error", err, "Server");
+ });
+ });
+};
+
+transcriptionService.setupWebSocketServer(server);
+
+server.listen(config.PORT, () => {
+ console.log(`Server is running on http://localhost:${config.PORT}`);
+});
+```
+
+---
+
+## Testing Your Integration
+
+### Code Examples – How to Test
+
+1. **Deploy Your Server:**
+ Run your server with:
+
+ ```bash
+ node server.js
+ ```
+
+2. **Expose Your Server:**
+ If you want to test externally, use a tool like ngrok to expose your server via HTTPS/WSS.
+
+3. **Initiate a Call with Vapi:**
+ Use the following CURL command (update the placeholders with your actual values):
+ ```bash
+ curl -X POST https://api.vapi.ai/call \
+ -H "Authorization: Bearer YOUR_API_KEY" \
+ -H "Content-Type: application/json" \
+ -d '{
+ "phoneNumberId": "YOUR_PHONE_NUMBER_ID",
+ "customer": {
+ "number": "CUSTOMER_PHONE_NUMBER"
+ },
+ "assistant": {
+ "transcriber": {
+ "provider": "custom-transcriber",
+ "server": {
+ "url": "wss://your-server.ngrok.io/api/custom-transcriber"
+ },
+ "secret": "your_optional_secret_value"
+ },
+ "firstMessage": "Hello! I am using a custom transcriber with Deepgram."
+ },
+ "name": "CustomTranscriberTest"
+ }'
+ ```
+
+### Expected Behavior
+
+- Vapi connects via WebSocket to your custom transcriber at `/api/custom-transcriber`.
+- 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:
+ ```json
+ {
+ "type": "transcriber-response",
+ "transcription": "The transcribed text",
+ "channel": "customer" // or "assistant"
+ }
+ ```
+
+## Notes and Limitations
+
+- **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.
+
+- **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.
+
+---
+
+## Conclusion
+
+Using a custom transcriber with Vapi gives you the flexibility to integrate any transcription service into your call flows. This guide walked you through the setup, usage, and testing of a solution that streams real-time audio, processes transcripts with multi‑channel detection, and returns formatted responses back to Vapi. Follow the steps above and use the provided code examples to build your custom transcriber solution.
+
+
+ This is the content for the doc fern/customization/custom-voices/custom-voice.mdx
+
+ ---
+title: Introduction
+subtitle: Use Custom Voice with your favourite provider instead of the preset ones.
+slug: customization/custom-voices/custom-voice
+---
+
+
+Vapi lets you use various providers with some preset voice. At the same time you can also create your own custom voices in the supported providers and use them with Vapi.
+
+You can update the `voice` property in the assistant configuration when you are creating the assistant to use your custom voice.
+
+```json
+{
+ "voice": {
+ "provider": "deepgram",
+ "voiceId": "your-voice-id"
+ }
+}
+```
+
+
+ This is the content for the doc fern/customization/custom-voices/elevenlabs.mdx
+
+ ---
+title: Elevenlabs
+subtitle: 'Quickstart: Setup Elevenlabs Custom Voice'
+slug: customization/custom-voices/elevenlabs
+---
+
+
+This guide outlines the procedure for integrating your cloned voice with 11labs through the Vapi platform.
+
+An subscription is required for this process to work.
+
+To integrate your cloned voice with 11labs using the Vapi platform, follow these steps.
+
+1. **Obtain an 11labs API Subscription:** Visit the [11labs pricing page](https://elevenlabs.io/pricing) and subscribe to an API plan that suits your needs.
+2. **Retrieve Your API Key:** Go to the 'Profile + Keys' section on the 11labs website to get your API key.
+3. **Enter Your API Key in Vapi:** Navigate to the [Vapi Provider Key section](https://dashboard.vapi.ai/keys) and input your 11labs API key under the 11labs section.
+4. **Sync Your Cloned Voice:** From the [Voice Library](https://dashboard.vapi.ai/voice-library) in Vapi, select 11labs as your voice provider and click on "Sync with 11labs."
+5. **Search and Use Your Cloned Voice:** After syncing, you can search for your cloned voice within the voice library and directly use it with your assistant.
+
+By following these steps, you will successfully integrate your cloned voice from 11labs with Vapi.
+
+**Video Tutorial:**
+
+
+
+ This is the content for the doc fern/customization/custom-voices/playht.mdx
+
+ ---
+title: PlayHT
+subtitle: 'Quickstart: Setup PlayHT Custom Voice'
+slug: customization/custom-voices/playht
+---
+
+
+This guide outlines the procedure for integrating your cloned voice with Play.ht through the Vapi platform.
+
+An API subscription is required for this process to work.
+
+To integrate your cloned voice with [Play.ht](http://play.ht/) using the Vapi platform, follow these steps.
+
+1. **Obtain a Play.ht API Subscription:** Visit the [Play.ht pricing page](https://play.ht/studio/pricing) and subscribe to an API plan.
+2. **Retrieve Your User ID and Secret Key:** Go to the [API Access section](https://play.ht/studio/api-access) on Play.ht to get your User ID and Secret Key.
+3. **Enter Your API Keys in Vapi:** Navigate to the [Vapi Provider Key section](https://dashboard.vapi.ai/keys) and input your Play.ht API keys under the Play.ht section.
+4. **Sync Your Cloned Voice:** From the [Voice Library](https://dashboard.vapi.ai/voice-library) in Vapi, select Play.ht as your voice provider and click on "Sync with Play.ht."
+5. **Search and Use Your Cloned Voice:** After syncing, you can search for your cloned voice within the voice library and directly use it with your assistant.
+
+**Video Tutorial:**
+
+
+ This is the content for the doc fern/customization/custom-voices/tavus.mdx
+
+ ---
+title: Tavus
+subtitle: 'Quickstart: Setup Tavus Custom Replica'
+slug: customization/custom-voices/tavus
+---
+
+
+This guide outlines the procedure for integrating your custom replica with Tavus through the Vapi platform.
+
+An API subscription is required for this process to work. This process is only required if you would like to use your **custom Tavus replicas**. This process is not required to use stock replicas on the Vapi platform.
+
+To integrate your custom replica with [Tavus](https://platform.tavus.io/) using the Vapi platform, follow these steps.
+
+1. **Obtain a Tavus API Subscription:** Visit the [Tavus pricing page](https://platform.tavus.io/billing) and subscribe to an API plan.
+2. **Retrieve Your API Key:** Go to the [API Keys section](https://platform.tavus.io/api-keys) on Tavus to get your API key.
+3. **Enter Your API Key in Vapi:** Navigate to the [Vapi Provider Key section](https://dashboard.vapi.ai/keys) and input your Tavus API key under the Tavus section.
+4. **Enter Your Custom Replica ID:** After adding your API key, you can select Tavus as your assistant's voice provider and add your Custom Replica ID manually through the dashboard. Alternatively, you may use the API and specify the replica ID within the `voiceId` field.
+
+**Video Tutorial:**
+
+
+ This is the content for the doc fern/customization/jwt-authentication.mdx
+
+ ---
+title: JWT Authentication
+subtitle: Secure API authentication guide
+slug: customization/jwt-authentication
+---
+
+This documentation provides an overview of JWT (JSON Web Token) Authentication and demonstrates how to generate a JWT token and use it to authenticate API requests securely.
+
+## Prerequisites
+
+Before you proceed, ensure you have the following:
+
+- An environment that supports JWT generation and API calls (e.g., a programming language or framework)
+- An account with a service that requires JWT authentication
+- Environment variables set up for the necessary credentials (e.g., organization ID and private key, both can be found in your Vapi portal)
+
+## Generating a JWT Token
+
+The following steps outline how to generate a JWT token:
+
+1. **Define the Payload**: The payload contains the data you want to include in the token. In this case, it includes an `orgId`.
+2. **Get the Private Key**: The private key (provided by Vapi) is used to sign the token. Ensure it is securely stored, often in environment variables.
+3. **Set Token Options**: Define options for the token, such as the expiration time (`expiresIn`).
+4. **Generate the Token**: Use a JWT library or built-in functionality to generate the token with the payload, key, and options.
+
+### JWT Token Scopes
+
+The generated JWT token can have one of two scopes: `private` or `public`. The scope of the token will determine the actions that can be performed using the token.
+
+For example, it can be used to restrict which API endpoints the token can access.
+
+
+ As of writing, the only publicly scoped API endpoint is
+ https://api.vapi.ai//call/web, which is used for Web Call creation. All other
+ endpoints are privately scoped.
+
+
+### Example (generating a private JWT token)
+
+```js
+// Define the payload
+const payload = {
+ orgId: process.env.ORG_ID,
+ token: {
+ // This is the scope of the token
+ tag: "private",
+ },
+};
+
+// Get the private key from environment variables
+const key = process.env.PRIVATE_KEY;
+
+// Define token options
+const options = {
+ expiresIn: "1h",
+};
+
+// Generate the token using a JWT library or built-in functionality
+const token = generateJWT(payload, key, options);
+```
+
+### Example (generating a public JWT token)
+
+```js
+// Define the payload
+const payload = {
+ orgId: process.env.ORG_ID,
+ // This is the scope of the token
+ token: {
+ tag: "public",
+ restrictions: {
+ enabled: true,
+ allowedOrigins: ["https://example.vapi.ai"],
+ allowedAssistantIds: ["1cbf8c70-5fd7-4f61-a220-376ab35be1b0"],
+ allowTransientAssistant: false,
+ },
+ },
+};
+
+// Get the private key from environment variables
+const key = process.env.PRIVATE_KEY;
+
+// Define token options
+const options = {
+ expiresIn: "1h",
+};
+
+// Generate the token using a JWT library or built-in functionality
+const token = generateJWT(payload, key, options);
+```
+
+### Explanation
+
+- **Payload**: The payload includes the `orgId` representing the organization ID and the `token` object with the scope of the token.
+- **Key**: The private key is used to sign the token, ensuring its authenticity.
+- **Options**: The `expiresIn` option specifies that the token will expire in 1 hour.
+- **Token Generation**: The `generateJWT` function (a placeholder for the actual JWT generation method) creates the token using the provided payload, key, and options.
+
+## Usage (Making an Authenticated API Request)
+
+If you set the scope to `private`, you can use it to make authenticated API requests. The following steps outline how to make an authenticated request:
+
+1. **Define the API Endpoint**: Specify the URL of the API you want to call.
+2. **Set the Headers**: Include the `Content-Type` and `Authorization` headers in your request. The `Authorization` header should include the generated JWT token prefixed with `Bearer`.
+3. **Make the API Call**: Use an appropriate method to send the request and handle the response.
+
+### Example
+
+```js
+async function getAssistants() {
+ const response = await fetch("https://api.vapi.ai/assistant", {
+ method: "GET",
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: `Bearer ${token}`,
+ },
+ });
+
+ const data = await response.json();
+ console.log(data);
+}
+
+fetchData().catch(console.error);
+```
+
+### Explanation
+
+- **API Endpoint**: The URL of the API you want to call.
+- **Headers**: The `Content-Type` is set to `application/json`, and the `Authorization` header includes the generated JWT token.
+- **API Call**: The `fetchData` function makes an asynchronous GET request to the specified API endpoint and logs the response.
+
+### Usage (Web Client)
+
+If you set the scope to `public`, you can use it to make authenticated API requests using the Vapi Web Client.
+
+```
+import Vapi from '@vapi-ai/web';
+
+const vapi = new Vapi({
+ token: 'your-jwt-token',
+});
+
+vapi.start('your-assistant-id');
+```
+
+## Notes
+
+- With the generated token, you can authenticate API requests to any endpoint requiring authentication. The token will be valid for the duration specified in the options (1 hour in this case).
+- If you don't specify `token` in the JWT payload, the token will be public.
+
+## Conclusion
+
+This documentation covered the basics of generating a JWT token and demonstrated how to use the token to make authenticated API requests. Ensure that your environment variables (e.g., `ORG_ID` and `PRIVATE_KEY`) are correctly set up before running the code.
+
+
+ This is the content for the doc fern/customization/multilingual.mdx
+
+ ---
+title: Multilingual
+subtitle: Learn how to set up and test multilingual support in Vapi.
+slug: customization/multilingual
+---
+
+
+Vapi's multilingual support is primarily facilitated through transcribers, which are part of the speech-to-text process. The pipeline consists of three key elements: text-to-speech, speech-to-text, and the llm model, which acts as the brain of the operation. Each of these elements can be customized using different providers.
+
+## Transcribers (Speech-to-Text)
+
+Currently, Vapi supports two providers for speech-to-text transcriptions:
+
+- `Deepgram` (nova - family models)
+- `Talkscriber` (whisper model)
+
+Each provider supports different languages. For more detailed information, you can visit your dashboard and navigate to the transcribers tab on the assistant page. Here, you can see the languages supported by each provider and the available models. **Note that not all models support all languages**. For specific details, you can refer to the documentation for the corresponding providers.
+
+## Voice (Text-to-Speech)
+
+Once you have set your transcriber and corresponding language, you can choose a voice for text-to-speech in that language. For example, you can choose a voice with a Spanish accent if needed.
+
+Vapi currently supports the following providers for text-to-speech:
+
+- `PlayHT`
+- `11labs`
+- `Rime-ai`
+- `Deepgram`
+- `OpenAI`
+- `Azure`
+- `Lmnt`
+- `Neets`
+
+Each provider offers varying degrees of language support. Azure, for instance, supports the most languages, with approximately 400 prebuilt voices across 140 languages and variants. You can also create your own custom languages with other providers.
+
+## Multilingual Support
+
+For multilingual support, you can choose providers like Eleven Labs or Azure, which have models and voices designed for this purpose. This allows your voice assistant to understand and respond in multiple languages, enhancing the user experience for non-English speakers.
+
+To set up multilingual support, you no longer need to specify the desired language when configuring the voice assistant. This configuration in the voice section is deprecated.
+
+Instead, you directly choose a voice that supports the desired language from your voice provider. This can be done when you are setting up or modifying your voice assistant.
+
+Here is an example of how to set up a voice assistant that speaks Spanish:
+
+```json
+{
+ "voice": {
+ "provider": "azure",
+ "voiceId": "es-ES-ElviraNeural"
+ }
+}
+```
+
+In this example, the voice `es-ES-ElviraNeural` from the provider `azure` supports Spanish. You can replace `es-ES-ElviraNeural` with the ID of any other voice that supports your desired language.
+
+By leveraging Vapi's multilingual support, you can make your voice assistant more accessible and user-friendly, reaching a wider audience and providing a better user experience.
+
+
+ This is the content for the doc fern/customization/provider-keys.mdx
+
+ ---
+title: Provider Keys
+subtitle: Bring your own API keys to Vapi.
+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.
+
+## 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).
+
+## 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.
+
+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.
+
+## 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).
+
+## Cloud Providers
+
+Vapi stores recordings of conversations with assistants in the cloud. By default, Vapi stores these recordings in its
+own bucket in Cloudflare R2. You can configure Vapi to store recordings in your own bucket in AWS S3, GCP, or
+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)
+
+
+ This is the content for the doc fern/customization/speech-configuration.mdx
+
+ ---
+title: Speech Configuration
+subtitle: Timing control for assistant speech
+slug: customization/speech-configuration
+---
+
+
+The Speaking Plan and Stop Speaking Plan are essential configurations designed to optimize the timing of when the assistant begins and stops speaking during interactions with a customer. These plans ensure that the assistant does not interrupt the customer and also prevents awkward pauses that can occur if the assistant starts speaking too late. Adjusting these parameters helps tailor the assistant’s responsiveness to different conversational dynamics.
+
+**Note**: At the moment these configurations can currently only be made via API.
+
+## 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.
+
+- **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
+ - **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
+
+ 
+
+ **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."
+ - 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.
+
+
+## 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.
+
+
+- **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.
+
+Here's a code snippet for Stop Speaking Plan -
+
+```json
+ "stopSpeakingPlan": {
+ "numWords": 0,
+ "voiceSeconds": 0.2,
+ "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",
+```
+
+- **Conversation Flow**: Aim for a balance where the assistant is responsive but not intrusive. Test different settings to find the best fit for your needs.
+
+
+ This is the content for the doc fern/enterprise/onprem.mdx
+
+ ---
+title: On-Prem Deployments
+subtitle: Deploy Vapi in your private cloud.
+slug: enterprise/onprem
+---
+
+
+Vapi On-Prem allows you to deploy Vapi's best in class enterprise voice infrastructure AI directly in your own cloud. It can be deployed in a dockerized format on any cloud provider, in any geographic location, running on your GPUs.
+
+With On-Prem, your audio and text data stays in your cloud. Data never passes through Vapi's servers. If you're are handling sensitive data (e.g. health, financial, legal) and are under strict data requirements, you should consider deploying on-prem.
+
+Your device regularly sends performance and usage information to Vapi's cloud. This data helps adjust your device's GPU resources and is also used for billing. All network traffic from your device is tracked in an audit log, letting your engineering or security team see what the device is doing at all times.
+
+## Frequently Asked Questions
+
+#### Can the appliance adjust to my needs?
+
+Yes, the Vapi On-Prem appliance automatically adjusts its GPU resources to handle your workload as required by our service agreement. It can take a few minutes to adjust to changes in your workload. If you need quicker adjustments, you might want to ask for more GPUs by contacting support@vapi.ai.
+
+#### What if I can’t get enough GPUs from my cloud provider?
+
+If you're struggling to get more GPUs from your provider, contact support@vapi.ai for help.
+
+#### Can I access Vapi's AI models?
+
+No, our AI models are on secure machines in your Isolated VPC and you can’t log into these machines or check their files.
+
+#### How can I make sure my data stays within my cloud?
+
+Your device operates in VPCs that you control. You can check the network settings and firewall rules, and look at traffic logs to make sure everything is as it should be. The Control VPC uses open source components, allowing you to make sure the policies are being followed. Performance data and model updates are sent to Vapi, but all other traffic leaving your device is logged, except for the data sent back to your API clients.
+
+## Contact us
+
+For more information about Vapi On-Prem, please contact us at support@vapi.ai
+
+
+ This is the content for the doc fern/enterprise/plans.mdx
+
+ ---
+title: Vapi Enterprise
+subtitle: Build and scale with Vapi.
+slug: enterprise/plans
+---
+
+
+If you're building a production application on Vapi, we can help you every step of the way from idea to full-scale deployment.
+
+#### Enterprise Plans include:
+
+- Unlimited concurrency and higher rate limits
+- Reserved capacity on our dedicated Enterprise Cluster
+- Hands-on 24/7 support with dedicated solutions engineer
+- Shared Slack channel with our team
+- Regular check-in calls with our team
+
+## Contact us
+
+To get started on Vapi Enterprise, [fill out this form](https://book.vapi.ai).
+
+
+ This is the content for the doc fern/examples/inbound-support.mdx
+
+ ---
+title: Inbound Support Example ⚙️
+subtitle: Let's build a technical support assistant that remembers where we left off.
+slug: examples/inbound-support
+---
+
+
+We want a phone number we can call to get technical support. We want the assistant to use a provided set of troubleshooting guides to help walk the caller through solving their issue.
+
+As a bonus, we also want the assistant to remember by the phone number of the caller where we left off if we get disconnected.
+
+
+
+ We'll start by taking a look at the [Assistant API
+ reference](/api-reference/assistants/create-assistant) and define our
+ assistant:
+
+ ```json
+ {
+ "transcriber":{
+ "provider": "deepgram",
+ "keywords": ["iPhone:1", "MacBook:1.5", "iPad:1", "iMac:0.8", "Watch:1", "TV:1", "Apple:2"],
+ },
+ "model": {
+ "provider": "openai",
+ "model": "gpt-4",
+ "messages": [
+ {
+ "role": "system",
+ "content": "You're a technical support assistant. You're helping a customer troubleshoot their Apple device. You can ask the customer questions, and you can use the following troubleshooting guides to help the customer solve their issue: ..."
+ }
+ ]
+ },
+ "forwardingPhoneNumber": "+16054440129",
+ "firstMessage": "Hey, I'm an A.I. assistant for Apple. I can help you troubleshoot your Apple device. What's the issue?",
+ "recordingEnabled": true,
+ }
+ ```
+
+ - `transcriber` - We're defining this to make sure the transcriber picks up the custom words related to our devices.
+ - `model` - We're using the OpenAI GPT-3.5-turbo model. It's much faster and preferred if we don't need GPT-4.
+ - `messages` - We're defining the assistant's instructions for how to run the call.
+ - `forwardingPhoneNumber` - Since we've added this, the assistant will be provided the [transferCall](/assistants#transfer-call) function to use if the caller asks to be transferred to a person.
+ - `firstMessage` - This is the first message the assistant will say when the user picks up.
+ - `recordingEnabled` - We're recording the call so we can hear the conversation later.
+
+
+
+ Since we want the assistant to remember where we left off, its configuration is going to change based on the caller. So, we're not going to use [temporary assistants](/assistants/persistent-assistants).
+
+ For this example, we're going to store the conversation on our server between calls and use the [Server URL's `assistant-request`](/server-url#retrieving-assistants) to fetch a new configuration based on the caller every time someone calls.
+
+
+
+ We'll create a phone number for inbound calls using the [Phone Numbers API](/api-reference/phone-numbers/create).
+
+ ```json
+ {
+ "id": "c86b5177-5cd8-447f-9013-99e307a8a7bb",
+ "orgId": "aa4c36ba-db21-4ce0-9c6e-99e307a8a7bb",
+ "provider": "vapi",
+ "number": "+11234567890",
+ "createdAt": "2023-09-29T21:44:37.946Z",
+ "updatedAt": "2023-12-08T00:57:24.706Z",
+ }
+ ```
+
+
+
+ When someone calls our number, we want to fetch the assistant configuration from our server. We'll use the [Server URL's `assistant-request`](/server-url#retrieving-assistants) to do this.
+
+ First, we'll create an endpoint on our server for Vapi to hit. It'll receive messages as shown in the [Assistant Request](/server-url#retrieving-assistants-calling) docs. Once created, we'll add that endpoint URL to the **Server URL** field in the Account page on the [Vapi Dashboard](https://dashboard.vapi.ai).
+
+
+
+ We'll want to save the conversation at the end of the call for the next time they call. We'll use the [Server URL's `end-of-call-report`](/server-url#end-of-call-report) message to do this.
+
+ At the end of each call, we'll get a message like this:
+
+ ```json
+ {
+ "message": {
+ "type": "end-of-call-report",
+ "endedReason": "hangup",
+ "call": { Call Object },
+ "recordingUrl": "https://vapi-public.s3.amazonaws.com/recordings/1234.wav",
+ "summary": "The user mentioned they were having an issue with their iPhone restarting randomly. They restarted their phone, but the issue persisted. They mentioned they were using an iPhone 12 Pro Max. They mentioned they were using iOS 15.",
+ "transcript": "Hey, I'm an A.I. assistant for Apple...",
+ "messages":[
+ {
+ "role": "assistant",
+ "message": "Hey, I'm an A.I. assistant for Apple. I can help you troubleshoot your Apple device. What's the issue?",
+ },
+ {
+ "role": "user",
+ "message": "Yeah I'm having an issue with my iPhone restarting randomly.",
+ },
+ ...
+ ]
+ }
+ }
+ ```
+
+ We'll save the `call.customer.number` and `summary` fields to our database for the next time they call.
+
+
+ When our number receives a call, Vapi will also hit our server's endpoint with a message like this:
+
+ ```json
+ {
+ "message": {
+ "type": "assistant-request",
+ "call": { Call Object },
+ }
+ }
+ ```
+
+ We'll check our database to see if we have a conversation for this caller. If we do, we'll create an assistant configuration like in Step 1 and respond with it:
+
+ ```json
+ {
+ "assistant": {
+ ...
+ "model": {
+ "provider": "openai",
+ "model": "gpt-4",
+ "messages": [
+ {
+ "role": "system",
+ "content": "You're a technical support assistant. Here's where we left off: ..."
+ }
+ ]
+ },
+ ...
+ }
+ }
+ ```
+
+ If we don't, we'll just respond with the assistant configuration from Step 1.
+
+
+
+
+ We'll call our number and see if it works. Give it a call, and tell it you're having an issue with your iPhone restarting randomly.
+
+ Hang up, and call back. Then ask what the issue was. The assistant should remember where we left off.
+
+
+
+
+
+ This is the content for the doc fern/examples/outbound-call-python.mdx
+
+ ---
+title: Outbound Calls from Python 📞
+subtitle: Some sample code for placing an outbound call using Python
+slug: examples/outbound-call-python
+---
+
+
+```python
+import requests
+
+# Your Vapi API Authorization token
+auth_token = ''
+# The Phone Number ID, and the Customer details for the call
+phone_number_id = ''
+customer_number = "+14151231234"
+
+# Create the header with Authorization token
+headers = {
+ 'Authorization': f'Bearer {auth_token}',
+ 'Content-Type': 'application/json',
+}
+
+# Create the data payload for the API request
+data = {
+ 'assistant': {
+ "firstMessage": "Hey, what's up?",
+ "model": {
+ "provider": "openai",
+ "model": "gpt-3.5-turbo",
+ "messages": [
+ {
+ "role": "system",
+ "content": "You are an assistant."
+ }
+ ]
+ },
+ "voice": "jennifer-playht"
+ },
+ 'phoneNumberId': phone_number_id,
+ 'customer': {
+ 'number': customer_number,
+ },
+}
+
+# Make the POST request to Vapi to create the phone call
+response = requests.post(
+ 'https://api.vapi.ai/call/phone', headers=headers, json=data)
+
+# Check if the request was successful and print the response
+if response.status_code == 201:
+ print('Call created successfully')
+ print(response.json())
+else:
+ print('Failed to create call')
+ print(response.text)
+```
+
+
+ This is the content for the doc fern/examples/outbound-sales.mdx
+
+ ---
+title: Outbound Sales Example 📞
+subtitle: Let's build an outbound sales agent that can schedule appointments.
+slug: examples/outbound-sales
+---
+
+
+We want this agent to be able to call a list of leads and schedule appointments. We'll create our assistant, create a phone number for it, then we'll configure our server for function calling to book the appointments.
+
+
+
+ We'll start by taking a look at the [Assistant API
+ reference](/api-reference/assistants/create-assistant) and define our
+ assistant:
+
+ ```json
+ {
+ "transcriber":{
+ "provider": "deepgram",
+ "keywords": ["Bicky:1"]
+ },
+ "model": {
+ "provider": "openai",
+ "model": "gpt-4",
+ "messages": [
+ {
+ "role": "system",
+ "content": "You're a sales agent for a Bicky Realty. You're calling a list of leads to schedule appointments to show them houses..."
+ }
+ ],
+ "functions": [
+ {
+ "name": "bookAppointment",
+ "description": "Used to book the appointment.",
+ "parameters": {
+ "type": "object",
+ "properties": {
+ "datetime": {
+ "type": "string",
+ "description": "The date and time of the appointment in ISO format."
+ }
+ }
+ }
+ }
+ ]
+ },
+ "voice": {
+ "provider": "openai",
+ "voiceId": "onyx"
+ },
+ "forwardingPhoneNumber": "+16054440129",
+ "voicemailMessage": "Hi, this is Jennifer from Bicky Realty. We were just calling to let you know...",
+ "firstMessage": "Hi, this Jennifer from Bicky Realty. We're calling to schedule an appointment to show you a house. When would be a good time for you?",
+ "endCallMessage": "Thanks for your time.",
+ "endCallFunctionEnabled": true,
+ "recordingEnabled": false,
+ }
+ ```
+ Let's break this down:
+ - `transcriber` - We're defining this to make sure the transcriber picks up the custom word "Bicky"
+ - `model` - We're using the OpenAI GPT-4 model, which is better at function calling.
+ - `messages` - We're defining the assistant's instructions for how to run the call.
+ - `functions` - We're providing a bookAppointment function with a datetime parameter. The assistant can call this during the conversation to book the appointment.
+ - `voice` - We're using the Onyx voice from OpenAI.
+ - `forwardingPhoneNumber` - Since we've added this, the assistant will be provided the [transferCall](/assistants#transfer-call) function to use.
+ - `voicemailMessage` - If the call goes to voicemail, this message will be played.
+ - `firstMessage` - This is the first message the assistant will say when the user picks up.
+ - `endCallMessage` - This is the message the assistant will deciding to hang up.
+ - `endCallFunctionEnabled` - This will give the assistant the [endCall](/assistants#end-call) function.
+ - `recordingEnabled` - We've disabled recording, since we don't have the user's consent to record the call.
+
+ We'll then make a POST request to the [Create Assistant](/api-reference/assistants/create-assistant) endpoint to create the assistant.
+
+
+
+ We'll create a phone number for outbound calls using the [Phone Numbers API](/phone-calling#set-up-a-phone-number).
+
+ ```json
+ {
+ "id": "c86b5177-5cd8-447f-9013-99e307a8a7bb",
+ "orgId": "aa4c36ba-db21-4ce0-9c6e-99e307a8a7bb",
+ "provider": "vapi",
+ "number": "+11234567890",
+ "createdAt": "2023-09-29T21:44:37.946Z",
+ "updatedAt": "2023-12-08T00:57:24.706Z",
+ }
+ ```
+
+ Great, let's take note of that `id` field- we'll need it later.
+
+
+
+ When the assistant calls that `bookAppointment` function, we'll want to handle that function call and actually book the appointment. We also want to let the user know if booking the appointment was unsuccessful.
+
+ First, we'll create an endpoint on our server for Vapi to hit. It'll receive messages as shown in the [Function Calling](/server-url#function-calling) docs. Once created, we'll add that endpoint URL to the **Server URL** field in the Account page on the [Vapi Dashboard](https://dashboard.vapi.ai).
+
+
+
+ So now, when the assistant decides to call `bookAppointment`, our server will get something like this:
+
+ ```json
+ {
+ "message": {
+ "type": "function-call",
+ "call": { Call Object },
+ "functionCall": {
+ "name": "bookAppointment",
+ "parameters": "{ \"datetime\": \"2023-09-29T21:44:37.946Z\"}"
+ }
+ }
+ }
+ ```
+
+ We'll do our own logic to book the appointment, then we'll respond to the request with the result to let the assistant know it was booked:
+
+ ```json
+ { "result": "The appointment was booked successfully." }
+ ```
+
+ or, if it failed:
+
+ ```json
+ { "result": "The appointment time is unavailable, please try another time." }
+ ```
+
+ So, when the assistant calls this function, these results will be appended to the conversation, and the assistant will respond to the user knowing the result.
+
+ Great, now we're ready to start calling leads!
+
+
+
+ We'll use the [Create Phone Call](/api-reference/calls/create-phone-call) endpoint to place a call to a lead:
+
+ ```json
+ {
+ "phoneNumberId": "c86b5177-5cd8-447f-9013-99e307a8a7bb",
+ "assistantId": "d87b5177-5cd8-447f-9013-99e307a8a7bb",
+ "customer": {
+ "number": "+11234567890"
+ }
+ }
+ ```
+
+ Since we also defined a `forwardingPhoneNumber`, when the user asks to speak to a human, the assistant will transfer the call to that number automatically.
+
+ We can then check the [Dashboard](https://dashboard.vapi.ai) to see the call logs and read the transcripts.
+
+
+
+
+
+ This is the content for the doc fern/examples/pizza-website.mdx
+
+ ---
+title: Pizza Website Example 🍕
+subtitle: Let's build a pizza ordering assistant for our website.
+slug: examples/pizza-website
+---
+
+
+In this example, we'll be using the [Web SDK](https://github.com/VapiAI/web) to create an assistant that can take a pizza order. Since all the [Client SDKs](/sdks) have equivalent functionality, you can use this example as a guide for any Vapi client.
+
+We want to add a button to the page to start a call, update our UI with the call status, and display what the user's saying while they say it. When the user mentions a topping, we should add it to the pizza. When they're done, we should redirect them to checkout.
+
+
+
+ We'll start by taking a look at the [Assistant API
+ reference](/api-reference/assistants/create-assistant) and define our
+ assistant:
+
+ ```json
+ {
+ "model": {
+ "provider": "openai",
+ "model": "gpt-4",
+ "messages": [
+ {
+ "role": "system",
+ "content": "You're a pizza ordering assistant. The user will ask for toppings, you'll add them. When they're done, you'll redirect them to checkout."
+ }
+ ],
+ "functions": [
+ {
+ "name": "addTopping",
+ "description": "Used to add a topping to the pizza.",
+ "parameters": {
+ "type": "object",
+ "properties": {
+ "topping": {
+ "type": "string",
+ "description": "The name of the topping. For example, 'pepperoni'."
+ }
+ }
+ }
+ },
+ {
+ "name": "goToCheckout",
+ "description": "Redirects the user to checkout and order their pizza.",
+ "parameters": {"type": "object", "properties": {}}
+ }
+ ]
+ },
+ "firstMessage": "Hi, I'm the pizza ordering assistant. What toppings would you like?",
+ }
+ ```
+ Let's break this down:
+ - `model` - We're using the OpenAI GPT-4 model, which is better at function calling.
+ - `messages` - We're defining the assistant's instructions for how to run the call.
+ - `functions` - We're providing a addTopping function with a topping parameter. The assistant can call this during the conversation to add a topping. We're also adding goToCheckout, with an empty parameters object. The assistant can call this to redirect the user to checkout.
+ - `firstMessage` - This is the first message the assistant will say when the user starts the call.
+
+ We'll then make a POST request to the [Create Assistant](/api-reference/assistants/create-assistant) endpoint to create the assistant.
+
+
+
+ We'll follow the `README` for the [Web SDK](https://github.com/VapiAI/web) to get it installed.
+
+ We'll then get our **Public Key** from the [Vapi Dashboard](https://dashboard.vapi.ai) and initialize the SDK:
+
+ ```js
+ import Vapi from '@vapi-ai/web';
+
+ const vapi = new Vapi('your-web-token');
+ ```
+
+
+
+ We'll add a button to the page that starts the call when clicked:
+
+ ```html
+
+
+ ```
+
+ ```js
+ const startCallButton = document.getElementById('start-call');
+
+ startCallButton.addEventListener('click', async () => {
+ await vapi.start('your-assistant-id');
+ });
+
+ const stopCallButton = document.getElementById('stop-call');
+
+ stopCallButton.addEventListener('click', async () => {
+ await vapi.stop();
+ });
+ ```
+
+
+
+ ```js
+ vapi.on('call-start', () => {
+ // Update UI to show that the call has started
+ });
+
+ vapi.on('call-end', () => {
+ // Update UI to show that the call has ended
+ });
+ ```
+
+
+
+
+ ```js
+ vapi.on('speech-start', () => {
+ // Update UI to show that the assistant is speaking
+ });
+
+vapi.on('speech-end', () => {
+// Update UI to show that the assistant is done speaking
+});
+
+````
+
+
+
+
+ All messages send to the [Server URL](/server-url), including `transcript` and `function-call` messages, are also sent to the client as `message` events. We'll need to check the `type` of the message to see what type it is.
+
+```js
+vapi.on("message", (msg) => {
+ if (msg.type !== "transcript") return;
+
+ if (msg.transcriptType === "partial") {
+ // Update UI to show the live partial transcript
+ }
+
+ if (msg.transcriptType === "final") {
+ // Update UI to show the final transcript
+ }
+});
+````
+
+
+
+
+```javascript
+vapi.on('message', (msg) => {
+ if (msg.type !== "function-call") return;
+
+if (msg.functionCall.name === "addTopping") {
+const topping = msg.functionCall.parameters.topping;
+// Add the topping to the pizza
+}
+
+if (msg.functionCall.name === "goToCheckout") {
+// Redirect the user to checkout
+}
+});
+
+```
+
+
+You should now have a working pizza ordering assistant! 🍕
+
+
+
+```
+
+
+ This is the content for the doc fern/examples/voice-widget.mdx
+
+ ---
+title: Web Snippet
+subtitle: >-
+ Easily integrate the Vapi Voice Widget into your website for enhanced user
+ interaction.
+slug: examples/voice-widget
+---
+
+
+Improve your website's user interaction with the Vapi Voice Widget. This robust tool enables your visitors to engage with a voice assistant for support and interaction, offering a smooth and contemporary way to connect with your services.
+
+## Steps for Installation
+
+
+
+ Copy the snippet below and insert it into your website's HTML, ideally before the closing `