diff --git a/fern/chat/chat.mdx b/fern/chat/chat.mdx new file mode 100644 index 000000000..0776ad98c --- /dev/null +++ b/fern/chat/chat.mdx @@ -0,0 +1,509 @@ +--- +title: Chat API +subtitle: Build text-based conversations with Vapi assistants using streaming and non-streaming chat +--- + +## Overview + +The Chat API enables text-based conversations with Vapi assistants. Unlike voice calls, chats provide a synchronous or streaming text interface perfect for integrations with messaging platforms, web interfaces, or any text-based communication channel. + +Key features: +- **Non-streaming responses** (default) for simple request-response patterns +- **Streaming responses** for real-time, token-by-token output +- **Context preservation** through sessions or previous chats +- **OpenAI compatibility** through the `/chat/responses` endpoint + +## Key concepts + +- **`messages`** - Conversation history that provides context for the chat +- **`input`** - The user's input to the chat (required) +- **`output`** - The response generated by the assistant + +## Quick start + + + + Send a POST request to create a new chat conversation: + + ```bash + curl -X POST https://api.vapi.ai/chat \ + -H "Authorization: Bearer YOUR_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "assistantId": "your-assistant-id", + "input": "Hello, how can you help me today?" + }' + ``` + + + + The API returns the assistant's response in the `output` field: + + ```json + { + "id": "chat_abc123", + "assistantId": "your-assistant-id", + "messages": [ + { + "role": "user", + "content": "Hello, how can you help me today?" + } + ], + "output": [ + { + "role": "assistant", + "content": "Hello! I'm here to help. What would you like to know?" + } + ], + "createdAt": "2024-01-15T09:30:00Z", + "updatedAt": "2024-01-15T09:30:00Z" + } + ``` + + + + Use the `previousChatId` to maintain context: + + ```bash + curl -X POST https://api.vapi.ai/chat \ + -H "Authorization: Bearer YOUR_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "previousChatId": "chat_abc123", + "input": "Tell me about your features" + }' + ``` + + + +## Non-streaming chat + +Non-streaming chat returns the complete response after the assistant finishes processing. This is ideal for simple integrations where you don't need real-time output. + +### Basic example + +```javascript +const response = await fetch('https://api.vapi.ai/chat', { + method: 'POST', + headers: { + 'Authorization': 'Bearer YOUR_API_KEY', + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + assistantId: 'your-assistant-id', + input: 'What is the weather like today?' + }) +}); + +const chat = await response.json(); +console.log(chat.output[0].content); // Assistant's response +``` + +### Response structure + +```javascript +{ + "id": "chat_123456", + "orgId": "org_789012", + "assistantId": "assistant_345678", + "name": "Weather Chat", + "sessionId": "session_901234", + "messages": [ + { + "role": "user", + "content": "What is the weather like today?" + } + ], + "output": [ + { + "role": "assistant", + "content": "I'd be happy to help with weather information, but I'll need to know your location first. What city are you in?" + } + ], + "createdAt": "2024-01-15T09:30:00Z", + "updatedAt": "2024-01-15T09:30:01Z" +} +``` + +### With custom assistant configuration + +```javascript +const response = await fetch('https://api.vapi.ai/chat', { + method: 'POST', + headers: { + 'Authorization': 'Bearer YOUR_API_KEY', + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + input: 'Help me plan a trip to Paris', + assistant: { + model: { + provider: 'openai', + model: 'gpt-4', + temperature: 0.7, + messages: [ + { + role: 'system', + content: 'You are a helpful travel assistant specializing in European destinations.' + } + ] + }, + voice: { + provider: 'azure', + voiceId: 'andrew' + } + } + }) +}); +``` + +## Streaming chat + +Streaming chat provides real-time, token-by-token responses. Enable streaming by setting `stream: true` in your request (default is `false`). + +### Basic streaming example + +```javascript +const response = await fetch('https://api.vapi.ai/chat', { + method: 'POST', + headers: { + 'Authorization': 'Bearer YOUR_API_KEY', + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + assistantId: 'your-assistant-id', + input: 'Write me a short story', + stream: true + }) +}); + +const reader = response.body.getReader(); +const decoder = new TextDecoder(); + +while (true) { + const { done, value } = await reader.read(); + if (done) break; + + const chunk = decoder.decode(value); + const lines = chunk.split('\n').filter(line => line.trim()); + + for (const line of lines) { + if (line.startsWith('data: ')) { + const data = JSON.parse(line.slice(6)); + // Stream events have format: { id, path, delta } + if (data.path && data.delta) { + process.stdout.write(data.delta); // Print each token as it arrives + } + } + } +} +``` + +### Streaming response format + +When streaming is enabled, the response is sent as Server-Sent Events (SSE). Each event contains: + +```javascript +{ + "id": "stream_123456", + "path": "chat.output[0].content", + "delta": "Hello" +} +``` + +The `path` indicates where in the response structure the content is being appended, following the format `chat.output[{index}].content`. + +### Handling streaming events + +```javascript +async function streamChat(input) { + const response = await fetch('https://api.vapi.ai/chat', { + method: 'POST', + headers: { + 'Authorization': 'Bearer YOUR_API_KEY', + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + assistantId: 'your-assistant-id', + input: input, + stream: true + }) + }); + + const reader = response.body.getReader(); + const decoder = new TextDecoder(); + let buffer = ''; + let fullContent = ''; + + while (true) { + const { done, value } = await reader.read(); + if (done) break; + + buffer += decoder.decode(value, { stream: true }); + const lines = buffer.split('\n'); + buffer = lines.pop(); // Keep incomplete line in buffer + + for (const line of lines) { + if (line.startsWith('data: ')) { + try { + const event = JSON.parse(line.slice(6)); + if (event.path && event.delta) { + // Extract content index from path like "chat.output[0].content" + const match = event.path.match(/output\[(\d+)\]\.content/); + if (match) { + process.stdout.write(event.delta); + fullContent += event.delta; + } + } + } catch (e) { + console.error('Failed to parse event:', e); + } + } + } + } + + console.log('\n\nFull response:', fullContent); +} +``` + +## Context management + +Maintain conversation context across multiple chat interactions using sessions or previous chat references. + +### Using sessions + +Sessions allow multiple chats to share the same context: + +```javascript +// Create a session +const sessionResponse = await fetch('https://api.vapi.ai/session', { + method: 'POST', + headers: { + 'Authorization': 'Bearer YOUR_API_KEY', + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + assistantId: 'your-assistant-id' + }) +}); + +const session = await sessionResponse.json(); + +// Use the session for multiple chats +const chat1 = await fetch('https://api.vapi.ai/chat', { + method: 'POST', + headers: { + 'Authorization': 'Bearer YOUR_API_KEY', + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + sessionId: session.id, + input: 'My name is Alice' + }) +}); + +const chat1Data = await chat1.json(); +console.log(chat1Data.output[0].content); // "Nice to meet you, Alice!" + +const chat2 = await fetch('https://api.vapi.ai/chat', { + method: 'POST', + headers: { + 'Authorization': 'Bearer YOUR_API_KEY', + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + sessionId: session.id, + input: 'What is my name?' // Assistant will remember "Alice" + }) +}); + +const chat2Data = await chat2.json(); +console.log(chat2Data.output[0].content); // "Your name is Alice." +``` + +### Using previous chat + +Link chats together without creating a session: + +```javascript +// First chat +const firstChat = await fetch('https://api.vapi.ai/chat', { + method: 'POST', + headers: { + 'Authorization': 'Bearer YOUR_API_KEY', + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + assistantId: 'your-assistant-id', + input: 'I need help with Python programming' + }) +}); + +const firstChatData = await firstChat.json(); + +// Continue conversation +const secondChat = await fetch('https://api.vapi.ai/chat', { + method: 'POST', + headers: { + 'Authorization': 'Bearer YOUR_API_KEY', + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + previousChatId: firstChatData.id, + input: 'Show me how to create a list' + }) +}); +``` + +## OpenAI compatibility + +Vapi provides an OpenAI-compatible endpoint at `/chat/responses` that works with the OpenAI SDK. This allows you to use existing OpenAI client libraries with Vapi. + +### Using the OpenAI SDK + +```javascript +import OpenAI from 'openai'; + +const openai = new OpenAI({ + apiKey: 'YOUR_VAPI_API_KEY', + baseURL: 'https://api.vapi.ai/chat' +}); + +// Create a streaming response +const stream = await openai.responses.create({ + model: 'gpt-4o', + input: 'Tell me a joke', + stream: true, + assistantId: 'your-assistant-id' +}); + +// Handle the stream +for await (const event of stream) { + if (event.type === 'response.output_text.delta') { + process.stdout.write(event.delta); + } +} +``` + +### Non-streaming with OpenAI SDK + +```javascript +const response = await openai.responses.create({ + model: 'gpt-4o', + input: 'What is the capital of France?', + stream: false, + assistantId: 'your-assistant-id' +}); + +console.log(response.output[0].content[0].text); +``` + +### Maintaining context with OpenAI SDK + +```javascript +// First request +const response1 = await openai.responses.create({ + model: 'gpt-4o', + input: 'My name is Sarah', + stream: false, + assistantId: 'your-assistant-id' +}); + +// Continue conversation using previous_response_id +const response2 = await openai.responses.create({ + model: 'gpt-4o', + input: 'What is my name?', + previous_response_id: response1.id, + stream: false, + assistantId: 'your-assistant-id' +}); + +console.log(response2.output[0].content[0].text); // "Your name is Sarah" +``` + +### OpenAI compatibility notes + +- Use your Vapi API key as the OpenAI API key +- Set the base URL to `https://api.vapi.ai/chat` +- The `assistantId` parameter is required to specify which Vapi assistant to use +- The `model` parameter is included for compatibility but the actual model is determined by your assistant configuration +- Use `previous_response_id` instead of `previousChatId` for context continuation + +## Message types + +The Chat API supports various message types for both input and output: + +### User message +```javascript +{ + "role": "user", + "content": "Hello, how are you?", + "name": "Alice" // Optional +} +``` + +### Assistant message +```javascript +{ + "role": "assistant", + "content": "I'm doing well, thank you!", + "tool_calls": [...], // Optional tool calls + "refusal": null // Optional refusal message +} +``` + +### System message +```javascript +{ + "role": "system", + "content": "You are a helpful assistant specializing in technical support." +} +``` + +### Tool message +```javascript +{ + "role": "tool", + "content": "Weather data retrieved successfully", + "tool_call_id": "call_123456" +} +``` + +### Developer message +```javascript +{ + "role": "developer", + "content": "Always be concise in your responses." +} +``` + +## Best practices + + +**Optimize for performance** +- Reuse `sessionId` or `previousChatId` to maintain context efficiently +- Use streaming for long responses to improve perceived performance +- Set appropriate `temperature` values (0.0-1.0) based on your use case + + + +**Security considerations** +- Never expose your API key in client-side code +- Implement proper authentication in your backend +- Validate and sanitize user inputs before sending to the API + + + +**Rate limits** +Be mindful of rate limits when implementing chat features. Consider implementing: +- Request queuing for high-traffic applications +- Exponential backoff for retries +- User-level rate limiting in your application + + +## Next steps + +- Explore the [API reference](/api-reference/chats/chat-controller-create-chat) for all available parameters +- Learn about [assistants](/docs/assistants) to customize chat behavior +- Implement [tools](/docs/tools) for advanced functionality +- Set up [webhooks](/docs/webhooks) for real-time events diff --git a/fern/docs.yml b/fern/docs.yml index 5e8c61a10..21e8a66c6 100644 --- a/fern/docs.yml +++ b/fern/docs.yml @@ -320,6 +320,12 @@ navigation: path: squads/silent-transfers.mdx icon: fa-light fa-arrow-right-arrow-left + - section: Chat + contents: + - page: Chat API + path: chat/chat.mdx + icon: fa-light fa-comments + - section: Webhooks collapsed: true icon: fa-light fa-webhook