Skip to Content
Dial v1 live 🎉
SdkVoicemail

Voicemail

Record and manage voicemails for missed calls with persistent storage on-chain.

How It Works

When a call is missed and the caller chooses to leave a voicemail:

  1. Audio is recorded from the caller
  2. Voicemail metadata is stored on-chain
  3. Audio file is stored on decentralized storage (IPFS)
  4. Recipient receives notification of new voicemail

Recording Voicemail

After Missed Call

// Listen for missed call dial.on('call:missed', async (call) => { // Prompt caller to leave voicemail const recording = await dial.voicemail.startRecording({ callId: call.id, maxDuration: 120 // seconds }); });

Manual Recording

const voicemail = await dial.voicemail.record({ to: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb', maxDuration: 120 }); // Stop recording manually await dial.voicemail.stopRecording(voicemail.id);

Voicemail Object

interface Voicemail { id: string; from: string; // Caller wallet address to: string; // Recipient wallet address audioUrl: string; // IPFS URL duration: number; // seconds timestamp: Date; isRead: boolean; transcription?: string; // AI-generated transcription }

Receiving Voicemails

Listen for New Voicemails

dial.on('voicemail:received', (voicemail) => { console.log(`New voicemail from ${voicemail.from}`); console.log(`Duration: ${voicemail.duration}s`); console.log(`Listen: ${voicemail.audioUrl}`); });

Get All Voicemails

const voicemails = await dial.voicemail.getAll({ limit: 20, unreadOnly: false });

Get Unread Voicemails

const unread = await dial.voicemail.getAll({ unreadOnly: true }); console.log(`You have ${unread.length} unread voicemails`);

Playing Voicemail

const voicemail = await dial.voicemail.get(voicemailId); // Play audio const audio = new Audio(voicemail.audioUrl); await audio.play(); // Mark as read await dial.voicemail.markAsRead(voicemail.id);

Transcription

AI-powered automatic transcription is available:

// Get voicemail with transcription const voicemail = await dial.voicemail.get(voicemailId); if (voicemail.transcription) { console.log('Transcription:', voicemail.transcription); } // Request transcription if not available if (!voicemail.transcription) { const transcription = await dial.voicemail.transcribe(voicemail.id); console.log('Transcription:', transcription.text); }

Voicemail Settings

Set Greeting

// Record custom greeting const greeting = await dial.voicemail.setGreeting({ audioFile: greetingFile, duration: 10 }); // Or use text-to-speech await dial.voicemail.setGreeting({ text: 'Hey, you\'ve reached my Dial. Leave a message!', voice: 'en-US-Standard-A' });

Get Current Greeting

const greeting = await dial.voicemail.getGreeting(); console.log('Greeting URL:', greeting.audioUrl);

Enable/Disable Voicemail

// Enable voicemail await dial.voicemail.enable(); // Disable voicemail await dial.voicemail.disable(); // Check status const isEnabled = await dial.voicemail.isEnabled();

Voicemail Management

Delete Voicemail

await dial.voicemail.delete(voicemailId);

Archive Voicemail

await dial.voicemail.archive(voicemailId); // Get archived voicemails const archived = await dial.voicemail.getArchived();

Save Voicemail

// Download voicemail file const blob = await dial.voicemail.download(voicemailId); // Save to device const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = `voicemail-${voicemailId}.mp3`; a.click();

Complete Example: Voicemail Inbox

import { useState, useEffect } from 'react'; import { DialClient, Voicemail } from '@dial/sdk'; export function VoicemailInbox({ dial }) { const [voicemails, setVoicemails] = useState<Voicemail[]>([]); const [playing, setPlaying] = useState<string | null>(null); const [audio, setAudio] = useState<HTMLAudioElement | null>(null); useEffect(() => { loadVoicemails(); // Listen for new voicemails dial.on('voicemail:received', (voicemail) => { setVoicemails(prev => [voicemail, ...prev]); }); return () => { dial.off('voicemail:received'); if (audio) audio.pause(); }; }, [dial]); const loadVoicemails = async () => { const vms = await dial.voicemail.getAll({ limit: 50 }); setVoicemails(vms); }; const playVoicemail = async (voicemail: Voicemail) => { // Stop current playback if (audio) { audio.pause(); } // Play new voicemail const newAudio = new Audio(voicemail.audioUrl); await newAudio.play(); setAudio(newAudio); setPlaying(voicemail.id); // Mark as read if (!voicemail.isRead) { await dial.voicemail.markAsRead(voicemail.id); setVoicemails(prev => prev.map(vm => vm.id === voicemail.id ? { ...vm, isRead: true } : vm ) ); } // Handle end of playback newAudio.onended = () => { setPlaying(null); }; }; const stopPlayback = () => { if (audio) { audio.pause(); setPlaying(null); } }; const deleteVoicemail = async (id: string) => { await dial.voicemail.delete(id); setVoicemails(prev => prev.filter(vm => vm.id !== id)); }; const formatDuration = (seconds: number) => { const mins = Math.floor(seconds / 60); const secs = seconds % 60; return `${mins}:${secs.toString().padStart(2, '0')}`; }; const unreadCount = voicemails.filter(vm => !vm.isRead).length; return ( <div className="voicemail-inbox"> <h2>Voicemail ({unreadCount} unread)</h2> <div className="voicemail-list"> {voicemails.map(vm => ( <div key={vm.id} className={`voicemail-item ${!vm.isRead ? 'unread' : ''}`} > <div className="info"> <strong>{vm.from}</strong> <span>{vm.timestamp.toLocaleString()}</span> <span>{formatDuration(vm.duration)}</span> </div> {vm.transcription && ( <p className="transcription">{vm.transcription}</p> )} <div className="actions"> {playing === vm.id ? ( <button onClick={stopPlayback}>⏹️ Stop</button> ) : ( <button onClick={() => playVoicemail(vm)}>▶️ Play</button> )} <button onClick={() => deleteVoicemail(vm.id)}>🗑️ Delete</button> </div> </div> ))} </div> </div> ); }

Visual Voicemail

Get a visual representation of the audio waveform:

const waveform = await dial.voicemail.getWaveform(voicemailId); // Returns array of amplitude values (0-1) console.log(waveform.data); // [0.1, 0.3, 0.5, 0.7, ...]

Voicemail Notifications

Configure how you want to be notified:

await dial.voicemail.setNotificationPreferences({ push: true, // Push notifications email: true, // Email notifications includeTranscription: true // Include transcription in notification });

Storage and Costs

  • Voicemail audio is stored on IPFS (decentralized)
  • Metadata is stored on-chain
  • First 100 voicemails per month: free
  • Additional storage: 0.001 SOL per voicemail

Next Steps

Last updated on