@voxai/nodejs-sdk
v1.1.1
Published
Official Node.js SDK for Vox AI platform - Build and deploy AI voice agents
Maintainers
Readme
Vox AI Node.js SDK
Official Node.js SDK for the Vox AI platform. Build and deploy AI voice agents with ease.
Features
- 🤖 Agent Management - Create, configure, and manage AI voice agents
- 📞 Call Management - Make outbound calls and handle inbound calls
- 🔊 Voice Configuration - Support for multiple TTS providers (ElevenLabs, OpenAI, Azure)
- ⚡ Real-time Events - WebSocket support for live call monitoring
- 🛡️ Type Safety - Full TypeScript support with comprehensive type definitions
- 🔄 Auto Retry - Built-in retry logic with exponential backoff
- 📊 Call Analytics - Track call performance and statistics
- 🎯 Fluent API - Intuitive builder pattern for agent creation
Installation
npm install @voxai/nodejs-sdkyarn add @voxai/nodejs-sdkpnpm add @voxai/nodejs-sdkQuick Start
import { VoxClient } from '@voxai/nodejs-sdk';
// Initialize the client
const vox = new VoxClient({
apiKey: 'your-api-key-here'
});
// Create an agent
const agent = await vox.agents
.name('Customer Support Bot')
.description('Handles customer inquiries')
.personality('Professional and helpful')
.elevenlabsVoice('voice-id-here')
.enableFunctionCalling()
.create();
// Make a call
const call = await vox.calls.initiate({
agentId: agent.id,
phoneNumber: '+1234567890',
recordCall: true
});
console.log(`Call initiated: ${call.id}`);Authentication
Get your API key from the Vox AI Dashboard.
const vox = new VoxClient({
apiKey: 'vox_live_...', // Your API key
baseUrl: 'https://api.vox.ai', // Optional: Custom API endpoint
timeout: 30000, // Optional: Request timeout in ms
retryAttempts: 3 // Optional: Number of retry attempts
});Agent Management
Creating Agents
Basic Agent
const agent = await vox.agents
.name('Sales Assistant')
.description('Helps with product inquiries')
.create();Advanced Agent with Voice and Capabilities
const agent = await vox.agents
.name('Advanced Assistant')
.description('Multi-capable AI assistant')
.personality('Friendly, professional, and knowledgeable')
.instructions('Always greet customers warmly and ask how you can help.')
.elevenlabsVoice('voice-id', {
stability: 0.8,
clarity: 0.9,
speed: 1.0
})
.enableFunctionCalling({
functions: ['get_weather', 'schedule_appointment']
})
.enableWebSearch()
.enableMemory({
maxContextLength: 4000
})
.addMetadata('department', 'sales')
.create();Voice Providers
// ElevenLabs
const agent1 = await vox.agents
.name('ElevenLabs Agent')
.elevenlabsVoice('voice-id', { stability: 0.8 })
.create();
// OpenAI
const agent2 = await vox.agents
.name('OpenAI Agent')
.openaiVoice('alloy', { speed: 1.2 })
.create();
// Azure
const agent3 = await vox.agents
.name('Azure Agent')
.azureVoice('en-US-AriaNeural')
.create();Managing Agents
// Get agent by ID
const agent = await vox.agents.get('agent-id');
// List all agents
const agents = await vox.agents.list();
// Search agents
const results = await vox.agents.search('customer service');
// Update agent
const updated = await vox.agents.update('agent-id', {
name: 'Updated Name',
personality: 'More casual and friendly'
});
// Clone agent
const cloned = await vox.agents.clone('agent-id', 'Cloned Agent');
// Delete agent
await vox.agents.delete('agent-id');Call Management
Making Calls
// Basic call
const call = await vox.calls.initiate({
agentId: 'agent-id',
phoneNumber: '+1234567890'
});
// Advanced call with options
const call = await vox.calls.initiate({
agentId: 'agent-id',
phoneNumber: '+1234567890',
recordCall: true,
maxDuration: 1800000, // 30 minutes in ms
webhookUrl: 'https://your-app.com/webhook',
metadata: {
customerID: '12345',
campaign: 'summer-sale'
}
});
// Quick call helper
const call = await vox.calls.quickCall('agent-id', '+1234567890');Monitoring Calls
// Get call status
const call = await vox.calls.get('call-id');
// Wait for call completion
const completedCall = await vox.calls.waitForCompletion('call-id');
// Monitor with status updates
const finalCall = await vox.calls.monitor(
'call-id',
(call) => {
console.log(`Call status: ${call.status}`);
}
);
// Cancel or hang up
await vox.calls.cancel('call-id');
await vox.calls.hangup('call-id');Call History and Analytics
// List all calls
const calls = await vox.calls.list({
page: 1,
limit: 50,
sortBy: 'created_at',
sortOrder: 'desc'
});
// Get calls by agent
const agentCalls = await vox.calls.getByAgent('agent-id');
// Get calls by status
const activeCalls = await vox.calls.getActive();
const completedCalls = await vox.calls.getByStatus('completed');
// Search by phone number
const customerCalls = await vox.calls.searchByPhoneNumber('+1234567890');
// Get call statistics
const stats = await vox.calls.getStats('agent-id');
console.log(`Total calls: ${stats.total}`);
console.log(`Average duration: ${stats.avgDuration}ms`);Call Transcripts and Recordings
// Get call transcript
const transcript = await vox.calls.getTranscript('call-id');
transcript.forEach(entry => {
console.log(`${entry.role}: ${entry.content}`);
});
// Get call recording URL
const recordingUrl = await vox.calls.getRecording('call-id');
console.log(`Recording available at: ${recordingUrl}`);Real-time Events
WebSocket Connection
// Connect to WebSocket for real-time events
await vox.connectWebSocket();
// Set up event handlers
vox.websocket.on({
onCallStarted: (call) => {
console.log(`Call ${call.id} started`);
},
onCallEnded: (call) => {
console.log(`Call ${call.id} ended with status: ${call.status}`);
},
onTranscriptUpdate: (transcript, callId) => {
console.log(`${transcript.role}: ${transcript.content}`);
},
onAgentSpeaking: (callId) => {
console.log(`Agent is speaking on call ${callId}`);
},
onUserSpeaking: (callId) => {
console.log(`User is speaking on call ${callId}`);
},
onError: (error) => {
console.error('WebSocket error:', error);
}
});
// Subscribe to specific call events
await vox.websocket.subscribeToCall('call-id');
// Subscribe to agent events
await vox.websocket.subscribeToAgent('agent-id');Call Monitoring
// Monitor a specific call with custom handlers
const cleanup = await vox.websocket.monitorCall('call-id', {
onTranscriptUpdate: (transcript, callId) => {
// Handle real-time transcript updates
updateUI(transcript);
},
onCallEnded: (call) => {
// Handle call completion
showCallSummary(call);
}
});
// Clean up when done
await cleanup();Error Handling
The SDK provides comprehensive error handling with specific error types:
import {
VoxError,
VoxApiError,
VoxValidationError,
VoxWebSocketError
} from '@voxai/nodejs-sdk';
try {
const call = await vox.calls.initiate({
agentId: 'invalid-agent',
phoneNumber: 'invalid-number'
});
} catch (error) {
if (error instanceof VoxValidationError) {
console.error('Validation error:', error.message);
console.error('Details:', error.details);
} else if (error instanceof VoxApiError) {
console.error('API error:', error.message);
console.error('Status code:', error.statusCode);
console.error('Error code:', error.code);
} else if (error instanceof VoxWebSocketError) {
console.error('WebSocket error:', error.message);
} else {
console.error('Unknown error:', error);
}
}Advanced Usage
Custom Configuration
const vox = new VoxClient({
apiKey: 'your-api-key',
baseUrl: 'https://your-custom-endpoint.com',
timeout: 60000,
retryAttempts: 5,
enableWebSocket: true,
websocketUrl: 'wss://your-websocket-endpoint.com'
});Pagination
// Manual pagination
let page = 1;
let hasMore = true;
while (hasMore) {
const result = await vox.calls.list({ page, limit: 100 });
// Process calls
result.data.forEach(call => {
console.log(call.id);
});
hasMore = result.pagination.hasNext;
page++;
}
// Get all pages at once (be careful with large datasets)
const allCalls = [];
let currentPage = 1;
let response;
do {
response = await vox.calls.list({ page: currentPage, limit: 100 });
allCalls.push(...response.data);
currentPage++;
} while (response.pagination.hasNext);Bulk Operations
// Bulk cancel calls
const result = await vox.calls.bulkCancel(['call-1', 'call-2', 'call-3']);
console.log(`Successfully cancelled: ${result.success.length}`);
console.log(`Failed to cancel: ${result.failed.length}`);Testing Connection
// Test API connectivity
const isConnected = await vox.ping();
if (!isConnected) {
console.error('Unable to connect to Vox AI API');
}
// Get account information
const account = await vox.getAccount();
console.log('Account info:', account.data);TypeScript Support
The SDK is written in TypeScript and provides comprehensive type definitions:
import type {
Agent,
Call,
CallStatus,
Transcript,
VoiceConfig,
AgentCapability,
WebSocketMessage
} from '@voxai/nodejs-sdk';
// Type-safe agent creation
const agentConfig: CreateAgentRequest = {
name: 'Typed Agent',
voice: {
provider: 'elevenlabs',
voiceId: 'voice-id'
},
capabilities: [
{
type: 'function_calling',
enabled: true
}
]
};
// Type-safe call options
const callOptions: CallOptions = {
agentId: 'agent-id',
phoneNumber: '+1234567890',
recordCall: true
};Best Practices
- API Key Security: Never commit API keys to version control. Use environment variables:
const vox = new VoxClient({
apiKey: process.env.VOX_AI_API_KEY!
});Error Handling: Always wrap API calls in try-catch blocks and handle specific error types.
WebSocket Management: Clean up WebSocket connections when your application shuts down:
process.on('SIGINT', async () => {
await vox.destroy();
process.exit(0);
});Rate Limiting: The API has rate limits. The SDK handles retries automatically, but consider implementing exponential backoff for bulk operations.
Logging: Enable debug logging in development:
// Add custom logging
vox.websocket.on({
onMessage: (message) => {
console.debug('WebSocket message:', message);
}
});Examples
Complete Call Flow
import { VoxClient } from '@voxai/nodejs-sdk';
async function makeCall() {
const vox = new VoxClient({
apiKey: process.env.VOX_AI_API_KEY!
});
try {
// Create agent
const agent = await vox.agents
.name('Demo Agent')
.personality('Professional and helpful')
.elevenlabsVoice('voice-id')
.enableFunctionCalling()
.create();
console.log(`Created agent: ${agent.id}`);
// Connect WebSocket for real-time updates
await vox.connectWebSocket();
// Set up call monitoring
const cleanup = await vox.websocket.monitorCall('pending-call-id', {
onCallStarted: (call) => {
console.log(`Call started: ${call.id}`);
},
onTranscriptUpdate: (transcript) => {
console.log(`${transcript.role}: ${transcript.content}`);
},
onCallEnded: (call) => {
console.log(`Call ended with status: ${call.status}`);
}
});
// Initiate call
const call = await vox.calls.initiate({
agentId: agent.id,
phoneNumber: '+1234567890',
recordCall: true,
metadata: { demo: true }
});
// Wait for completion
const finalCall = await vox.calls.waitForCompletion(call.id);
// Get transcript and recording
const transcript = await vox.calls.getTranscript(finalCall.id);
const recordingUrl = await vox.calls.getRecording(finalCall.id);
console.log('Call completed!');
console.log('Transcript:', transcript);
console.log('Recording:', recordingUrl);
// Cleanup
await cleanup();
await vox.destroy();
} catch (error) {
console.error('Error:', error);
}
}
makeCall();Support
License
This project is licensed under the MIT License - see the LICENSE file for details.
