Reference
This page documents the client-side JavaScript SDK for voice calls. The SDK supports both Client-Side and Server-Side Initiation methods.
Call Management
handleCall2(partner, character, credential, customMetadata)
Initiates a call to the AI character. The method supports both authentication flows:
Client-Side Initiation
For direct client-side calls using an API key:
| Parameter | Type | Description | Example |
|---|---|---|---|
| partner | String | Partner identifier (same as your login id in Character Editor) | "github:partner" |
| character | String | Name of the AI character created in the Character Editor | "character" |
| credential | String | Your API key | "your-api-key" |
| customMetadata | Object | Custom metadata for statistics collection | { userType: "premium", userName: "James"} |
Example:
await callManager.handleCall2("github:partner", "character", "your-api-key", {
userType: "premium",
userName: "James"
});
Server-Side Initiation (Recommended)
For secure calls using a signed URL from your backend:
| Parameter | Type | Description | Example |
|---|---|---|---|
| partner | null | Not used with signed URLs | null |
| character | null | Not used with signed URLs | null |
| credential | String | Signed URL from your backend | "https://backend.funtimewithaisolutions.com/v2/calls/3267?signature=..." |
| customMetadata | Object | Custom metadata for statistics collection | { userType: "premium", userName: "James"} |
Your application should initiate calls through your backend and provide the SDK with the returned signed URL:
// signedUrl obtained from your backend
await callManager.handleCall2(null, null, signedUrl, {
userType: "premium",
userName: "James"
});
hangUp()
Ends the current call.
callManager.hangUp();
mute(isMuted)
Mutes or unmutes the microphone during an active call.
| Parameter | Type | Description |
|---|---|---|
| isMuted | Boolean | true to mute the microphone (sends silence), false to unmute |
Example:
// During a call, mute the microphone
callManager.mute(true);
// Unmute to resume talking
callManager.mute(false);
Device Management
CallManager.getAvailableDevices() (Static Method)
Returns a list of available audio input and output devices.
| Returns | Type | Description |
|---|---|---|
| Promise<Object> | Object | Object with microphones and speakers arrays |
Each device object contains:
deviceId- Unique identifier for the devicelabel- Human-readable device nameisDefault- Whether it's the system default device
Example:
// Get all available audio devices
const devices = await CallManager.getAvailableDevices();
console.log("Microphones:", devices.microphones);
console.log("Speakers:", devices.speakers);
changeDevices(microphoneId, speakerId)
Changes audio input/output devices during an active call.
| Parameter | Type | Description |
|---|---|---|
| microphoneId | String or null | Device ID of the microphone to switch to. Pass null to keep current. |
| speakerId | String or null | Device ID of the speaker to switch to. Pass null to keep current. |
Example:
// Change both devices
await callManager.changeDevices(microphoneId, speakerId);
// Change only microphone
await callManager.changeDevices(microphoneId, null);
// Change only speaker
await callManager.changeDevices(null, speakerId);
Callback Functions
The SDK uses a callback-based approach to handle different events. You may use them in order to have a visual feedback / change UI based on the call events. Define these in the callbacks object when initializing CallManager:
Required vs Optional Callbacks:
- Required callbacks are called directly by the SDK and must be implemented to prevent errors
- Optional callbacks are checked before calling - the SDK will safely skip them if not provided
- You can provide empty functions for required callbacks if you don't need the functionality:
onCallStart: () => {}
| Callback | Parameters | Required | Description |
|---|---|---|---|
| onCallStart | None | Required | Triggered when a call initiation begins (at the start of handleCall2) |
| onCallError | None | Required | Triggered when there's an error starting or during a call |
| onHangUp | None | Required | Triggered when a call ends |
| onStatusUpdate | status (String) | Required | Triggered when the call status changes |
| onCallStarting | None | Optional | Triggered after microphone permission is granted but before WebSocket connection begins |
| onConnected | None | Optional | Triggered when WebSocket connection is successfully established |
| onUserInfo | info (String) | Optional | Triggered when there's new user information |
| onRagInfo | ragData (Object) | Optional | Triggered when the AI uses RAG (Retrieval Augmented Generation) to fetch relevant documents. Contains metadata and array of documents used for context. |
RAG Data Structure
The ragData object contains the following fields:
| Field | Type | Description |
|---|---|---|
| documents | Array | Array of document objects retrieved by RAG search |
| count | Number | Total number of documents (optional, defaults to documents.length) |
| total_tokens | Number | Total tokens across all retrieved documents |
Document Object Structure
Each document in the documents array contains:
| Field | Type | Description |
|---|---|---|
| title | String | Document title or identifier |
| fusion_score | Number | Relevance score from RAG fusion algorithm |
| token_count | Number | Number of tokens in this document |
Example handling RAG information:
const callbacks = {
// ... other required callbacks (onCallStart, onCallError, onHangUp, onStatusUpdate) ...
onRagInfo: (ragData) => { // Optional callback
console.log(`Found ${ragData.count || ragData.documents.length} documents (${ragData.total_tokens || 0} tokens)`);
// Display each document with its metadata
ragData.documents.forEach((doc, index) => {
console.log(`${index + 1}. ${doc.title}`);
console.log(` Score: ${doc.fusion_score || 'N/A'}, Tokens: ${doc.token_count}`);
});
// Example: Show RAG sources in your UI
const ragPanel = document.getElementById('ragPanel');
if (ragData.documents.length > 0) {
ragPanel.style.display = 'block';
ragPanel.innerHTML = `
Sources Used (${ragData.count || ragData.documents.length})
${ragData.documents.map((doc, i) => `
<div>
${i + 1}. ${doc.title}
Score: ${doc.fusion_score || 'N/A'} | ${doc.token_count} tokens
</div>
`).join('')}
`;
}
}
};
Initialization
CallManager Constructor
const callManager = new CallManager(callbacks, config);
| Parameter | Type | Description |
|---|---|---|
| callbacks | Object | Required - Object containing callback functions |
| config | Object | Optional configuration object |
Configuration Options
| Option | Type | Description | Default |
|---|---|---|---|
| characterRole | String | Display name for the AI character in conversation history | Character name |
| personRole | String | Display name for the user in conversation history | "You" |
| microphoneId | String | Preferred microphone device ID to use | System default |
| speakerId | String | Preferred speaker device ID to use | System default |
Example:
const callbacks = {
onCallStart: () => console.log("Call starting..."),
onStatusUpdate: (status) => console.log(status),
onCallError: () => console.log("Call error"),
onHangUp: () => console.log("Call ended"),
onConnected: () => console.log("Connected!")
};
const config = {
characterRole: "Assistant",
personRole: "User",
microphoneId: "device123",
speakerId: "speaker456"
};
const callManager = new CallManager(callbacks, config);
Next Steps
- Authentication Methods: See Call Initiation Methods to choose between client-side and server-side flows
- Backend Integration: See Backend API Reference for server-side implementation
- Getting Started: Check Quick Start for complete examples