From 18c313b48b25f75eb4236a0dba9a5908e29986a9 Mon Sep 17 00:00:00 2001 From: goosewin Date: Mon, 26 May 2025 16:14:56 -0700 Subject: [PATCH 01/12] feat: create dedicated `examples` page --- fern/examples.mdx | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 fern/examples.mdx diff --git a/fern/examples.mdx b/fern/examples.mdx new file mode 100644 index 00000000..480065e3 --- /dev/null +++ b/fern/examples.mdx @@ -0,0 +1,20 @@ +--- +title: Examples +subtitle: Explore complete examples with step-by-step instructions to build with Vapi +slug: examples +--- + + + + Create an outbound sales agent that can schedule appointments automatically + + + Build a technical support assistant that remembers where you left off between calls + + + Build a pizza ordering assistant for your website using the Web SDK + + + Easily integrate the Vapi Voice Widget into your website for enhanced user interaction + + From 59474864349aabe67f8c6c5a6d73079f8978dbcb Mon Sep 17 00:00:00 2001 From: goosewin Date: Mon, 26 May 2025 16:15:21 -0700 Subject: [PATCH 02/12] feat(web): add web sdk quickstart --- fern/quickstart/web.mdx | 570 ++++++++++++++++++++++++++++++++++------ 1 file changed, 488 insertions(+), 82 deletions(-) diff --git a/fern/quickstart/web.mdx b/fern/quickstart/web.mdx index 64f4a16a..d308e2dc 100644 --- a/fern/quickstart/web.mdx +++ b/fern/quickstart/web.mdx @@ -1,116 +1,522 @@ --- -title: Web call -subtitle: Make a web call to your assistant from a browser +title: Web SDK Quickstart +subtitle: Learn to build web applications with Vapi Web SDK in under 5 minutes. +slug: quickstart/web --- -## Overview +## Installation -This guide shows you how to integrate live, two-way voice calls with your Vapi assistant into any web app. You can use Vapi in plain JavaScript, React, Next.js, or any other web framework. + + + + + ```bash + npm install @vapi-ai/web + ``` + + + ```bash + yarn add @vapi-ai/web + ``` + + + ```bash + pnpm add @vapi-ai/web + ``` + + + ```bash + bun add @vapi-ai/web + ``` + + + -Get started with either the Vapi web SDK or by connecting to an assistant you created in the dashboard. + + You'll need your public API key and/or private API key from the [Dashboard → Vapi API Keys](https://dashboard.vapi.ai/org/api-keys). -See the full next.js [demo here on v0](https://v0.dev/chat/vapi-quickstart-nextjs-z3lv02T7Dd5). To try it live and make edits, follow these steps: + + Always use your **public key** (starts with `pk_`) in client-side code. Never expose your private key in the browser. + + -1. Fork the app in v0 -2. Go to settings --> environment variables -3. Create a new environment variable called `NEXT_PUBLIC_VAPI_API_KEY` -4. Add your [public api key from the dashboard](https://dashboard.vapi.ai/org/api-keys)! + + You'll need your assistant ID from the [Dashboard → Assistants](https://dashboard.vapi.ai/assistants). + + -## Installation +## Framework Examples - - ### Install the SDK - + + + + + ```env title=".env.local" + NEXT_PUBLIC_VAPI_API_KEY=pk_your_public_key_here + NEXT_PUBLIC_VAPI_ASSISTANT_ID=your_assistant_id_here + ``` + - ### Import the SDK - - + + ```typescript title="components/voice-button.tsx" + 'use client'; -## Get started + import Vapi from '@vapi-ai/web'; + import { useState } from 'react'; - - + export function VoiceButton() { + const [vapi] = useState(() => new Vapi(process.env.NEXT_PUBLIC_VAPI_API_KEY!)); + const [isActive, setIsActive] = useState(false); + + const toggleCall = async () => { + if (isActive) { + vapi.stop(); + } else { + await vapi.start(process.env.NEXT_PUBLIC_VAPI_ASSISTANT_ID!); + } + }; + + vapi.on('call-start', () => setIsActive(true)); + vapi.on('call-end', () => setIsActive(false)); + + return ( + + ); + } + ``` + + + + ```typescript title="app/page.tsx" + import { VoiceButton } from '@/components/voice-button'; + + export default function Home() { + return ( +
+

Voice AI Demo

+ +
+ ); + } + ``` +
+
+ + + - - Create an assistant object. - - ```javascript - const assistantOptions = { - name: "Vapi's Pizza Front Desk", - firstMessage: "Vapi's Pizzeria speaking, how can I help you?", - transcriber: { - provider: "deepgram", - model: "nova-2", - language: "en-US", - }, - voice: { - provider: "playht", - voiceId: "jennifer", - }, - model: { - provider: "openai", - model: "gpt-4", - messages: [ - { - role: "system", - content: `You are a voice assistant for Vappy's Pizzeria, a pizza shop located on the Internet.\n\nYour job is to take the order of customers calling in. The menu has only 3 types of items: pizza, sides, and drinks. There are no other types of items on the menu.\n\n1) There are 3 kinds of pizza: cheese pizza, pepperoni pizza, and vegetarian pizza (often called \"veggie\" pizza).\n2) There are 3 kinds of sides: french fries, garlic bread, and chicken wings.\n3) There are 2 kinds of drinks: soda, and water. (if a customer asks for a brand name like \"coca cola\", just let them know that we only offer \"soda\")\n\nCustomers can only order 1 of each item. If a customer tries to order more than 1 item within each category, politely inform them that only 1 item per category may be ordered.\n\nCustomers must order 1 item from at least 1 category to have a complete order. They can order just a pizza, or just a side, or just a drink.\n\nBe sure to introduce the menu items, don't assume that the caller knows what is on the menu (most appropriate at the start of the conversation).\n\nIf the customer goes off-topic or off-track and talks about anything but the process of ordering, politely steer the conversation back to collecting their order.\n\nOnce you have all the information you need pertaining to their order, you can end the conversation. You can say something like \"Awesome, we'll have that ready for you in 10-20 minutes.\" to naturally let the customer know the order has been fully communicated.\n\nIt is important that you collect the order in an efficient manner (succinct replies & direct questions). You only have 1 task here, and it is to collect the customers order, then end the conversation.\n\n- Be sure to be kind of funny and witty!\n- Keep all your responses short and simple. Use casual language, phrases like \"Umm...\", \"Well...\", and \"I mean\" are preferred.\n- This is a voice conversation, so keep your responses short, like in a real conversation. Don't ramble for too long.`, - }, - ], - }, - }; + + ```env title=".env" + VITE_VAPI_API_KEY=pk_your_public_key_here + VITE_VAPI_ASSISTANT_ID=your_assistant_id_here ``` + + + + ```typescript title="components/VoiceButton.tsx" + import Vapi from '@vapi-ai/web'; + import { useState } from 'react'; - **Parameters:** - - `name` sets the display name for the assistant (internal use) - - `firstMessage` is the first message the assistant says - - `transcriber` selects the speech-to-text provider and model - - `voice` selects the text-to-speech provider and voice - - `model` sets the LLM provider, model, and system prompt + export function VoiceButton() { + const [vapi] = useState(() => new Vapi(import.meta.env.VITE_VAPI_API_KEY)); + const [isActive, setIsActive] = useState(false); + + const toggleCall = async () => { + if (isActive) { + vapi.stop(); + } else { + await vapi.start(import.meta.env.VITE_VAPI_ASSISTANT_ID); + } + }; + + vapi.on('call-start', () => setIsActive(true)); + vapi.on('call-end', () => setIsActive(false)); + + return ( + + ); + } + ``` - - Start a call using your assistant configuration. - ```javascript - vapi.start(assistantOptions); + + ```typescript title="src/App.tsx" + import { VoiceButton } from './components/VoiceButton'; + + function App() { + return ( +
+

Voice AI Demo

+ +
+ ); + } + + export default App; ```
- + + - - To create an assistant in the dashboard, follow the step-by-step guide in the [Dashboard Quickstart](https://docs.vapi.ai/quickstart/dashboard#get-started). + + ```env title=".env" + VITE_VAPI_API_KEY=pk_your_public_key_here + VITE_VAPI_ASSISTANT_ID=your_assistant_id_here + ``` - - Once you have your assistant's ID, you can start a call with it: - - Assistant ID in dashboard - + + ```vue title="src/components/VoiceButton.vue" + + + ``` - - To override assistant settings or set template variables, pass an `assistantOverrides` object as the second argument. - - ```javascript - const assistantOverrides = { - transcriber: { - provider: "deepgram", - model: "nova-2", - language: "en-US", - }, - recordingEnabled: false, - variableValues: { - name: "John", - }, + + + + + + + + + ```env title=".env" + VITE_VAPI_API_KEY=pk_your_public_key_here + VITE_VAPI_ASSISTANT_ID=your_assistant_id_here + ``` + + + + ```svelte title="src/lib/VoiceButton.svelte" + + + + ``` + + + + ```svelte title="src/routes/+page.svelte" + + +
+

Voice AI Demo

+ +
+ ``` +
+
+
+ + + + + ```env title=".env" + VITE_VAPI_API_KEY=pk_your_public_key_here + VITE_VAPI_ASSISTANT_ID=your_assistant_id_here + ``` + + + + ```svelte title="src/lib/VoiceButton.svelte" + + + + ``` + + + + ```svelte title="src/routes/+page.svelte" + + +
+

Voice AI Demo

+ +
+ ``` +
+
+
+
+
+ + + + + ```typescript title="src/environments/environment.ts" + export const environment = { + production: false, + vapiApiKey: 'pk_your_public_key_here', + vapiAssistantId: 'your_assistant_id_here' }; + ``` + + + + ```typescript title="src/app/voice-button/voice-button.component.ts" + import { Component, OnInit, OnDestroy } from '@angular/core'; + import Vapi from '@vapi-ai/web'; + import { environment } from '../../environments/environment'; + + @Component({ + selector: 'app-voice-button', + template: ` + + ` + }) + export class VoiceButtonComponent implements OnInit, OnDestroy { + isActive = false; + private vapi!: Vapi; + + ngOnInit() { + this.vapi = new Vapi(environment.vapiApiKey); + + this.vapi.on('call-start', () => { + this.isActive = true; + }); + + this.vapi.on('call-end', () => { + this.isActive = false; + }); + } + + ngOnDestroy() { + if (this.vapi) { + this.vapi.removeAllListeners(); + } + } - vapi.start("YOUR_ASSISTANT_ID_FROM_THE_DASHBOARD", assistantOverrides); + async toggleCall() { + if (this.isActive) { + this.vapi.stop(); + } else { + await this.vapi.start(environment.vapiAssistantId); + } + } + } + ``` + + + + ```typescript title="src/app/app.component.ts" + import { Component } from '@angular/core'; + + @Component({ + selector: 'app-root', + template: ` +
+

Voice AI Demo

+ +
+ ` + }) + export class AppComponent {} ```
+ + + ```javascript title="main.js" + import Vapi from '@vapi-ai/web'; + + const vapi = new Vapi('pk_your_public_key_here'); + const button = document.getElementById('voice-btn'); + let isActive = false; + + button.addEventListener('click', async () => { + if (isActive) { + vapi.stop(); + } else { + await vapi.start('your_assistant_id'); + } + }); + + vapi.on('call-start', () => { + isActive = true; + button.textContent = 'End Call'; + }); + + vapi.on('call-end', () => { + isActive = false; + button.textContent = 'Start Call'; + }); + ``` + + +## Basic Usage + +### Core Methods + +```typescript +// Initialize Vapi +const vapi = new Vapi('pk_your_public_key'); + +// Start a call +await vapi.start('your_assistant_id'); + +// End a call +vapi.stop(); + +// Listen to events +vapi.on('call-start', () => console.log('Call started')); +vapi.on('call-end', () => console.log('Call ended')); +vapi.on('message', (message) => console.log('Message:', message)); +``` + +### Assistant Configuration + +You can also pass an assistant configuration directly instead of using an ID: + +```typescript +const assistantConfig = { + model: { + provider: "openai", + model: "gpt-4o-2024-11-20", + }, + voice: { + provider: "11labs", + voiceId: "21m00Tcm4TlvDq8ikWAM", + }, + firstMessage: "Hello! How can I help you today?", + systemMessage: "You are a helpful assistant.", +}; + +await vapi.start(assistantConfig); +``` + +## Next Steps + + + + Complete Web SDK documentation + + + Complete API reference documentation + + + + + **Need help?** Join our [Discord community](https://discord.gg/vapi) or check out the [full documentation](/overview). + From c793defcfb776c47055d8539da62142686cc38ef Mon Sep 17 00:00:00 2001 From: goosewin Date: Mon, 26 May 2025 16:15:37 -0700 Subject: [PATCH 03/12] chore(dashboard): update dashboard quickstart for consistency --- fern/quickstart/dashboard.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fern/quickstart/dashboard.mdx b/fern/quickstart/dashboard.mdx index e48f875c..7b687357 100644 --- a/fern/quickstart/dashboard.mdx +++ b/fern/quickstart/dashboard.mdx @@ -1,6 +1,6 @@ --- title: Dashboard -subtitle: Learn to build a voice agent in under 5 minutes. +subtitle: Learn to build a voice agent in under 5 minutes using the Vapi dashboard. slug: quickstart/dashboard --- @@ -138,4 +138,4 @@ Vapi makes it easy to build end-to-end voice agents, which we call ***assistants You will learn more about configuring call end behaviour in later guides. - \ No newline at end of file + From 9d524896acbf65b43b6ea59f3ea722e99e33066b Mon Sep 17 00:00:00 2001 From: goosewin Date: Mon, 26 May 2025 16:15:44 -0700 Subject: [PATCH 04/12] chore: update navigation --- fern/docs.yml | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/fern/docs.yml b/fern/docs.yml index b8dc7ff5..e6fb431a 100644 --- a/fern/docs.yml +++ b/fern/docs.yml @@ -94,23 +94,15 @@ navigation: layout: - section: Get started contents: - - page: Quickstart - icon: fa-light fa-bolt-lightning + - page: Dashboard + icon: fa-light fa-table-columns path: quickstart/dashboard.mdx - - page: Make a web call - icon: fa-light fa-browser + - page: Web SDK + icon: fa-light fa-laptop-code path: quickstart/web.mdx - - section: How Vapi works - icon: fa-light fa-diagram-project - contents: - - page: Core models - path: quickstart.mdx - icon: fa-light fa-microchip-ai - - page: Orchestration models - icon: fa-light fa-network-wired - path: how-vapi-works.mdx - section: Examples icon: fa-light fa-code + path: examples.mdx contents: - page: Outbound sales path: examples/outbound-sales.mdx @@ -187,7 +179,7 @@ navigation: contents: - page: Query tool path: knowledge-base/using-query-tool.mdx - icon: fa-light fa-magnifying-glass + icon: fa-light fa-magnifying-glass - page: Trieve integration path: knowledge-base/integrating-with-trieve.mdx icon: fa-light fa-brain @@ -322,6 +314,15 @@ navigation: - page: FAQ path: faq.mdx icon: fa-light fa-question + - section: How Vapi works + icon: fa-light fa-diagram-project + contents: + - page: Core models + path: quickstart.mdx + icon: fa-light fa-microchip-ai + - page: Orchestration models + icon: fa-light fa-network-wired + path: how-vapi-works.mdx - section: Integrations collapsed: true icon: fa-light fa-link @@ -508,7 +509,7 @@ navigation: - page: MCP server path: sdk/mcp-server.mdx icon: fa-light fa-server - + - tab: sdks layout: - section: Client SDKs From 2a61406009c2b57502ec5f9190206af1c316947f Mon Sep 17 00:00:00 2001 From: goosewin Date: Mon, 26 May 2025 20:06:28 -0700 Subject: [PATCH 05/12] feat(quickstart/web): remove less popular framework starters, expand on core features --- fern/quickstart/web.mdx | 536 +++++++++++++++++++--------------------- 1 file changed, 254 insertions(+), 282 deletions(-) diff --git a/fern/quickstart/web.mdx b/fern/quickstart/web.mdx index d308e2dc..f0e6d258 100644 --- a/fern/quickstart/web.mdx +++ b/fern/quickstart/web.mdx @@ -45,7 +45,7 @@ slug: quickstart/web -## Framework Examples +## Quick Start @@ -168,274 +168,6 @@ slug: quickstart/web - - - - ```env title=".env" - VITE_VAPI_API_KEY=pk_your_public_key_here - VITE_VAPI_ASSISTANT_ID=your_assistant_id_here - ``` - - - - ```vue title="src/components/VoiceButton.vue" - - - - ``` - - - - - - - - - - ```env title=".env" - VITE_VAPI_API_KEY=pk_your_public_key_here - VITE_VAPI_ASSISTANT_ID=your_assistant_id_here - ``` - - - - ```svelte title="src/lib/VoiceButton.svelte" - - - - ``` - - - - ```svelte title="src/routes/+page.svelte" - - -
-

Voice AI Demo

- -
- ``` -
-
-
- - - - - ```env title=".env" - VITE_VAPI_API_KEY=pk_your_public_key_here - VITE_VAPI_ASSISTANT_ID=your_assistant_id_here - ``` - - - - ```svelte title="src/lib/VoiceButton.svelte" - - - - ``` - - - - ```svelte title="src/routes/+page.svelte" - - -
-

Voice AI Demo

- -
- ``` -
-
-
-
-
- - - - - ```typescript title="src/environments/environment.ts" - export const environment = { - production: false, - vapiApiKey: 'pk_your_public_key_here', - vapiAssistantId: 'your_assistant_id_here' - }; - ``` - - - - ```typescript title="src/app/voice-button/voice-button.component.ts" - import { Component, OnInit, OnDestroy } from '@angular/core'; - import Vapi from '@vapi-ai/web'; - import { environment } from '../../environments/environment'; - - @Component({ - selector: 'app-voice-button', - template: ` - - ` - }) - export class VoiceButtonComponent implements OnInit, OnDestroy { - isActive = false; - private vapi!: Vapi; - - ngOnInit() { - this.vapi = new Vapi(environment.vapiApiKey); - - this.vapi.on('call-start', () => { - this.isActive = true; - }); - - this.vapi.on('call-end', () => { - this.isActive = false; - }); - } - - ngOnDestroy() { - if (this.vapi) { - this.vapi.removeAllListeners(); - } - } - - async toggleCall() { - if (this.isActive) { - this.vapi.stop(); - } else { - await this.vapi.start(environment.vapiAssistantId); - } - } - } - ``` - - - - ```typescript title="src/app/app.component.ts" - import { Component } from '@angular/core'; - - @Component({ - selector: 'app-root', - template: ` -
-

Voice AI Demo

- -
- ` - }) - export class AppComponent {} - ``` -
-
-
- ```javascript title="main.js" import Vapi from '@vapi-ai/web'; @@ -465,32 +197,269 @@ slug: quickstart/web
-## Basic Usage +## Core Features -### Core Methods +### Starting and Stopping Calls + +Start voice conversations with your AI assistant using either a pre-configured assistant ID or inline configuration. You can customize the model, voice, and behavior on-the-fly. ```typescript +import Vapi from "@vapi-ai/web"; +import { CreateAssistantDTO } from "@vapi-ai/web/dist/api"; + // Initialize Vapi const vapi = new Vapi('pk_your_public_key'); -// Start a call +// Start a call with assistant ID await vapi.start('your_assistant_id'); +// Start with inline assistant config +const assistantConfig: CreateAssistantDTO = { + model: { + provider: "openai", + model: "gpt-4o-2024-05-13", + messages: [ + { + role: "system", + content: "You are a helpful assistant." + } + ] + }, + voice: { + provider: "11labs", + voiceId: "21m00Tcm4TlvDq8ikWAM", + }, + firstMessage: "Hello! How can I help you today?", +}; +await vapi.start(assistantConfig); + // End a call vapi.stop(); +``` + +### Event Handling + +Monitor call lifecycle, speech activity, and real-time transcription. These events help you build responsive UIs and handle call state changes. + +```typescript +// Call lifecycle events +vapi.on('call-start', () => { + console.log('Call started'); +}); + +vapi.on('call-end', () => { + console.log('Call ended'); +}); + +// Speech events +vapi.on('speech-start', () => { + console.log('User started speaking'); +}); + +vapi.on('speech-end', () => { + console.log('User stopped speaking'); +}); + +// Message events +vapi.on('message', (message) => { + console.log('Received message:', message); +}); + +// Volume level (for visualizations) +vapi.on('volume-level', (level) => { + console.log('Volume level:', level); +}); + +// Error handling +vapi.on('error', (error) => { + console.error('Call error:', error); +}); +``` + +### Sending Messages + +Inject context or trigger actions by sending messages to your assistant during an active call. Useful for providing real-time updates or user interface interactions. + +```typescript +// Send a text message +vapi.send({ + type: 'add-message', + message: { + role: 'system', + content: 'The user just clicked a button on the interface.' + } +}); + +// Add tool call result +vapi.send({ + type: 'add-message', + message: { + role: 'tool', + content: { + name: 'getUserData', + parameters: { userId: '123' }, + } + } +}); +``` + +### Mute Control + +Control microphone input during calls. Essential for privacy and managing when the assistant should listen to user speech. + +```typescript +// Mute/unmute the microphone +vapi.setMuted(true); // Mute +vapi.setMuted(false); // Unmute + +// Check if muted +const isMuted = vapi.isMuted(); +``` + +### Assistant Overrides + +Customize assistant behavior for specific calls without modifying your base assistant configuration in Vapi API or Vapi Dashboard. Override transcription settings, recording options, conversation flow, etc. -// Listen to events -vapi.on('call-start', () => console.log('Call started')); -vapi.on('call-end', () => console.log('Call ended')); -vapi.on('message', (message) => console.log('Message:', message)); +```typescript +const vapi = new Vapi('pk_your_key'); + +const overrides: OverrideAssistantDTO = { + // Assistant overrides + firstMessageMode: 'assistant-waits-for-user', // wait for user to speak first + recordingEnabled: false, // don't record the call + + // use deepgram for transcription + transcriber: { + provider: 'deepgram', + model: 'nova-2', + language: 'en-US' + }, + + // use custom summary prompt + analysisPlan: { + summaryPrompt: 'Summarize the conversation in a few sentences.', + }, +}; + +// Start call with overrides +await vapi.start('your_assistant_id', overrides); ``` -### Assistant Configuration +### React Hook Example + +Simplify Vapi integration with a custom React hook that manages call state, conversation history, and common controls in a reusable way. + +```typescript title="hooks/useVapi.ts" +import { useState, useEffect, useCallback } from 'react'; +import Vapi from '@vapi-ai/web'; + +export function useVapi(apiKey: string) { + const [vapi] = useState(() => new Vapi(apiKey)); + const [isActive, setIsActive] = useState(false); + const [isMuted, setIsMuted] = useState(false); + const [volume, setVolume] = useState(0); + const [conversation, setConversation] = useState>([]); + + useEffect(() => { + vapi.on('call-start', () => setIsActive(true)); + vapi.on('call-end', () => setIsActive(false)); + vapi.on('volume-level', setVolume); + + vapi.on('message', (message) => { + if (message.type === 'transcript' && message.transcript) { + setConversation(prev => [...prev, { + role: message.transcript.role, + text: message.transcript.text, + timestamp: new Date().toISOString(), + }]); + } + }); -You can also pass an assistant configuration directly instead of using an ID: + return () => { + vapi.removeAllListeners(); + }; + }, [vapi]); + + const start = useCallback(async (assistantId: string) => { + setConversation([]); + await vapi.start(assistantId); + }, [vapi]); + + const stop = useCallback(() => { + vapi.stop(); + }, [vapi]); + + const toggleMute = useCallback(() => { + const newMuted = !isMuted; + vapi.setMuted(newMuted); + setIsMuted(newMuted); + }, [vapi, isMuted]); + + return { + vapi, + isActive, + isMuted, + volume, + conversation, + start, + stop, + toggleMute + }; +} +``` + +### Defining Custom Tools + +Enable your assistant to call external functions and APIs with custom tools. ```typescript -const assistantConfig = { +// Assistant with function calling +const assistantWithTools: CreateAssistantDTO = { + model: { + provider: "openai", + model: "gpt-4o-2024-05-13", + tools: [ + { + type: "function", + function: { + name: "get_weather", + description: "Get current weather for a location", + parameters: { + type: "object", + properties: { + location: { + type: "string", + description: "City name" + } + }, + required: ["location"] + } + } + } + ], + }, + voice: { + provider: "11labs", + voiceId: "21m00Tcm4TlvDq8ikWAM", + }, + serverUrl: "https://your-domain.com/api/webhook", + firstMessage: "Hello! I can help you with weather information and more.", +}; + +await vapi.start(assistantWithTools); +``` + +### Video Recording + +Capture video recordings of web-based voice calls. + +```typescript +// Assistant with video recording enabled +const videoAssistant = { model: { provider: "openai", model: "gpt-4o-2024-11-20", @@ -499,11 +468,14 @@ const assistantConfig = { provider: "11labs", voiceId: "21m00Tcm4TlvDq8ikWAM", }, - firstMessage: "Hello! How can I help you today?", - systemMessage: "You are a helpful assistant.", + artifactPlan: { + videoRecordingEnabled: true, + recordingEnabled: true, + }, + firstMessage: "Hello! This call is being recorded with video. How can I help?", }; -await vapi.start(assistantConfig); +await vapi.start(videoAssistant); ``` ## Next Steps From 26591be3612695473c3f847cbc1bbc635706829a Mon Sep 17 00:00:00 2001 From: goosewin Date: Tue, 27 May 2025 10:31:04 -0700 Subject: [PATCH 06/12] chore(quickstart/web): address PR feedback --- fern/quickstart/web.mdx | 341 ++++++++++++++++++++++++++-------------- 1 file changed, 222 insertions(+), 119 deletions(-) diff --git a/fern/quickstart/web.mdx b/fern/quickstart/web.mdx index f0e6d258..14c73e40 100644 --- a/fern/quickstart/web.mdx +++ b/fern/quickstart/web.mdx @@ -1,9 +1,62 @@ --- title: Web SDK Quickstart -subtitle: Learn to build web applications with Vapi Web SDK in under 5 minutes. +subtitle: Build a customer support voice assistant in under 5 minutes using Vapi Web SDK. slug: quickstart/web --- +In this quickstart, we'll build a **customer support voice assistant** that can help users with order inquiries, account questions, and general support. You'll learn how to integrate Vapi's Web SDK and see both ways to configure your assistant. + +## Ways to Configure Assistant + +With Vapi, you have flexibility in how you configure your assistant: + + + + Dashboard Configuration + + Recommended for production + + + } icon="dashboard"> + + Configure your assistant in the [Vapi Dashboard](https://dashboard.vapi.ai/assistants). Your configuration is stored securely and pulled automatically when you provide the assistant ID. + + + SDK Configuration + + Great for customization + + + } icon="code"> + + Pass configuration directly to the Web SDK. You can override existing assistants or create entirely new ones programmatically based on your app logic. + + + +Instructions below are going to primarily focus on configuring the assistant via the Web SDK. + ## Installation @@ -33,19 +86,35 @@ slug: quickstart/web - You'll need your public API key and/or private API key from the [Dashboard → Vapi API Keys](https://dashboard.vapi.ai/org/api-keys). + You'll need your public API key from the [Dashboard → Vapi API Keys](https://dashboard.vapi.ai/org/api-keys). Always use your **public key** (starts with `pk_`) in client-side code. Never expose your private key in the browser. - - You'll need your assistant ID from the [Dashboard → Assistants](https://dashboard.vapi.ai/assistants). + + **Option 1: Dashboard Configuration** + + Create an assistant in the [Dashboard → Assistants](https://dashboard.vapi.ai/assistants) with this system prompt: + + ``` + You are a helpful customer support assistant for TechCorp. You can help with: + - Order status and tracking + - Account questions + - Product information + - Technical support + + Be friendly, professional, and concise. If you need to look up specific information, ask for order numbers or account details. + ``` + + **Option 2: SDK Configuration** + + We'll show you how to configure the assistant directly in code below. -## Quick Start +## Build an Assistant @@ -53,6 +122,7 @@ slug: quickstart/web ```env title=".env.local" NEXT_PUBLIC_VAPI_API_KEY=pk_your_public_key_here + # Only needed if using Dashboard configuration NEXT_PUBLIC_VAPI_ASSISTANT_ID=your_assistant_id_here ``` @@ -72,7 +142,29 @@ slug: quickstart/web if (isActive) { vapi.stop(); } else { - await vapi.start(process.env.NEXT_PUBLIC_VAPI_ASSISTANT_ID!); + // Option 1: Use Dashboard-configured assistant + if (process.env.NEXT_PUBLIC_VAPI_ASSISTANT_ID) { + await vapi.start(process.env.NEXT_PUBLIC_VAPI_ASSISTANT_ID); + } else { + // Option 2: Configure assistant directly in SDK + await vapi.start({ + model: { + provider: "openai", + model: "gpt-4o-2024-05-13", + messages: [ + { + role: "system", + content: "You are a helpful customer support assistant for TechCorp. You can help with order status, account questions, product information, and technical support. Be friendly, professional, and concise." + } + ] + }, + voice: { + provider: "11labs", + voiceId: "21m00Tcm4TlvDq8ikWAM", + }, + firstMessage: "Hi! I'm here to help with your TechCorp support needs. How can I assist you today?", + }); + } } }; @@ -98,7 +190,10 @@ slug: quickstart/web export default function Home() { return (
-

Voice AI Demo

+

TechCorp Customer Support

+

+ Need help? Click the button below to speak with our AI support assistant. +

); @@ -113,6 +208,7 @@ slug: quickstart/web ```env title=".env" VITE_VAPI_API_KEY=pk_your_public_key_here + # Only needed if using Dashboard configuration VITE_VAPI_ASSISTANT_ID=your_assistant_id_here ``` @@ -130,7 +226,29 @@ slug: quickstart/web if (isActive) { vapi.stop(); } else { - await vapi.start(import.meta.env.VITE_VAPI_ASSISTANT_ID); + // Option 1: Use Dashboard-configured assistant + if (import.meta.env.VITE_VAPI_ASSISTANT_ID) { + await vapi.start(import.meta.env.VITE_VAPI_ASSISTANT_ID); + } else { + // Option 2: Configure assistant directly in SDK + await vapi.start({ + model: { + provider: "openai", + model: "gpt-4o-2024-05-13", + messages: [ + { + role: "system", + content: "You are a helpful customer support assistant for TechCorp. You can help with order status, account questions, product information, and technical support. Be friendly, professional, and concise." + } + ] + }, + voice: { + provider: "11labs", + voiceId: "21m00Tcm4TlvDq8ikWAM", + }, + firstMessage: "Hi! I'm here to help with your TechCorp support needs. How can I assist you today?", + }); + } } }; @@ -156,7 +274,10 @@ slug: quickstart/web function App() { return (
-

Voice AI Demo

+

TechCorp Customer Support

+

+ Need help? Click the button below to speak with our AI support assistant. +

); @@ -180,7 +301,27 @@ slug: quickstart/web if (isActive) { vapi.stop(); } else { - await vapi.start('your_assistant_id'); + // Option 1: Use Dashboard-configured assistant + // await vapi.start('your_assistant_id'); + + // Option 2: Configure assistant directly in SDK + await vapi.start({ + model: { + provider: "openai", + model: "gpt-4o-2024-05-13", + messages: [ + { + role: "system", + content: "You are a helpful customer support assistant for TechCorp. You can help with order status, account questions, product information, and technical support. Be friendly, professional, and concise." + } + ] + }, + voice: { + provider: "11labs", + voiceId: "21m00Tcm4TlvDq8ikWAM", + }, + firstMessage: "Hi! I'm here to help with your TechCorp support needs. How can I assist you today?", + }); } }); @@ -197,9 +338,9 @@ slug: quickstart/web
-## Core Features +## Customize an Assistant -### Starting and Stopping Calls +### Start and Stop Calls Start voice conversations with your AI assistant using either a pre-configured assistant ID or inline configuration. You can customize the model, voice, and behavior on-the-fly. @@ -210,10 +351,10 @@ import { CreateAssistantDTO } from "@vapi-ai/web/dist/api"; // Initialize Vapi const vapi = new Vapi('pk_your_public_key'); -// Start a call with assistant ID +// Start a call with assistant ID (Dashboard configuration) await vapi.start('your_assistant_id'); -// Start with inline assistant config +// Start with inline assistant config (SDK configuration) const assistantConfig: CreateAssistantDTO = { model: { provider: "openai", @@ -221,7 +362,7 @@ const assistantConfig: CreateAssistantDTO = { messages: [ { role: "system", - content: "You are a helpful assistant." + content: "You are a helpful customer support assistant for TechCorp. You can help with order status, account questions, product information, and technical support. Be friendly, professional, and concise." } ] }, @@ -229,7 +370,7 @@ const assistantConfig: CreateAssistantDTO = { provider: "11labs", voiceId: "21m00Tcm4TlvDq8ikWAM", }, - firstMessage: "Hello! How can I help you today?", + firstMessage: "Hi! I'm here to help with your TechCorp support needs. How can I assist you today?", }; await vapi.start(assistantConfig); @@ -237,27 +378,27 @@ await vapi.start(assistantConfig); vapi.stop(); ``` -### Event Handling +### Handle Events Monitor call lifecycle, speech activity, and real-time transcription. These events help you build responsive UIs and handle call state changes. ```typescript // Call lifecycle events vapi.on('call-start', () => { - console.log('Call started'); + console.log('Customer support call started'); }); vapi.on('call-end', () => { - console.log('Call ended'); + console.log('Customer support call ended'); }); // Speech events vapi.on('speech-start', () => { - console.log('User started speaking'); + console.log('Customer started speaking'); }); vapi.on('speech-end', () => { - console.log('User stopped speaking'); + console.log('Customer stopped speaking'); }); // Message events @@ -276,34 +417,34 @@ vapi.on('error', (error) => { }); ``` -### Sending Messages +### Send Messages Inject context or trigger actions by sending messages to your assistant during an active call. Useful for providing real-time updates or user interface interactions. ```typescript -// Send a text message +// Send customer context when they log in vapi.send({ type: 'add-message', message: { role: 'system', - content: 'The user just clicked a button on the interface.' + content: 'Customer John Doe (ID: 12345) has logged in. Recent orders: #ORD-789, #ORD-456.' } }); -// Add tool call result +// Add tool call result for order lookup vapi.send({ type: 'add-message', message: { role: 'tool', content: { - name: 'getUserData', - parameters: { userId: '123' }, + name: 'getOrderStatus', + parameters: { orderId: 'ORD-789' }, } } }); ``` -### Mute Control +### Mute the Microphone Control microphone input during calls. Essential for privacy and managing when the assistant should listen to user speech. @@ -318,26 +459,26 @@ const isMuted = vapi.isMuted(); ### Assistant Overrides -Customize assistant behavior for specific calls without modifying your base assistant configuration in Vapi API or Vapi Dashboard. Override transcription settings, recording options, conversation flow, etc. +Customize assistant behavior for specific calls without modifying your base assistant configuration in Vapi Dashboard. Override transcription settings, recording options, conversation flow, etc. ```typescript const vapi = new Vapi('pk_your_key'); const overrides: OverrideAssistantDTO = { - // Assistant overrides - firstMessageMode: 'assistant-waits-for-user', // wait for user to speak first - recordingEnabled: false, // don't record the call + // Assistant overrides for customer support + firstMessageMode: 'assistant-waits-for-user', // wait for customer to speak first + recordingEnabled: true, // record calls for quality assurance - // use deepgram for transcription + // Use Deepgram for better customer service transcription transcriber: { provider: 'deepgram', model: 'nova-2', language: 'en-US' }, - // use custom summary prompt + // Custom summary for support tickets analysisPlan: { - summaryPrompt: 'Summarize the conversation in a few sentences.', + summaryPrompt: 'Summarize this customer support conversation including: customer issue, resolution provided, and any follow-up needed.', }, }; @@ -345,80 +486,13 @@ const overrides: OverrideAssistantDTO = { await vapi.start('your_assistant_id', overrides); ``` -### React Hook Example - -Simplify Vapi integration with a custom React hook that manages call state, conversation history, and common controls in a reusable way. - -```typescript title="hooks/useVapi.ts" -import { useState, useEffect, useCallback } from 'react'; -import Vapi from '@vapi-ai/web'; - -export function useVapi(apiKey: string) { - const [vapi] = useState(() => new Vapi(apiKey)); - const [isActive, setIsActive] = useState(false); - const [isMuted, setIsMuted] = useState(false); - const [volume, setVolume] = useState(0); - const [conversation, setConversation] = useState>([]); - - useEffect(() => { - vapi.on('call-start', () => setIsActive(true)); - vapi.on('call-end', () => setIsActive(false)); - vapi.on('volume-level', setVolume); - - vapi.on('message', (message) => { - if (message.type === 'transcript' && message.transcript) { - setConversation(prev => [...prev, { - role: message.transcript.role, - text: message.transcript.text, - timestamp: new Date().toISOString(), - }]); - } - }); - - return () => { - vapi.removeAllListeners(); - }; - }, [vapi]); - - const start = useCallback(async (assistantId: string) => { - setConversation([]); - await vapi.start(assistantId); - }, [vapi]); - - const stop = useCallback(() => { - vapi.stop(); - }, [vapi]); - - const toggleMute = useCallback(() => { - const newMuted = !isMuted; - vapi.setMuted(newMuted); - setIsMuted(newMuted); - }, [vapi, isMuted]); - - return { - vapi, - isActive, - isMuted, - volume, - conversation, - start, - stop, - toggleMute - }; -} -``` - -### Defining Custom Tools +### Add Custom Tools -Enable your assistant to call external functions and APIs with custom tools. +Enable your assistant to call external functions and APIs for order lookups, account management, and more. ```typescript -// Assistant with function calling -const assistantWithTools: CreateAssistantDTO = { +// Customer support assistant with function calling +const customerSupportAssistant: CreateAssistantDTO = { model: { provider: "openai", model: "gpt-4o-2024-05-13", @@ -426,43 +500,72 @@ const assistantWithTools: CreateAssistantDTO = { { type: "function", function: { - name: "get_weather", - description: "Get current weather for a location", + name: "get_order_status", + description: "Get the current status of a customer order", + parameters: { + type: "object", + properties: { + orderId: { + type: "string", + description: "The order ID to look up" + } + }, + required: ["orderId"] + } + } + }, + { + type: "function", + function: { + name: "get_account_info", + description: "Get customer account information", parameters: { type: "object", properties: { - location: { + customerId: { type: "string", - description: "City name" + description: "The customer ID" } }, - required: ["location"] + required: ["customerId"] } } } ], + messages: [ + { + role: "system", + content: "You are a helpful customer support assistant for TechCorp. You can help with order status, account questions, product information, and technical support. Use the available tools to look up specific information when customers provide order numbers or account details." + } + ] }, voice: { provider: "11labs", voiceId: "21m00Tcm4TlvDq8ikWAM", }, serverUrl: "https://your-domain.com/api/webhook", - firstMessage: "Hello! I can help you with weather information and more.", + firstMessage: "Hi! I'm here to help with your TechCorp support needs. I can look up order status, account information, and answer product questions. How can I assist you today?", }; -await vapi.start(assistantWithTools); +await vapi.start(customerSupportAssistant); ``` -### Video Recording +### Enable Video Recording -Capture video recordings of web-based voice calls. +Capture video recordings of customer support calls for compliance, training and quality assurance purposes. ```typescript -// Assistant with video recording enabled -const videoAssistant = { +// Customer support assistant with video recording enabled +const videoSupportAssistant = { model: { provider: "openai", model: "gpt-4o-2024-11-20", + messages: [ + { + role: "system", + content: "You are a helpful customer support assistant for TechCorp. This call is being recorded for quality assurance purposes." + } + ] }, voice: { provider: "11labs", @@ -472,10 +575,10 @@ const videoAssistant = { videoRecordingEnabled: true, recordingEnabled: true, }, - firstMessage: "Hello! This call is being recorded with video. How can I help?", + firstMessage: "Hi! I'm here to help with your TechCorp support needs. Please note this call is being recorded for quality assurance. How can I assist you today?", }; -await vapi.start(videoAssistant); +await vapi.start(videoSupportAssistant); ``` ## Next Steps From 275537784b1eefc53a757e51b1d36612bb070765 Mon Sep 17 00:00:00 2001 From: goosewin Date: Mon, 26 May 2025 16:14:56 -0700 Subject: [PATCH 07/12] feat: create dedicated `examples` page --- fern/examples.mdx | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 fern/examples.mdx diff --git a/fern/examples.mdx b/fern/examples.mdx new file mode 100644 index 00000000..480065e3 --- /dev/null +++ b/fern/examples.mdx @@ -0,0 +1,20 @@ +--- +title: Examples +subtitle: Explore complete examples with step-by-step instructions to build with Vapi +slug: examples +--- + + + + Create an outbound sales agent that can schedule appointments automatically + + + Build a technical support assistant that remembers where you left off between calls + + + Build a pizza ordering assistant for your website using the Web SDK + + + Easily integrate the Vapi Voice Widget into your website for enhanced user interaction + + From fc0e854fb7b640f75241872a00c0a7b3ace6a6eb Mon Sep 17 00:00:00 2001 From: goosewin Date: Mon, 26 May 2025 16:15:21 -0700 Subject: [PATCH 08/12] feat(web): add web sdk quickstart --- fern/quickstart/web.mdx | 570 ++++++++++++++++++++++++++++++++++------ 1 file changed, 488 insertions(+), 82 deletions(-) diff --git a/fern/quickstart/web.mdx b/fern/quickstart/web.mdx index 64f4a16a..d308e2dc 100644 --- a/fern/quickstart/web.mdx +++ b/fern/quickstart/web.mdx @@ -1,116 +1,522 @@ --- -title: Web call -subtitle: Make a web call to your assistant from a browser +title: Web SDK Quickstart +subtitle: Learn to build web applications with Vapi Web SDK in under 5 minutes. +slug: quickstart/web --- -## Overview +## Installation -This guide shows you how to integrate live, two-way voice calls with your Vapi assistant into any web app. You can use Vapi in plain JavaScript, React, Next.js, or any other web framework. + + + + + ```bash + npm install @vapi-ai/web + ``` + + + ```bash + yarn add @vapi-ai/web + ``` + + + ```bash + pnpm add @vapi-ai/web + ``` + + + ```bash + bun add @vapi-ai/web + ``` + + + -Get started with either the Vapi web SDK or by connecting to an assistant you created in the dashboard. + + You'll need your public API key and/or private API key from the [Dashboard → Vapi API Keys](https://dashboard.vapi.ai/org/api-keys). -See the full next.js [demo here on v0](https://v0.dev/chat/vapi-quickstart-nextjs-z3lv02T7Dd5). To try it live and make edits, follow these steps: + + Always use your **public key** (starts with `pk_`) in client-side code. Never expose your private key in the browser. + + -1. Fork the app in v0 -2. Go to settings --> environment variables -3. Create a new environment variable called `NEXT_PUBLIC_VAPI_API_KEY` -4. Add your [public api key from the dashboard](https://dashboard.vapi.ai/org/api-keys)! + + You'll need your assistant ID from the [Dashboard → Assistants](https://dashboard.vapi.ai/assistants). + + -## Installation +## Framework Examples - - ### Install the SDK - + + + + + ```env title=".env.local" + NEXT_PUBLIC_VAPI_API_KEY=pk_your_public_key_here + NEXT_PUBLIC_VAPI_ASSISTANT_ID=your_assistant_id_here + ``` + - ### Import the SDK - - + + ```typescript title="components/voice-button.tsx" + 'use client'; -## Get started + import Vapi from '@vapi-ai/web'; + import { useState } from 'react'; - - + export function VoiceButton() { + const [vapi] = useState(() => new Vapi(process.env.NEXT_PUBLIC_VAPI_API_KEY!)); + const [isActive, setIsActive] = useState(false); + + const toggleCall = async () => { + if (isActive) { + vapi.stop(); + } else { + await vapi.start(process.env.NEXT_PUBLIC_VAPI_ASSISTANT_ID!); + } + }; + + vapi.on('call-start', () => setIsActive(true)); + vapi.on('call-end', () => setIsActive(false)); + + return ( + + ); + } + ``` + + + + ```typescript title="app/page.tsx" + import { VoiceButton } from '@/components/voice-button'; + + export default function Home() { + return ( +
+

Voice AI Demo

+ +
+ ); + } + ``` +
+
+
+ + - - Create an assistant object. - - ```javascript - const assistantOptions = { - name: "Vapi's Pizza Front Desk", - firstMessage: "Vapi's Pizzeria speaking, how can I help you?", - transcriber: { - provider: "deepgram", - model: "nova-2", - language: "en-US", - }, - voice: { - provider: "playht", - voiceId: "jennifer", - }, - model: { - provider: "openai", - model: "gpt-4", - messages: [ - { - role: "system", - content: `You are a voice assistant for Vappy's Pizzeria, a pizza shop located on the Internet.\n\nYour job is to take the order of customers calling in. The menu has only 3 types of items: pizza, sides, and drinks. There are no other types of items on the menu.\n\n1) There are 3 kinds of pizza: cheese pizza, pepperoni pizza, and vegetarian pizza (often called \"veggie\" pizza).\n2) There are 3 kinds of sides: french fries, garlic bread, and chicken wings.\n3) There are 2 kinds of drinks: soda, and water. (if a customer asks for a brand name like \"coca cola\", just let them know that we only offer \"soda\")\n\nCustomers can only order 1 of each item. If a customer tries to order more than 1 item within each category, politely inform them that only 1 item per category may be ordered.\n\nCustomers must order 1 item from at least 1 category to have a complete order. They can order just a pizza, or just a side, or just a drink.\n\nBe sure to introduce the menu items, don't assume that the caller knows what is on the menu (most appropriate at the start of the conversation).\n\nIf the customer goes off-topic or off-track and talks about anything but the process of ordering, politely steer the conversation back to collecting their order.\n\nOnce you have all the information you need pertaining to their order, you can end the conversation. You can say something like \"Awesome, we'll have that ready for you in 10-20 minutes.\" to naturally let the customer know the order has been fully communicated.\n\nIt is important that you collect the order in an efficient manner (succinct replies & direct questions). You only have 1 task here, and it is to collect the customers order, then end the conversation.\n\n- Be sure to be kind of funny and witty!\n- Keep all your responses short and simple. Use casual language, phrases like \"Umm...\", \"Well...\", and \"I mean\" are preferred.\n- This is a voice conversation, so keep your responses short, like in a real conversation. Don't ramble for too long.`, - }, - ], - }, - }; + + ```env title=".env" + VITE_VAPI_API_KEY=pk_your_public_key_here + VITE_VAPI_ASSISTANT_ID=your_assistant_id_here ``` + + + + ```typescript title="components/VoiceButton.tsx" + import Vapi from '@vapi-ai/web'; + import { useState } from 'react'; - **Parameters:** - - `name` sets the display name for the assistant (internal use) - - `firstMessage` is the first message the assistant says - - `transcriber` selects the speech-to-text provider and model - - `voice` selects the text-to-speech provider and voice - - `model` sets the LLM provider, model, and system prompt + export function VoiceButton() { + const [vapi] = useState(() => new Vapi(import.meta.env.VITE_VAPI_API_KEY)); + const [isActive, setIsActive] = useState(false); + + const toggleCall = async () => { + if (isActive) { + vapi.stop(); + } else { + await vapi.start(import.meta.env.VITE_VAPI_ASSISTANT_ID); + } + }; + + vapi.on('call-start', () => setIsActive(true)); + vapi.on('call-end', () => setIsActive(false)); + + return ( + + ); + } + ``` - - Start a call using your assistant configuration. - ```javascript - vapi.start(assistantOptions); + + ```typescript title="src/App.tsx" + import { VoiceButton } from './components/VoiceButton'; + + function App() { + return ( +
+

Voice AI Demo

+ +
+ ); + } + + export default App; ```
- + + - - To create an assistant in the dashboard, follow the step-by-step guide in the [Dashboard Quickstart](https://docs.vapi.ai/quickstart/dashboard#get-started). + + ```env title=".env" + VITE_VAPI_API_KEY=pk_your_public_key_here + VITE_VAPI_ASSISTANT_ID=your_assistant_id_here + ``` - - Once you have your assistant's ID, you can start a call with it: - - Assistant ID in dashboard - + + ```vue title="src/components/VoiceButton.vue" + + + ``` - - To override assistant settings or set template variables, pass an `assistantOverrides` object as the second argument. - - ```javascript - const assistantOverrides = { - transcriber: { - provider: "deepgram", - model: "nova-2", - language: "en-US", - }, - recordingEnabled: false, - variableValues: { - name: "John", - }, + + + + + + + + + ```env title=".env" + VITE_VAPI_API_KEY=pk_your_public_key_here + VITE_VAPI_ASSISTANT_ID=your_assistant_id_here + ``` + + + + ```svelte title="src/lib/VoiceButton.svelte" + + + + ``` + + + + ```svelte title="src/routes/+page.svelte" + + +
+

Voice AI Demo

+ +
+ ``` +
+
+
+ + + + + ```env title=".env" + VITE_VAPI_API_KEY=pk_your_public_key_here + VITE_VAPI_ASSISTANT_ID=your_assistant_id_here + ``` + + + + ```svelte title="src/lib/VoiceButton.svelte" + + + + ``` + + + + ```svelte title="src/routes/+page.svelte" + + +
+

Voice AI Demo

+ +
+ ``` +
+
+
+
+
+ + + + + ```typescript title="src/environments/environment.ts" + export const environment = { + production: false, + vapiApiKey: 'pk_your_public_key_here', + vapiAssistantId: 'your_assistant_id_here' }; + ``` + + + + ```typescript title="src/app/voice-button/voice-button.component.ts" + import { Component, OnInit, OnDestroy } from '@angular/core'; + import Vapi from '@vapi-ai/web'; + import { environment } from '../../environments/environment'; + + @Component({ + selector: 'app-voice-button', + template: ` + + ` + }) + export class VoiceButtonComponent implements OnInit, OnDestroy { + isActive = false; + private vapi!: Vapi; + + ngOnInit() { + this.vapi = new Vapi(environment.vapiApiKey); + + this.vapi.on('call-start', () => { + this.isActive = true; + }); + + this.vapi.on('call-end', () => { + this.isActive = false; + }); + } + + ngOnDestroy() { + if (this.vapi) { + this.vapi.removeAllListeners(); + } + } - vapi.start("YOUR_ASSISTANT_ID_FROM_THE_DASHBOARD", assistantOverrides); + async toggleCall() { + if (this.isActive) { + this.vapi.stop(); + } else { + await this.vapi.start(environment.vapiAssistantId); + } + } + } + ``` + + + + ```typescript title="src/app/app.component.ts" + import { Component } from '@angular/core'; + + @Component({ + selector: 'app-root', + template: ` +
+

Voice AI Demo

+ +
+ ` + }) + export class AppComponent {} ```
+ + + ```javascript title="main.js" + import Vapi from '@vapi-ai/web'; + + const vapi = new Vapi('pk_your_public_key_here'); + const button = document.getElementById('voice-btn'); + let isActive = false; + + button.addEventListener('click', async () => { + if (isActive) { + vapi.stop(); + } else { + await vapi.start('your_assistant_id'); + } + }); + + vapi.on('call-start', () => { + isActive = true; + button.textContent = 'End Call'; + }); + + vapi.on('call-end', () => { + isActive = false; + button.textContent = 'Start Call'; + }); + ``` + + +## Basic Usage + +### Core Methods + +```typescript +// Initialize Vapi +const vapi = new Vapi('pk_your_public_key'); + +// Start a call +await vapi.start('your_assistant_id'); + +// End a call +vapi.stop(); + +// Listen to events +vapi.on('call-start', () => console.log('Call started')); +vapi.on('call-end', () => console.log('Call ended')); +vapi.on('message', (message) => console.log('Message:', message)); +``` + +### Assistant Configuration + +You can also pass an assistant configuration directly instead of using an ID: + +```typescript +const assistantConfig = { + model: { + provider: "openai", + model: "gpt-4o-2024-11-20", + }, + voice: { + provider: "11labs", + voiceId: "21m00Tcm4TlvDq8ikWAM", + }, + firstMessage: "Hello! How can I help you today?", + systemMessage: "You are a helpful assistant.", +}; + +await vapi.start(assistantConfig); +``` + +## Next Steps + + + + Complete Web SDK documentation + + + Complete API reference documentation + + + + + **Need help?** Join our [Discord community](https://discord.gg/vapi) or check out the [full documentation](/overview). + From 280b944755a9b6002f49b784585f41d7cc93c883 Mon Sep 17 00:00:00 2001 From: goosewin Date: Mon, 26 May 2025 16:15:37 -0700 Subject: [PATCH 09/12] chore(dashboard): update dashboard quickstart for consistency --- fern/quickstart/dashboard.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fern/quickstart/dashboard.mdx b/fern/quickstart/dashboard.mdx index d8a6022d..3068c1d0 100644 --- a/fern/quickstart/dashboard.mdx +++ b/fern/quickstart/dashboard.mdx @@ -1,6 +1,6 @@ --- title: Dashboard -subtitle: Learn to build a voice agent in under 5 minutes. +subtitle: Learn to build a voice agent in under 5 minutes using the Vapi dashboard. slug: quickstart/dashboard --- From c24d5f71d4c0a2b60bcd418a27d52625fc991a1e Mon Sep 17 00:00:00 2001 From: goosewin Date: Mon, 26 May 2025 16:15:44 -0700 Subject: [PATCH 10/12] chore: update navigation --- fern/docs.yml | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/fern/docs.yml b/fern/docs.yml index 87043c8f..d245e131 100644 --- a/fern/docs.yml +++ b/fern/docs.yml @@ -95,23 +95,15 @@ navigation: layout: - section: Get started contents: - - page: Quickstart - icon: fa-light fa-bolt-lightning + - page: Dashboard + icon: fa-light fa-table-columns path: quickstart/dashboard.mdx - - page: Make a web call - icon: fa-light fa-browser + - page: Web SDK + icon: fa-light fa-laptop-code path: quickstart/web.mdx - - section: How Vapi works - icon: fa-light fa-diagram-project - contents: - - page: Core models - path: quickstart.mdx - icon: fa-light fa-microchip-ai - - page: Orchestration models - icon: fa-light fa-network-wired - path: how-vapi-works.mdx - section: Examples icon: fa-light fa-code + path: examples.mdx contents: - page: Inbound support path: examples/inbound-support.mdx @@ -373,6 +365,15 @@ navigation: - page: FAQ path: faq.mdx icon: fa-light fa-question + - section: How Vapi works + icon: fa-light fa-diagram-project + contents: + - page: Core models + path: quickstart.mdx + icon: fa-light fa-microchip-ai + - page: Orchestration models + icon: fa-light fa-network-wired + path: how-vapi-works.mdx - section: Integrations collapsed: true icon: fa-light fa-link From 0f615c808a29c004feda3f0fd5badfef4a461d2c Mon Sep 17 00:00:00 2001 From: goosewin Date: Mon, 26 May 2025 20:06:28 -0700 Subject: [PATCH 11/12] feat(quickstart/web): remove less popular framework starters, expand on core features --- fern/quickstart/web.mdx | 536 +++++++++++++++++++--------------------- 1 file changed, 254 insertions(+), 282 deletions(-) diff --git a/fern/quickstart/web.mdx b/fern/quickstart/web.mdx index d308e2dc..f0e6d258 100644 --- a/fern/quickstart/web.mdx +++ b/fern/quickstart/web.mdx @@ -45,7 +45,7 @@ slug: quickstart/web -## Framework Examples +## Quick Start @@ -168,274 +168,6 @@ slug: quickstart/web - - - - ```env title=".env" - VITE_VAPI_API_KEY=pk_your_public_key_here - VITE_VAPI_ASSISTANT_ID=your_assistant_id_here - ``` - - - - ```vue title="src/components/VoiceButton.vue" - - - - ``` - - - - - - - - - - ```env title=".env" - VITE_VAPI_API_KEY=pk_your_public_key_here - VITE_VAPI_ASSISTANT_ID=your_assistant_id_here - ``` - - - - ```svelte title="src/lib/VoiceButton.svelte" - - - - ``` - - - - ```svelte title="src/routes/+page.svelte" - - -
-

Voice AI Demo

- -
- ``` -
-
-
- - - - - ```env title=".env" - VITE_VAPI_API_KEY=pk_your_public_key_here - VITE_VAPI_ASSISTANT_ID=your_assistant_id_here - ``` - - - - ```svelte title="src/lib/VoiceButton.svelte" - - - - ``` - - - - ```svelte title="src/routes/+page.svelte" - - -
-

Voice AI Demo

- -
- ``` -
-
-
-
-
- - - - - ```typescript title="src/environments/environment.ts" - export const environment = { - production: false, - vapiApiKey: 'pk_your_public_key_here', - vapiAssistantId: 'your_assistant_id_here' - }; - ``` - - - - ```typescript title="src/app/voice-button/voice-button.component.ts" - import { Component, OnInit, OnDestroy } from '@angular/core'; - import Vapi from '@vapi-ai/web'; - import { environment } from '../../environments/environment'; - - @Component({ - selector: 'app-voice-button', - template: ` - - ` - }) - export class VoiceButtonComponent implements OnInit, OnDestroy { - isActive = false; - private vapi!: Vapi; - - ngOnInit() { - this.vapi = new Vapi(environment.vapiApiKey); - - this.vapi.on('call-start', () => { - this.isActive = true; - }); - - this.vapi.on('call-end', () => { - this.isActive = false; - }); - } - - ngOnDestroy() { - if (this.vapi) { - this.vapi.removeAllListeners(); - } - } - - async toggleCall() { - if (this.isActive) { - this.vapi.stop(); - } else { - await this.vapi.start(environment.vapiAssistantId); - } - } - } - ``` - - - - ```typescript title="src/app/app.component.ts" - import { Component } from '@angular/core'; - - @Component({ - selector: 'app-root', - template: ` -
-

Voice AI Demo

- -
- ` - }) - export class AppComponent {} - ``` -
-
-
- ```javascript title="main.js" import Vapi from '@vapi-ai/web'; @@ -465,32 +197,269 @@ slug: quickstart/web
-## Basic Usage +## Core Features -### Core Methods +### Starting and Stopping Calls + +Start voice conversations with your AI assistant using either a pre-configured assistant ID or inline configuration. You can customize the model, voice, and behavior on-the-fly. ```typescript +import Vapi from "@vapi-ai/web"; +import { CreateAssistantDTO } from "@vapi-ai/web/dist/api"; + // Initialize Vapi const vapi = new Vapi('pk_your_public_key'); -// Start a call +// Start a call with assistant ID await vapi.start('your_assistant_id'); +// Start with inline assistant config +const assistantConfig: CreateAssistantDTO = { + model: { + provider: "openai", + model: "gpt-4o-2024-05-13", + messages: [ + { + role: "system", + content: "You are a helpful assistant." + } + ] + }, + voice: { + provider: "11labs", + voiceId: "21m00Tcm4TlvDq8ikWAM", + }, + firstMessage: "Hello! How can I help you today?", +}; +await vapi.start(assistantConfig); + // End a call vapi.stop(); +``` + +### Event Handling + +Monitor call lifecycle, speech activity, and real-time transcription. These events help you build responsive UIs and handle call state changes. + +```typescript +// Call lifecycle events +vapi.on('call-start', () => { + console.log('Call started'); +}); + +vapi.on('call-end', () => { + console.log('Call ended'); +}); + +// Speech events +vapi.on('speech-start', () => { + console.log('User started speaking'); +}); + +vapi.on('speech-end', () => { + console.log('User stopped speaking'); +}); + +// Message events +vapi.on('message', (message) => { + console.log('Received message:', message); +}); + +// Volume level (for visualizations) +vapi.on('volume-level', (level) => { + console.log('Volume level:', level); +}); + +// Error handling +vapi.on('error', (error) => { + console.error('Call error:', error); +}); +``` + +### Sending Messages + +Inject context or trigger actions by sending messages to your assistant during an active call. Useful for providing real-time updates or user interface interactions. + +```typescript +// Send a text message +vapi.send({ + type: 'add-message', + message: { + role: 'system', + content: 'The user just clicked a button on the interface.' + } +}); + +// Add tool call result +vapi.send({ + type: 'add-message', + message: { + role: 'tool', + content: { + name: 'getUserData', + parameters: { userId: '123' }, + } + } +}); +``` + +### Mute Control + +Control microphone input during calls. Essential for privacy and managing when the assistant should listen to user speech. + +```typescript +// Mute/unmute the microphone +vapi.setMuted(true); // Mute +vapi.setMuted(false); // Unmute + +// Check if muted +const isMuted = vapi.isMuted(); +``` + +### Assistant Overrides + +Customize assistant behavior for specific calls without modifying your base assistant configuration in Vapi API or Vapi Dashboard. Override transcription settings, recording options, conversation flow, etc. -// Listen to events -vapi.on('call-start', () => console.log('Call started')); -vapi.on('call-end', () => console.log('Call ended')); -vapi.on('message', (message) => console.log('Message:', message)); +```typescript +const vapi = new Vapi('pk_your_key'); + +const overrides: OverrideAssistantDTO = { + // Assistant overrides + firstMessageMode: 'assistant-waits-for-user', // wait for user to speak first + recordingEnabled: false, // don't record the call + + // use deepgram for transcription + transcriber: { + provider: 'deepgram', + model: 'nova-2', + language: 'en-US' + }, + + // use custom summary prompt + analysisPlan: { + summaryPrompt: 'Summarize the conversation in a few sentences.', + }, +}; + +// Start call with overrides +await vapi.start('your_assistant_id', overrides); ``` -### Assistant Configuration +### React Hook Example + +Simplify Vapi integration with a custom React hook that manages call state, conversation history, and common controls in a reusable way. + +```typescript title="hooks/useVapi.ts" +import { useState, useEffect, useCallback } from 'react'; +import Vapi from '@vapi-ai/web'; + +export function useVapi(apiKey: string) { + const [vapi] = useState(() => new Vapi(apiKey)); + const [isActive, setIsActive] = useState(false); + const [isMuted, setIsMuted] = useState(false); + const [volume, setVolume] = useState(0); + const [conversation, setConversation] = useState>([]); + + useEffect(() => { + vapi.on('call-start', () => setIsActive(true)); + vapi.on('call-end', () => setIsActive(false)); + vapi.on('volume-level', setVolume); + + vapi.on('message', (message) => { + if (message.type === 'transcript' && message.transcript) { + setConversation(prev => [...prev, { + role: message.transcript.role, + text: message.transcript.text, + timestamp: new Date().toISOString(), + }]); + } + }); -You can also pass an assistant configuration directly instead of using an ID: + return () => { + vapi.removeAllListeners(); + }; + }, [vapi]); + + const start = useCallback(async (assistantId: string) => { + setConversation([]); + await vapi.start(assistantId); + }, [vapi]); + + const stop = useCallback(() => { + vapi.stop(); + }, [vapi]); + + const toggleMute = useCallback(() => { + const newMuted = !isMuted; + vapi.setMuted(newMuted); + setIsMuted(newMuted); + }, [vapi, isMuted]); + + return { + vapi, + isActive, + isMuted, + volume, + conversation, + start, + stop, + toggleMute + }; +} +``` + +### Defining Custom Tools + +Enable your assistant to call external functions and APIs with custom tools. ```typescript -const assistantConfig = { +// Assistant with function calling +const assistantWithTools: CreateAssistantDTO = { + model: { + provider: "openai", + model: "gpt-4o-2024-05-13", + tools: [ + { + type: "function", + function: { + name: "get_weather", + description: "Get current weather for a location", + parameters: { + type: "object", + properties: { + location: { + type: "string", + description: "City name" + } + }, + required: ["location"] + } + } + } + ], + }, + voice: { + provider: "11labs", + voiceId: "21m00Tcm4TlvDq8ikWAM", + }, + serverUrl: "https://your-domain.com/api/webhook", + firstMessage: "Hello! I can help you with weather information and more.", +}; + +await vapi.start(assistantWithTools); +``` + +### Video Recording + +Capture video recordings of web-based voice calls. + +```typescript +// Assistant with video recording enabled +const videoAssistant = { model: { provider: "openai", model: "gpt-4o-2024-11-20", @@ -499,11 +468,14 @@ const assistantConfig = { provider: "11labs", voiceId: "21m00Tcm4TlvDq8ikWAM", }, - firstMessage: "Hello! How can I help you today?", - systemMessage: "You are a helpful assistant.", + artifactPlan: { + videoRecordingEnabled: true, + recordingEnabled: true, + }, + firstMessage: "Hello! This call is being recorded with video. How can I help?", }; -await vapi.start(assistantConfig); +await vapi.start(videoAssistant); ``` ## Next Steps From f77704c2ddaa1c5eeaf06b68c204e0d426ed25d0 Mon Sep 17 00:00:00 2001 From: goosewin Date: Tue, 27 May 2025 10:31:04 -0700 Subject: [PATCH 12/12] chore(quickstart/web): address PR feedback --- fern/quickstart/web.mdx | 341 ++++++++++++++++++++++++++-------------- 1 file changed, 222 insertions(+), 119 deletions(-) diff --git a/fern/quickstart/web.mdx b/fern/quickstart/web.mdx index f0e6d258..14c73e40 100644 --- a/fern/quickstart/web.mdx +++ b/fern/quickstart/web.mdx @@ -1,9 +1,62 @@ --- title: Web SDK Quickstart -subtitle: Learn to build web applications with Vapi Web SDK in under 5 minutes. +subtitle: Build a customer support voice assistant in under 5 minutes using Vapi Web SDK. slug: quickstart/web --- +In this quickstart, we'll build a **customer support voice assistant** that can help users with order inquiries, account questions, and general support. You'll learn how to integrate Vapi's Web SDK and see both ways to configure your assistant. + +## Ways to Configure Assistant + +With Vapi, you have flexibility in how you configure your assistant: + + + + Dashboard Configuration + + Recommended for production + + + } icon="dashboard"> + + Configure your assistant in the [Vapi Dashboard](https://dashboard.vapi.ai/assistants). Your configuration is stored securely and pulled automatically when you provide the assistant ID. + + + SDK Configuration + + Great for customization + + + } icon="code"> + + Pass configuration directly to the Web SDK. You can override existing assistants or create entirely new ones programmatically based on your app logic. + + + +Instructions below are going to primarily focus on configuring the assistant via the Web SDK. + ## Installation @@ -33,19 +86,35 @@ slug: quickstart/web - You'll need your public API key and/or private API key from the [Dashboard → Vapi API Keys](https://dashboard.vapi.ai/org/api-keys). + You'll need your public API key from the [Dashboard → Vapi API Keys](https://dashboard.vapi.ai/org/api-keys). Always use your **public key** (starts with `pk_`) in client-side code. Never expose your private key in the browser. - - You'll need your assistant ID from the [Dashboard → Assistants](https://dashboard.vapi.ai/assistants). + + **Option 1: Dashboard Configuration** + + Create an assistant in the [Dashboard → Assistants](https://dashboard.vapi.ai/assistants) with this system prompt: + + ``` + You are a helpful customer support assistant for TechCorp. You can help with: + - Order status and tracking + - Account questions + - Product information + - Technical support + + Be friendly, professional, and concise. If you need to look up specific information, ask for order numbers or account details. + ``` + + **Option 2: SDK Configuration** + + We'll show you how to configure the assistant directly in code below. -## Quick Start +## Build an Assistant @@ -53,6 +122,7 @@ slug: quickstart/web ```env title=".env.local" NEXT_PUBLIC_VAPI_API_KEY=pk_your_public_key_here + # Only needed if using Dashboard configuration NEXT_PUBLIC_VAPI_ASSISTANT_ID=your_assistant_id_here ``` @@ -72,7 +142,29 @@ slug: quickstart/web if (isActive) { vapi.stop(); } else { - await vapi.start(process.env.NEXT_PUBLIC_VAPI_ASSISTANT_ID!); + // Option 1: Use Dashboard-configured assistant + if (process.env.NEXT_PUBLIC_VAPI_ASSISTANT_ID) { + await vapi.start(process.env.NEXT_PUBLIC_VAPI_ASSISTANT_ID); + } else { + // Option 2: Configure assistant directly in SDK + await vapi.start({ + model: { + provider: "openai", + model: "gpt-4o-2024-05-13", + messages: [ + { + role: "system", + content: "You are a helpful customer support assistant for TechCorp. You can help with order status, account questions, product information, and technical support. Be friendly, professional, and concise." + } + ] + }, + voice: { + provider: "11labs", + voiceId: "21m00Tcm4TlvDq8ikWAM", + }, + firstMessage: "Hi! I'm here to help with your TechCorp support needs. How can I assist you today?", + }); + } } }; @@ -98,7 +190,10 @@ slug: quickstart/web export default function Home() { return (
-

Voice AI Demo

+

TechCorp Customer Support

+

+ Need help? Click the button below to speak with our AI support assistant. +

); @@ -113,6 +208,7 @@ slug: quickstart/web ```env title=".env" VITE_VAPI_API_KEY=pk_your_public_key_here + # Only needed if using Dashboard configuration VITE_VAPI_ASSISTANT_ID=your_assistant_id_here ``` @@ -130,7 +226,29 @@ slug: quickstart/web if (isActive) { vapi.stop(); } else { - await vapi.start(import.meta.env.VITE_VAPI_ASSISTANT_ID); + // Option 1: Use Dashboard-configured assistant + if (import.meta.env.VITE_VAPI_ASSISTANT_ID) { + await vapi.start(import.meta.env.VITE_VAPI_ASSISTANT_ID); + } else { + // Option 2: Configure assistant directly in SDK + await vapi.start({ + model: { + provider: "openai", + model: "gpt-4o-2024-05-13", + messages: [ + { + role: "system", + content: "You are a helpful customer support assistant for TechCorp. You can help with order status, account questions, product information, and technical support. Be friendly, professional, and concise." + } + ] + }, + voice: { + provider: "11labs", + voiceId: "21m00Tcm4TlvDq8ikWAM", + }, + firstMessage: "Hi! I'm here to help with your TechCorp support needs. How can I assist you today?", + }); + } } }; @@ -156,7 +274,10 @@ slug: quickstart/web function App() { return (
-

Voice AI Demo

+

TechCorp Customer Support

+

+ Need help? Click the button below to speak with our AI support assistant. +

); @@ -180,7 +301,27 @@ slug: quickstart/web if (isActive) { vapi.stop(); } else { - await vapi.start('your_assistant_id'); + // Option 1: Use Dashboard-configured assistant + // await vapi.start('your_assistant_id'); + + // Option 2: Configure assistant directly in SDK + await vapi.start({ + model: { + provider: "openai", + model: "gpt-4o-2024-05-13", + messages: [ + { + role: "system", + content: "You are a helpful customer support assistant for TechCorp. You can help with order status, account questions, product information, and technical support. Be friendly, professional, and concise." + } + ] + }, + voice: { + provider: "11labs", + voiceId: "21m00Tcm4TlvDq8ikWAM", + }, + firstMessage: "Hi! I'm here to help with your TechCorp support needs. How can I assist you today?", + }); } }); @@ -197,9 +338,9 @@ slug: quickstart/web
-## Core Features +## Customize an Assistant -### Starting and Stopping Calls +### Start and Stop Calls Start voice conversations with your AI assistant using either a pre-configured assistant ID or inline configuration. You can customize the model, voice, and behavior on-the-fly. @@ -210,10 +351,10 @@ import { CreateAssistantDTO } from "@vapi-ai/web/dist/api"; // Initialize Vapi const vapi = new Vapi('pk_your_public_key'); -// Start a call with assistant ID +// Start a call with assistant ID (Dashboard configuration) await vapi.start('your_assistant_id'); -// Start with inline assistant config +// Start with inline assistant config (SDK configuration) const assistantConfig: CreateAssistantDTO = { model: { provider: "openai", @@ -221,7 +362,7 @@ const assistantConfig: CreateAssistantDTO = { messages: [ { role: "system", - content: "You are a helpful assistant." + content: "You are a helpful customer support assistant for TechCorp. You can help with order status, account questions, product information, and technical support. Be friendly, professional, and concise." } ] }, @@ -229,7 +370,7 @@ const assistantConfig: CreateAssistantDTO = { provider: "11labs", voiceId: "21m00Tcm4TlvDq8ikWAM", }, - firstMessage: "Hello! How can I help you today?", + firstMessage: "Hi! I'm here to help with your TechCorp support needs. How can I assist you today?", }; await vapi.start(assistantConfig); @@ -237,27 +378,27 @@ await vapi.start(assistantConfig); vapi.stop(); ``` -### Event Handling +### Handle Events Monitor call lifecycle, speech activity, and real-time transcription. These events help you build responsive UIs and handle call state changes. ```typescript // Call lifecycle events vapi.on('call-start', () => { - console.log('Call started'); + console.log('Customer support call started'); }); vapi.on('call-end', () => { - console.log('Call ended'); + console.log('Customer support call ended'); }); // Speech events vapi.on('speech-start', () => { - console.log('User started speaking'); + console.log('Customer started speaking'); }); vapi.on('speech-end', () => { - console.log('User stopped speaking'); + console.log('Customer stopped speaking'); }); // Message events @@ -276,34 +417,34 @@ vapi.on('error', (error) => { }); ``` -### Sending Messages +### Send Messages Inject context or trigger actions by sending messages to your assistant during an active call. Useful for providing real-time updates or user interface interactions. ```typescript -// Send a text message +// Send customer context when they log in vapi.send({ type: 'add-message', message: { role: 'system', - content: 'The user just clicked a button on the interface.' + content: 'Customer John Doe (ID: 12345) has logged in. Recent orders: #ORD-789, #ORD-456.' } }); -// Add tool call result +// Add tool call result for order lookup vapi.send({ type: 'add-message', message: { role: 'tool', content: { - name: 'getUserData', - parameters: { userId: '123' }, + name: 'getOrderStatus', + parameters: { orderId: 'ORD-789' }, } } }); ``` -### Mute Control +### Mute the Microphone Control microphone input during calls. Essential for privacy and managing when the assistant should listen to user speech. @@ -318,26 +459,26 @@ const isMuted = vapi.isMuted(); ### Assistant Overrides -Customize assistant behavior for specific calls without modifying your base assistant configuration in Vapi API or Vapi Dashboard. Override transcription settings, recording options, conversation flow, etc. +Customize assistant behavior for specific calls without modifying your base assistant configuration in Vapi Dashboard. Override transcription settings, recording options, conversation flow, etc. ```typescript const vapi = new Vapi('pk_your_key'); const overrides: OverrideAssistantDTO = { - // Assistant overrides - firstMessageMode: 'assistant-waits-for-user', // wait for user to speak first - recordingEnabled: false, // don't record the call + // Assistant overrides for customer support + firstMessageMode: 'assistant-waits-for-user', // wait for customer to speak first + recordingEnabled: true, // record calls for quality assurance - // use deepgram for transcription + // Use Deepgram for better customer service transcription transcriber: { provider: 'deepgram', model: 'nova-2', language: 'en-US' }, - // use custom summary prompt + // Custom summary for support tickets analysisPlan: { - summaryPrompt: 'Summarize the conversation in a few sentences.', + summaryPrompt: 'Summarize this customer support conversation including: customer issue, resolution provided, and any follow-up needed.', }, }; @@ -345,80 +486,13 @@ const overrides: OverrideAssistantDTO = { await vapi.start('your_assistant_id', overrides); ``` -### React Hook Example - -Simplify Vapi integration with a custom React hook that manages call state, conversation history, and common controls in a reusable way. - -```typescript title="hooks/useVapi.ts" -import { useState, useEffect, useCallback } from 'react'; -import Vapi from '@vapi-ai/web'; - -export function useVapi(apiKey: string) { - const [vapi] = useState(() => new Vapi(apiKey)); - const [isActive, setIsActive] = useState(false); - const [isMuted, setIsMuted] = useState(false); - const [volume, setVolume] = useState(0); - const [conversation, setConversation] = useState>([]); - - useEffect(() => { - vapi.on('call-start', () => setIsActive(true)); - vapi.on('call-end', () => setIsActive(false)); - vapi.on('volume-level', setVolume); - - vapi.on('message', (message) => { - if (message.type === 'transcript' && message.transcript) { - setConversation(prev => [...prev, { - role: message.transcript.role, - text: message.transcript.text, - timestamp: new Date().toISOString(), - }]); - } - }); - - return () => { - vapi.removeAllListeners(); - }; - }, [vapi]); - - const start = useCallback(async (assistantId: string) => { - setConversation([]); - await vapi.start(assistantId); - }, [vapi]); - - const stop = useCallback(() => { - vapi.stop(); - }, [vapi]); - - const toggleMute = useCallback(() => { - const newMuted = !isMuted; - vapi.setMuted(newMuted); - setIsMuted(newMuted); - }, [vapi, isMuted]); - - return { - vapi, - isActive, - isMuted, - volume, - conversation, - start, - stop, - toggleMute - }; -} -``` - -### Defining Custom Tools +### Add Custom Tools -Enable your assistant to call external functions and APIs with custom tools. +Enable your assistant to call external functions and APIs for order lookups, account management, and more. ```typescript -// Assistant with function calling -const assistantWithTools: CreateAssistantDTO = { +// Customer support assistant with function calling +const customerSupportAssistant: CreateAssistantDTO = { model: { provider: "openai", model: "gpt-4o-2024-05-13", @@ -426,43 +500,72 @@ const assistantWithTools: CreateAssistantDTO = { { type: "function", function: { - name: "get_weather", - description: "Get current weather for a location", + name: "get_order_status", + description: "Get the current status of a customer order", + parameters: { + type: "object", + properties: { + orderId: { + type: "string", + description: "The order ID to look up" + } + }, + required: ["orderId"] + } + } + }, + { + type: "function", + function: { + name: "get_account_info", + description: "Get customer account information", parameters: { type: "object", properties: { - location: { + customerId: { type: "string", - description: "City name" + description: "The customer ID" } }, - required: ["location"] + required: ["customerId"] } } } ], + messages: [ + { + role: "system", + content: "You are a helpful customer support assistant for TechCorp. You can help with order status, account questions, product information, and technical support. Use the available tools to look up specific information when customers provide order numbers or account details." + } + ] }, voice: { provider: "11labs", voiceId: "21m00Tcm4TlvDq8ikWAM", }, serverUrl: "https://your-domain.com/api/webhook", - firstMessage: "Hello! I can help you with weather information and more.", + firstMessage: "Hi! I'm here to help with your TechCorp support needs. I can look up order status, account information, and answer product questions. How can I assist you today?", }; -await vapi.start(assistantWithTools); +await vapi.start(customerSupportAssistant); ``` -### Video Recording +### Enable Video Recording -Capture video recordings of web-based voice calls. +Capture video recordings of customer support calls for compliance, training and quality assurance purposes. ```typescript -// Assistant with video recording enabled -const videoAssistant = { +// Customer support assistant with video recording enabled +const videoSupportAssistant = { model: { provider: "openai", model: "gpt-4o-2024-11-20", + messages: [ + { + role: "system", + content: "You are a helpful customer support assistant for TechCorp. This call is being recorded for quality assurance purposes." + } + ] }, voice: { provider: "11labs", @@ -472,10 +575,10 @@ const videoAssistant = { videoRecordingEnabled: true, recordingEnabled: true, }, - firstMessage: "Hello! This call is being recorded with video. How can I help?", + firstMessage: "Hi! I'm here to help with your TechCorp support needs. Please note this call is being recorded for quality assurance. How can I assist you today?", }; -await vapi.start(videoAssistant); +await vapi.start(videoSupportAssistant); ``` ## Next Steps