The Recall AI SDK provides a powerful Bot class for creating and managing bots that can join video meetings, record content, and extract data.
Initializing the SDK
First, initialize the Recall SDK with your API key and region:
import { Recall } from '@recall-ai/sdk';
const recall = new Recall({
apiKey: 'your-api-key',
region: 'us-west-2'
});
Creating a bot
Create a bot with a meeting URL
Use the create method to send a bot to a meeting:const bot = await recall.bot.create({
meeting_url: 'https://zoom.us/j/123456789',
bot_name: 'My Recording Bot'
});
console.log(bot.id); // Bot ID for future reference
Configure bot settings
Customize the bot’s behavior with additional configuration:const bot = await recall.bot.create({
meeting_url: 'https://meet.google.com/abc-defg-hij',
bot_name: 'Sales Call Recorder',
recording_mode: 'speaker_view',
recording_mode_options: {
participant_video_when_screenshare: 'hide',
start_recording_on: 'bot_join'
},
transcription_options: {
provider: 'assembly_ai'
}
});
Schedule a bot for later
Schedule a bot to join at a specific time:const scheduledBot = await recall.bot.create({
meeting_url: 'https://teams.microsoft.com/l/meetup-join/...',
bot_name: 'Future Meeting Bot',
join_at: new Date('2024-12-25T10:00:00Z')
});
Bot configuration parameters
Basic parameters
The URL of the meeting for the bot to join. Supports Zoom, Google Meet, Microsoft Teams, and other platforms.
The display name for the bot in the meeting. Defaults to “Meeting Bot”.
Schedule the bot to join at a specific time. If not provided, the bot joins immediately.
Recording configuration
The recording layout mode:
speaker_view - Focus on the active speaker
gallery_view - Show all participants
audio_only - Record only audio
Additional recording options:{
participant_video_when_screenshare?: string; // 'hide' or 'show'
start_recording_on?: string; // 'bot_join' or 'manual'
}
Transcription settings
Configure transcription provider:{
provider: string; // 'assembly_ai', 'deepgram', etc.
}
Real-time features
Enable real-time transcription streaming:{
destination_url?: string;
partial_results?: boolean;
enhanced_diarization?: boolean;
}
Configure real-time media streaming:{
rtmp_destination_url?: string;
websocket_video_destination_url?: string;
websocket_audio_destination_url?: string;
websocket_speaker_timeline_destionation_url?: string;
websocket_speaker_timeline_exclude_null_speaker?: boolean;
webhook_call_events_destination_url?: string;
webhook_chat_messages_destination_url?: string;
}
Visual customization
Customize the bot’s video appearance:{
in_call_recording?: {
kind: string;
b64_data: string; // Base64 encoded image
};
in_call_not_recording?: {
kind: string;
b64_data: string;
};
}
Get detailed information about a specific bot:
const botInfo = await recall.bot.retrieve({ id: 'bot-id' });
console.log(botInfo.status); // Current bot status
console.log(botInfo.meeting_url); // Meeting details
Listing bots
Query and filter your bots:
List all bots
Filter by status
Filter by date range
Filter by meeting URL
const bots = await recall.bot.list({});
bots.forEach(bot => {
console.log(`${bot.id}: ${bot.status}`);
});
const activeBots = await recall.bot.list({
status: 'in_call_recording'
});
const recentBots = await recall.bot.list({
join_at_after: new Date('2024-01-01'),
join_at_before: new Date('2024-12-31')
});
const zoomBots = await recall.bot.list({
meeting_url: 'https://zoom.us/j/123456789'
});
Bot status values
Bots progress through various states during their lifecycle:
| Status | Description |
|---|
ready | Bot is created and ready to join |
joining_call | Bot is attempting to join the meeting |
in_waiting_room | Bot is waiting to be admitted |
in_call_not_recording | Bot has joined but not yet recording |
recording_permission_allowed | Recording permission granted |
recording_permission_denied | Recording permission denied |
in_call_recording | Bot is actively recording |
recording_done | Recording has finished |
call_ended | Meeting has ended |
done | All processing complete |
fatal | Bot encountered an error |
media_expired | Recording media has expired |
analysis_done | Post-recording analysis complete |
analysis_failed | Analysis failed |
Managing scheduled bots
Update a scheduled bot
Modify a bot’s configuration before it joins:
const updated = await recall.bot.updateScheduledBot({
id: 'bot-id',
bot_name: 'Updated Bot Name',
join_at: new Date('2024-12-25T15:00:00Z'),
recording_mode: 'gallery_view'
});
You can only update scheduled bots that haven’t joined the meeting yet. Bots with status ready or joining_call can be updated.
Delete a scheduled bot
Cancel a scheduled bot before it joins:
await recall.bot.deleteScheduledBot({ id: 'bot-id' });
Bot intelligence
Retrieve AI-generated insights from the bot’s recording:
const intelligence = await recall.bot.getBotIntellienge({ id: 'bot-id' });
console.log(intelligence.summary);
console.log(intelligence.action_items);
console.log(intelligence.key_points);
Intelligence is available once the bot status reaches analysis_done.
Bot logs
Debug bot behavior by retrieving detailed logs:
const logs = await recall.bot.getBotLogs({ id: 'bot-id' });
logs.forEach(log => {
console.log(`[${log.timestamp}] ${log.level}: ${log.message}`);
});
Chat messages
Retrieve chat messages from the meeting:
const messages = await recall.bot.listChatMessages({
id: 'bot-id',
ordering: '-created_at'
});
messages.forEach(msg => {
console.log(`${msg.sender}: ${msg.message}`);
});
let cursor = null;
let allMessages = [];
do {
const response = await recall.bot.listChatMessages({
id: 'bot-id',
cursor: cursor
});
allMessages = allMessages.concat(response.results);
cursor = response.next_cursor;
} while (cursor);
Output audio during call
Make the bot play audio during an active call:
// Convert audio file to base64
const audioBase64 = fs.readFileSync('audio.mp3').toString('base64');
await recall.bot.outputAudio({
id: 'bot-id',
kind: 'audio/mp3',
b64_data: audioBase64
});
The bot must be in an active call (in_call_recording or in_call_not_recording status) to output audio.
Best practices
Monitor bot status
Regularly check the bot status to handle any issues promptly, especially recording_permission_denied and fatal states.
Handle waiting rooms
Be prepared to admit bots from waiting rooms, either manually or through automated workflows.
Use meaningful names
Give bots clear, descriptive names so meeting participants understand their purpose.
Clean up media
Delete bot media when no longer needed to manage storage costs (see the managing recordings guide).
Complete example
Here’s a complete workflow for creating and monitoring a bot:
import { Recall } from '@recall-ai/sdk';
const recall = new Recall({
apiKey: process.env.RECALL_API_KEY,
region: 'us-west-2'
});
async function recordMeeting(meetingUrl) {
try {
// Create bot
const bot = await recall.bot.create({
meeting_url: meetingUrl,
bot_name: 'Sales Meeting Recorder',
recording_mode: 'speaker_view',
transcription_options: {
provider: 'assembly_ai'
},
real_time_transcription: {
destination_url: 'https://yourapp.com/webhooks/transcript',
enhanced_diarization: true
}
});
console.log(`Bot created: ${bot.id}`);
// Monitor bot status
let status = 'ready';
while (!['done', 'fatal', 'call_ended'].includes(status)) {
await new Promise(resolve => setTimeout(resolve, 5000));
const botInfo = await recall.bot.retrieve({ id: bot.id });
status = botInfo.status;
console.log(`Bot status: ${status}`);
if (status === 'recording_permission_denied') {
console.error('Recording permission denied!');
break;
}
}
// Get final data
if (status === 'done') {
const transcript = await recall.bot.getTranscript({
id: bot.id,
enhanced_diarization: true
});
const intelligence = await recall.bot.getBotIntellienge({ id: bot.id });
return { transcript, intelligence };
}
} catch (error) {
console.error('Error recording meeting:', error);
throw error;
}
}
// Usage
recordMeeting('https://zoom.us/j/123456789')
.then(data => console.log('Recording complete:', data))
.catch(err => console.error('Recording failed:', err));