> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://docs.vapi.ai/assistants/examples/inbound-support/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.vapi.ai/_mcp/server. # Inbound customer support > Build a Vapi inbound support demo with a Query tool and sample CSV files, then configure prompts and test account, balance, and transaction retrieval. > **Warning** > > Use only the supplied sample data or other fictional records. Matching a name and phone digits is not identity verification, and this example does not enforce account-level authorization. ## Overview A [Query tool](/knowledge-base/using-query-tool) retrieves information from uploaded files. In this demo, one Query tool uses both CSV files to answer questions about sample accounts, balances, and transactions. You don't need a custom server or a `tool-calls` webhook handler. **Demo capabilities:** * Find a sample account by name and the last four phone digits. * Read a balance and summarize transactions from the uploaded files. **What you'll build:** * One Query tool with a knowledge base containing both CSV files. * An assistant and inbound phone number for testing the support conversation. ## Prerequisites * A [Vapi account](https://dashboard.vapi.ai/). * A Vapi private API key for the API examples. Set the `VAPI_API_KEY` environment variable to this key. Run the examples on your server or local machine, not in browser code. * Install `@vapi-ai/server-sdk` version 2.0.1 for TypeScript or the `requests` package for Python. The cURL model-update examples also use `jq`. Replace `YOUR_ASSISTANT_ID` and the file and tool ID placeholders with IDs from your Vapi account. ## Scenario VapiBank is a fictional bank. The CSV files are a fixed snapshot for this demo, not a connection to live banking data. --- ## 1. Upload the sample files #### Download the spreadsheets Download accounts.csv Download transactions.csv #### Upload the files #### Dashboard 1. Navigate to **Files** in your [Vapi Dashboard](https://dashboard.vapi.ai/). 2. Click **Choose file** and upload both `accounts.csv` and `transactions.csv`. 3. Note the file IDs for use in creating the Query tool. #### TypeScript (Server SDK) ```typescript import { VapiClient } from "@vapi-ai/server-sdk"; import fs from 'fs'; const apiKey = process.env.VAPI_API_KEY; if (!apiKey) throw new Error("Set VAPI_API_KEY to your Vapi private API key"); const vapi = new VapiClient({ token: apiKey }); async function uploadFile(filePath: string) { try { const file = await vapi.files.create({ file: fs.createReadStream(filePath) }); console.log(`File ${filePath} uploaded with ID: ${file.id}`); return file; } catch (error) { console.error(`Error uploading file ${filePath}:`, error); throw error; } } // Upload both files const accountsFile = await uploadFile("accounts.csv"); const transactionsFile = await uploadFile("transactions.csv"); console.log(`Accounts file ID: ${accountsFile.id}`); console.log(`Transactions file ID: ${transactionsFile.id}`); ``` #### Python (HTTP API) ```python import os import requests def upload_file(file_path): url = "https://api.vapi.ai/file" headers = {"Authorization": f"Bearer {os.environ['VAPI_API_KEY']}"} with open(file_path, 'rb') as file: files = {'file': file} response = requests.post(url, headers=headers, files=files, timeout=30) response.raise_for_status() return response.json() # Upload both files accounts_file = upload_file("accounts.csv") transactions_file = upload_file("transactions.csv") print(f"Accounts file ID: {accounts_file['id']}") print(f"Transactions file ID: {transactions_file['id']}") ``` #### cURL ```bash # Upload accounts.csv curl --fail -X POST https://api.vapi.ai/file \ -H "Authorization: Bearer $VAPI_API_KEY" \ -F "file=@accounts.csv" # Upload transactions.csv curl --fail -X POST https://api.vapi.ai/file \ -H "Authorization: Bearer $VAPI_API_KEY" \ -F "file=@transactions.csv" ``` --- ## 2. Create an Assistant #### Dashboard #### Navigate to Assistants Go to [dashboard.vapi.ai](https://dashboard.vapi.ai) and click `Assistants` in the left sidebar. #### Create a new assistant * Click `Create Assistant`. * Select `Blank Template` as your starting point. * Change assistant name to `Tom`. #### TypeScript (Server SDK) ```typescript import { VapiClient } from "@vapi-ai/server-sdk"; const apiKey = process.env.VAPI_API_KEY; if (!apiKey) throw new Error("Set VAPI_API_KEY to your Vapi private API key"); const vapi = new VapiClient({ token: apiKey }); const systemPrompt = `You are Tom, a friendly VapiBank customer support assistant. Help callers explore sample balances and transactions. Use fictional records only; do not treat a name or phone digits as identity verification.`; const assistant = await vapi.assistants.create({ name: "Tom", firstMessage: "Hello, you've reached VapiBank customer support! My name is Tom, how may I assist you today?", model: { provider: "openai", model: "gpt-4o", messages: [ { role: "system", content: systemPrompt } ] }, voice: { provider: "11labs", voiceId: "burt" } }); console.log(`Assistant created with ID: ${assistant.id}`); ``` #### Python (HTTP API) ```python import os import requests url = "https://api.vapi.ai/assistant" headers = { "Authorization": f"Bearer {os.environ['VAPI_API_KEY']}", "Content-Type": "application/json" } system_prompt = "You are Tom, a friendly VapiBank customer support assistant. Help callers explore sample balances and transactions. Use fictional records only; do not treat a name or phone digits as identity verification." data = { "name": "Tom", "firstMessage": "Hello, you've reached VapiBank customer support! My name is Tom, how may I assist you today?", "model": { "provider": "openai", "model": "gpt-4o", "messages": [ { "role": "system", "content": system_prompt } ] }, "voice": { "provider": "11labs", "voiceId": "burt" } } response = requests.post(url, headers=headers, json=data, timeout=30) response.raise_for_status() assistant = response.json() print(f"Assistant created with ID: {assistant['id']}") ``` #### cURL ```bash curl --fail -X POST https://api.vapi.ai/assistant \ -H "Authorization: Bearer $VAPI_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Tom", "firstMessage": "Hello, you'\''ve reached VapiBank customer support! My name is Tom, how may I assist you today?", "model": { "provider": "openai", "model": "gpt-4o", "messages": [ { "role": "system", "content": "You are Tom, a friendly VapiBank customer support assistant. Help callers explore sample balances and transactions. Use fictional records only; do not treat a name or phone digits as identity verification." } ] }, "voice": { "provider": "11labs", "voiceId": "burt" } }' ``` --- ## 3. Configure an Assistant #### Update the introduction message #### Dashboard Update `First Message` to: **`First Message`** ```txt title="First Message" wordWrap Hello, you've reached VapiBank customer support! My name is Tom, how may I assist you today? ``` #### TypeScript (Server SDK) ```typescript import { VapiClient } from "@vapi-ai/server-sdk"; const apiKey = process.env.VAPI_API_KEY; if (!apiKey) throw new Error("Set VAPI_API_KEY to your Vapi private API key"); const vapi = new VapiClient({ token: apiKey }); const updatedAssistant = await vapi.assistants.update({ id: "YOUR_ASSISTANT_ID", firstMessage: "Hello, you've reached VapiBank customer support! My name is Tom, how may I assist you today?" }); console.log("First message updated successfully"); ``` #### Python (HTTP API) ```python import os import requests url = "https://api.vapi.ai/assistant/YOUR_ASSISTANT_ID" headers = { "Authorization": f"Bearer {os.environ['VAPI_API_KEY']}", "Content-Type": "application/json" } data = { "firstMessage": "Hello, you've reached VapiBank customer support! My name is Tom, how may I assist you today?" } response = requests.patch(url, headers=headers, json=data, timeout=30) response.raise_for_status() assistant = response.json() print("First message updated successfully") ``` #### cURL ```bash curl --fail -X PATCH https://api.vapi.ai/assistant/YOUR_ASSISTANT_ID \ -H "Authorization: Bearer $VAPI_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "firstMessage": "Hello, you'\''ve reached VapiBank customer support! My name is Tom, how may I assist you today?" }' ``` #### Update the system prompt First, create this system prompt: **`System Prompt`** ```txt title="System Prompt" maxLines=10 # VapiBank - Phone Support Demo ## Identity and purpose You are Tom, a friendly VapiBank support assistant in a demo with fictional data. Do not introduce yourself again after the first message. Help callers find a sample account, read its stored balance, and review its transactions. ## Data and tool Use defaultQueryTool with knowledgeBaseNames set to ["bank_records"] before answering a question about account data. The bank_records knowledge base contains both accounts.csv and transactions.csv. accounts.csv contains account_id, name, phone_last4, balance, card_status, and email. transactions.csv contains account_id, date, description, and amount. These files are a snapshot, not live banking data. Never describe a returned balance as a live balance. ## Conversation flow 1. Ask for the name on the sample account and the last four phone digits. Ask one question at a time. 2. Call defaultQueryTool to find a sample account matching both values. 3. Use only a returned account whose name and phone_last4 match the supplied details. If the result is missing, ambiguous, or mismatched, ask for clarification. Do not guess or disclose another record. 4. For a balance question, call defaultQueryTool and report the matching account's balance from the file. 5. For a transaction question, call defaultQueryTool and use only transactions with the matching account_id. Summarize up to three returned transactions, newest date first. Do not invent missing transactions. 6. If the caller changes the account details, repeat the lookup and ignore results for the previous account. 7. When finished, ask whether the caller needs anything else, then thank them and say goodbye. ## Limits and failures This lookup does not authenticate the caller or authorize access to real accounts. If a lookup fails or the result is unclear, say that you could not retrieve the requested information. Do not interpret a failed lookup as a zero balance or no transactions. Do not claim to transfer the call, arrange a callback, change an account, or move money. Those actions are not configured. ## Style Be warm and concise. Aim for no more than 30 words per reply. Read important numbers slowly and clearly. ``` Then update your assistant. In the TypeScript and Python examples, replace the abbreviated prompt with the complete prompt above. When updating `model` through the API, retrieve its current configuration first and preserve the fields you are not changing: #### Dashboard Copy the system prompt above and paste it into the `System Prompt` field in your assistant configuration. #### TypeScript (Server SDK) ```typescript import { VapiClient } from "@vapi-ai/server-sdk"; const apiKey = process.env.VAPI_API_KEY; if (!apiKey) throw new Error("Set VAPI_API_KEY to your Vapi private API key"); const vapi = new VapiClient({ token: apiKey }); // Use the system prompt from above const systemPrompt = `# VapiBank - Phone Support Demo...`; const assistant = await vapi.assistants.get({ id: "YOUR_ASSISTANT_ID" }); if (!assistant.model) throw new Error("Assistant has no model configuration"); const updatedAssistant = await vapi.assistants.update({ id: assistant.id, model: { ...assistant.model, messages: [ { role: "system", content: systemPrompt } ] } }); console.log("System prompt updated successfully"); ``` #### Python (HTTP API) ```python import os import requests url = "https://api.vapi.ai/assistant/YOUR_ASSISTANT_ID" headers = { "Authorization": f"Bearer {os.environ['VAPI_API_KEY']}", "Content-Type": "application/json" } # Use the system prompt from above system_prompt = """# VapiBank - Phone Support Demo...""" current_response = requests.get(url, headers=headers, timeout=30) current_response.raise_for_status() current_model = current_response.json()["model"] data = { "model": { **current_model, "messages": [ { "role": "system", "content": system_prompt } ] } } response = requests.patch(url, headers=headers, json=data, timeout=30) response.raise_for_status() assistant = response.json() print("System prompt updated successfully") ``` #### cURL ```bash current_assistant=$(curl --fail https://api.vapi.ai/assistant/YOUR_ASSISTANT_ID \ -H "Authorization: Bearer $VAPI_API_KEY") && assistant_update=$(jq -e --argjson changes '{"messages":[{"role":"system","content":"# VapiBank - Phone Support Demo\n\n## Identity and purpose\nYou are Tom, a friendly VapiBank support assistant in a demo with fictional data.\nDo not introduce yourself again after the first message.\nHelp callers find a sample account, read its stored balance, and review its transactions.\n\n## Data and tool\nUse defaultQueryTool with knowledgeBaseNames set to [\"bank_records\"] before answering a question about account data.\nThe bank_records knowledge base contains both accounts.csv and transactions.csv.\naccounts.csv contains account_id, name, phone_last4, balance, card_status, and email.\ntransactions.csv contains account_id, date, description, and amount.\nThese files are a snapshot, not live banking data. Never describe a returned balance as a live balance.\n\n## Conversation flow\n1. Ask for the name on the sample account and the last four phone digits. Ask one question at a time.\n2. Call defaultQueryTool to find a sample account matching both values.\n3. Use only a returned account whose name and phone_last4 match the supplied details.\n If the result is missing, ambiguous, or mismatched, ask for clarification. Do not guess or disclose another record.\n4. For a balance question, call defaultQueryTool and report the matching account'\''s balance from the file.\n5. For a transaction question, call defaultQueryTool and use only transactions with the matching account_id.\n Summarize up to three returned transactions, newest date first. Do not invent missing transactions.\n6. If the caller changes the account details, repeat the lookup and ignore results for the previous account.\n7. When finished, ask whether the caller needs anything else, then thank them and say goodbye.\n\n## Limits and failures\nThis lookup does not authenticate the caller or authorize access to real accounts.\nIf a lookup fails or the result is unclear, say that you could not retrieve the requested information.\nDo not interpret a failed lookup as a zero balance or no transactions.\nDo not claim to transfer the call, arrange a callback, change an account, or move money. Those actions are not configured.\n\n## Style\nBe warm and concise. Aim for no more than 30 words per reply.\nRead important numbers slowly and clearly."}]}' \ 'if (.model | type) != "object" then error("Assistant has no model configuration") else {model: (.model + $changes)} end' \ <<< "$current_assistant") && curl --fail -X PATCH https://api.vapi.ai/assistant/YOUR_ASSISTANT_ID \ -H "Authorization: Bearer $VAPI_API_KEY" \ -H "Content-Type: application/json" \ --data "$assistant_update" ``` #### Configure LLM settings (optional) #### Dashboard Configure the LLM settings to your liking. * Select any provider and model you like (you will see cost and latency estimates). * You can specify the temperature and max tokens of the LLM. #### TypeScript (Server SDK) ```typescript import { VapiClient } from "@vapi-ai/server-sdk"; const apiKey = process.env.VAPI_API_KEY; if (!apiKey) throw new Error("Set VAPI_API_KEY to your Vapi private API key"); const vapi = new VapiClient({ token: apiKey }); async function updateAssistantLLMSettings(assistantId: string) { const currentAssistant = await vapi.assistants.get({ id: assistantId }); if (!currentAssistant.model) throw new Error("Assistant has no model configuration"); const updatedAssistant = await vapi.assistants.update({ id: assistantId, model: { ...currentAssistant.model, provider: "openai", model: "gpt-4o", temperature: 0.7, maxTokens: 150 } }); return updatedAssistant; } // Update LLM settings const assistant = await updateAssistantLLMSettings('YOUR_ASSISTANT_ID'); console.log('Assistant LLM settings updated'); ``` #### Python (HTTP API) ```python import os import requests def update_assistant_llm_settings(assistant_id): url = f"https://api.vapi.ai/assistant/{assistant_id}" headers = { "Authorization": f"Bearer {os.environ['VAPI_API_KEY']}", "Content-Type": "application/json" } current_response = requests.get(url, headers=headers, timeout=30) current_response.raise_for_status() current_model = current_response.json()["model"] data = { "model": { **current_model, "provider": "openai", "model": "gpt-4o", "temperature": 0.7, "maxTokens": 150 } } response = requests.patch(url, headers=headers, json=data, timeout=30) response.raise_for_status() return response.json() # Update LLM settings assistant = update_assistant_llm_settings('YOUR_ASSISTANT_ID') print("Assistant LLM settings updated") ``` #### cURL ```bash current_assistant=$(curl --fail https://api.vapi.ai/assistant/YOUR_ASSISTANT_ID \ -H "Authorization: Bearer $VAPI_API_KEY") && assistant_update=$(jq -e 'if (.model | type) != "object" then error("Assistant has no model configuration") else {model: (.model + {provider: "openai", model: "gpt-4o", temperature: 0.7, maxTokens: 150})} end' \ <<< "$current_assistant") && curl --fail -X PATCH https://api.vapi.ai/assistant/YOUR_ASSISTANT_ID \ -H "Authorization: Bearer $VAPI_API_KEY" \ -H "Content-Type: application/json" \ --data "$assistant_update" ``` #### Publish your assistant **Dashboard only:** Click `Publish` to save your changes. > **Note** > > When you use the Server SDK or HTTP API, changes apply immediately. You don't need a separate "publish" step. #### Test your assistant At this stage, test the greeting only. Test account answers after you [create and attach the Query tool](#4-create-and-attach-a-query-tool). The API examples in this step place an outbound call, which needs a number imported from [Twilio](/phone-numbers/import-twilio), [Telnyx](/telnyx), or [DIDWW](/phone-numbers/didww). Replace `YOUR_PHONE_NUMBER_ID` with the imported number's ID and `+14155550100` with a phone number you control. With free Vapi numbers, only inbound calls are supported. If you use a free Vapi number, [assign it to the assistant](#5-assign-a-phone-number-to-an-assistant) and call it from your own phone instead. See [Free Vapi numbers](/free-telephony) for details. #### Dashboard Click `Talk to Assistant` to test it out. #### TypeScript (Server SDK) ```typescript import { VapiClient } from "@vapi-ai/server-sdk"; const apiKey = process.env.VAPI_API_KEY; if (!apiKey) throw new Error("Set VAPI_API_KEY to your Vapi private API key"); const vapi = new VapiClient({ token: apiKey }); async function testAssistantWithCall(assistantId: string) { const call = await vapi.calls.create({ assistantId: assistantId, phoneNumberId: "YOUR_PHONE_NUMBER_ID", customer: { number: "+14155550100" // Your test phone number } }); if (!("id" in call)) throw new Error("Expected a single call"); console.log(`Test call created: ${call.id}`); return call; } // Create a test call const testCall = await testAssistantWithCall('YOUR_ASSISTANT_ID'); ``` #### Python (HTTP API) ```python import os import requests def test_assistant_with_call(assistant_id): url = "https://api.vapi.ai/call" headers = { "Authorization": f"Bearer {os.environ['VAPI_API_KEY']}", "Content-Type": "application/json" } data = { "assistantId": assistant_id, "phoneNumberId": "YOUR_PHONE_NUMBER_ID", "customer": { "number": "+14155550100" # Your test phone number } } response = requests.post(url, headers=headers, json=data, timeout=30) response.raise_for_status() call = response.json() print(f"Test call created: {call['id']}") return call # Create a test call test_call = test_assistant_with_call('YOUR_ASSISTANT_ID') ``` #### cURL ```bash # Create a test call curl --fail -X POST https://api.vapi.ai/call \ -H "Authorization: Bearer $VAPI_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "assistantId": "YOUR_ASSISTANT_ID", "phoneNumberId": "YOUR_PHONE_NUMBER_ID", "customer": { "number": "+14155550100" } }' ``` --- ## 4. Create and attach a Query tool Create one Query tool with both CSV files in the same knowledge base. Each lookup can then use the account details and transaction records together. The API examples use the default function name, `defaultQueryTool`. Use the same name in the dashboard and in the system prompt above. Replace the file ID placeholders with the IDs from [step 1](#1-upload-the-sample-files). For complete request schemas, see the [Create Tool](/api-reference/tools/create) and [Update Assistant](/api-reference/assistants/update) API references. #### Dashboard #### Create a Query tool Open **Tools** in the [Vapi Dashboard](https://dashboard.vapi.ai). Click **Create Tool** and select **Query**. Set **Tool Name** to `defaultQueryTool`. #### Add the knowledge base Under **Knowledge Bases**, click **Add Knowledge Base** and configure these fields: | Field | Value | | --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | | **Name** | `bank_records` | | **Description** | Sample bank account and transaction records. Use both CSV files to match sample accounts and retrieve their recorded balances and transactions. | | **Model** | `gemini-2.5-flash` | | **Files** | Select both `accounts.csv` and `transactions.csv`. | Save or publish the tool. #### Attach the tool Open **Assistants** and select `Tom`. In **Tools**, attach the saved `defaultQueryTool`. If you followed an earlier version of this example, detach `lookup_account`, `get_balance`, and `get_recent_transactions`. Keep the system prompt from step 3, then publish the assistant. #### TypeScript (Server SDK) Set `VAPI_API_KEY` to your Vapi private API key. ```typescript import { VapiClient } from "@vapi-ai/server-sdk"; const apiKey = process.env.VAPI_API_KEY; if (!apiKey) throw new Error("Set VAPI_API_KEY to your Vapi private API key"); const vapi = new VapiClient({ token: apiKey }); const queryTool = await vapi.tools.create({ type: "query", knowledgeBases: [ { name: "bank_records", provider: "google", model: "gemini-2.5-flash", description: "Sample bank account and transaction records. Use both CSV files to match sample accounts and retrieve their recorded balances and transactions.", fileIds: [ "YOUR_ACCOUNTS_FILE_ID", "YOUR_TRANSACTIONS_FILE_ID" ] } ] }); console.log(`Created Query tool: ${queryTool.id}`); const assistant = await vapi.assistants.get({ id: "YOUR_ASSISTANT_ID" }); if (!assistant.model) throw new Error("Assistant has no model configuration"); await vapi.assistants.update({ id: assistant.id, model: { ...assistant.model, toolIds: [queryTool.id] } }); ``` #### Python (HTTP API) Set `VAPI_API_KEY` to your Vapi private API key. ```python import os import requests headers = { "Authorization": f"Bearer {os.environ['VAPI_API_KEY']}", "Content-Type": "application/json" } tool_response = requests.post( "https://api.vapi.ai/tool", headers=headers, json={ "type": "query", "knowledgeBases": [ { "name": "bank_records", "provider": "google", "model": "gemini-2.5-flash", "description": "Sample bank account and transaction records. Use both CSV files to match sample accounts and retrieve their recorded balances and transactions.", "fileIds": [ "YOUR_ACCOUNTS_FILE_ID", "YOUR_TRANSACTIONS_FILE_ID" ] } ] }, timeout=30 ) tool_response.raise_for_status() query_tool = tool_response.json() print(f"Created Query tool: {query_tool['id']}") assistant_url = "https://api.vapi.ai/assistant/YOUR_ASSISTANT_ID" current_response = requests.get(assistant_url, headers=headers, timeout=30) current_response.raise_for_status() current_model = current_response.json()["model"] assistant_response = requests.patch( assistant_url, headers=headers, json={"model": {**current_model, "toolIds": [query_tool["id"]]}}, timeout=30 ) assistant_response.raise_for_status() ``` #### cURL Create the tool and copy its returned `id`: ```bash curl --fail -X POST https://api.vapi.ai/tool \ -H "Authorization: Bearer $VAPI_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "type": "query", "knowledgeBases": [ { "name": "bank_records", "provider": "google", "model": "gemini-2.5-flash", "description": "Sample bank account and transaction records. Use both CSV files to match sample accounts and retrieve their recorded balances and transactions.", "fileIds": [ "YOUR_ACCOUNTS_FILE_ID", "YOUR_TRANSACTIONS_FILE_ID" ] } ] }' ``` Replace `YOUR_QUERY_TOOL_ID` with that ID, then attach the tool: ```bash current_assistant=$(curl --fail https://api.vapi.ai/assistant/YOUR_ASSISTANT_ID \ -H "Authorization: Bearer $VAPI_API_KEY") && assistant_update=$(jq -e --arg toolId "YOUR_QUERY_TOOL_ID" \ 'if (.model | type) != "object" then error("Assistant has no model configuration") else {model: (.model + {toolIds: [$toolId]})} end' \ <<< "$current_assistant") && curl --fail -X PATCH https://api.vapi.ai/assistant/YOUR_ASSISTANT_ID \ -H "Authorization: Bearer $VAPI_API_KEY" \ -H "Content-Type: application/json" \ --data "$assistant_update" ``` The API examples target the new assistant created in this guide and replace its `model.toolIds` array. If you adapt an existing assistant, include any unrelated tool IDs you want to keep. Use only one Query tool for this example. After attaching the tool, test with the sample name `John Doe` and phone digits `1234`. Check that `defaultQueryTool` runs with `knowledgeBaseNames: ["bank_records"]`. Compare the answer with `acc_001` in the CSV files: the stored balance is `2534.67`, and the three transactions are dated May 22–24, 2025. Also test unknown or mismatched account details, a correction during the conversation, and a failed lookup. The assistant should ask for clarification or explain the failure, not invent account data. Prompt instructions guide retrieval; they do not enforce exact matching, identity verification, or account access controls. --- ## 5. Assign a Phone Number to an Assistant > **Note** > > These examples create a Vapi phone number in a US-region organization. Choose an available area code; the examples use `415`. #### Dashboard #### Navigate to Phone Numbers Open your [dashboard.vapi.ai](https://dashboard.vapi.ai) and click `Phone Numbers` in the left sidebar. #### Create a new phone number * Click **Create Phone Number**. * Select **Free Vapi Number**. * Enter an available area code in **Area code**, for example `415`. * Click **Create**. #### Configure the phone number * Set **Phone Number Label** to `Vapi Support Hotline`. * Under **Inbound Settings**, select `Tom` from the **Assistant** dropdown. * Click **Save**. #### TypeScript (Server SDK) ```typescript import { VapiClient } from "@vapi-ai/server-sdk"; const apiKey = process.env.VAPI_API_KEY; if (!apiKey) throw new Error("Set VAPI_API_KEY to your Vapi private API key"); const vapi = new VapiClient({ token: apiKey }); const phoneNumber = await vapi.phoneNumbers.create({ provider: "vapi", numberDesiredAreaCode: "415", name: "Vapi Support Hotline", assistantId: "YOUR_ASSISTANT_ID" }); console.log(`Phone number created: ${phoneNumber.number}`); console.log(`Phone number ID: ${phoneNumber.id}`); ``` #### Python (HTTP API) ```python import os import requests def create_phone_number(name, assistant_id): url = "https://api.vapi.ai/phone-number" headers = { "Authorization": f"Bearer {os.environ['VAPI_API_KEY']}", "Content-Type": "application/json" } data = { "provider": "vapi", "numberDesiredAreaCode": "415", "name": name, "assistantId": assistant_id } response = requests.post(url, headers=headers, json=data, timeout=30) response.raise_for_status() return response.json() # Create phone number for Tom assistant_id = "YOUR_ASSISTANT_ID" phone_number = create_phone_number("Vapi Support Hotline", assistant_id) print(f"Phone number created: {phone_number['number']}") print(f"Phone number ID: {phone_number['id']}") ``` #### cURL ```bash # Create a phone number curl --fail -X POST https://api.vapi.ai/phone-number \ -H "Authorization: Bearer $VAPI_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "provider": "vapi", "numberDesiredAreaCode": "415", "name": "Vapi Support Hotline", "assistantId": "YOUR_ASSISTANT_ID" }' ``` --- ## Next Steps You've configured an inbound support demo that uses a Query tool to answer questions from sample CSV files. For real customer accounts, use an authenticated backend that enforces account access and retrieves current data. Consider reading the following guides to further enhance your assistant: * [**Knowledge bases**](/knowledge-base) - Learn more about knowledge bases to build knowledge-based agents. * [**External Integrations**](/tools) - Configure integrations with [Google Calendar](/tools/google-calendar), [Google Sheets](/tools/google-sheets), [Slack](/tools/slack), etc. * [**Squads**](/squads) - Learn how to compose multiple assistants and transfer seamlessly for complex use cases. > **Note** > > Need help? Ask other developers in the [Vapi Discord community](https://discord.gg/v5Ee6FhAZt) or mention us on [X/Twitter](https://x.com/Vapi_AI). > Build an inbound support demo that answers questions from sample account and transaction files