IVR toolkit
Crea flussi di chiamate completamente personalizzati e automatizza ogni fase delle tue interazioni con i clienti con il nostro potente toolkit di azioni IVR.
Usa comandi semplici per riprodurre audio, raccogliere cifre, connettere chiamanti, attivare logiche, trasmettere audio a sistemi di IA e molto altro - tutto all’interno della tua configurazione telefonica esistente.
- Integra IA, automazione o logica back-end personalizzata
- Crea flussi IVR completi senza hardware aggiuntivo
- Controlla il comportamento delle chiamate con comandi precisi
Vantaggi della funzionalità Toolkit IVR
Scopri come le nostre funzionalità ti aiutano a lavorare in modo più intelligente, risparmiare tempo e migliorare il modo in cui la tua azienda comunica.
Automazione delle chiamate flessibile
Definisci esattamente come deve comportarsi ogni chiamata. Riproduci messaggi, raccogli input, indirizza i chiamanti o esegui logiche condizionali - tutto da un unico toolkit chiaro e adatto agli sviluppatori.
Progettato per i team di sviluppo
Usa azioni strutturate che si adattano naturalmente alla tua logica back-end. Ogni azione ha risultati prevedibili, gestione degli errori ed esempi per aiutarti a costruire con sicurezza.
Funziona con la tua configurazione esistente
Nessuna nuova infrastruttura necessaria. Usa il tuo numero Callfactory e semplicemente estendi la tua logica di chiamata tramite l'API, i tuoi script o strumenti di automazione interni.
Toolkit di Azioni IVR
Clicca su un'azione per visualizzare la sua descrizione, firma ed esempi.
Risponde a una chiamata in arrivo. Deve essere chiamato prima di riprodurre audio o raccogliere input su una chiamata in arrivo.
Description
- Segna la chiamata come risposta dal lato telefonia.
- Richiesto prima di usare azioni come
Play,PromptDigit,GatherDigits,Dial,Record, ecc., sulle chiamate in arrivo.
Throws
InvalidOperationException- se la chiamata è già stata risposta.
Signature
void Answer();Example
protected override async Task
HandleCallAsync(CancellationToken ct)
{
// Rispondi sempre prima alle chiamate in arrivo
Answer();
await Play("welcome.wav", ct);
}
Riproduce un file audio al chiamante o a un canale in uscita.
Description
- Riproduce un file audio (es.
.wav) situato nella directory audio del server. - Può essere indirizzato al chiamante in arrivo o a uno specifico OutboundChannel.
Parameters
audioFile- Nome/percorso del file relativo alla directory audio IVR.channel- (opzionale) Canale in uscita su cui riprodurre l’audio.ct- Token di cancellazione; cancellato quando il chiamante o il canale si disconnette.
Returns
PlayResult.Success- Audio riprodotto completamente.PlayResult.Fail- Riproduzione fallita (es. file non valido).PlayResult.Cancel- Operazione cancellata (es. il chiamante ha riagganciato).PlayResult.Error- Errore imprevisto durante la riproduzione.
Throws
OperationCanceledException- Se ct viene cancellato durante la riproduzione.- Altre eccezioni di trasporto/IO a seconda dell’implementazione.
Signatures
Task<PlayResult> Play(
string audioFile,
CancellationToken ct = default);
Task<PlayResult> Play(
string audioFile,
OutboundChannel channel,
CancellationToken ct = default);
Example
protected override async Task HandleCallAsync(CancellationToken ct)
{
Answer();
var result = await Play("welcome.wav", ct);
if (result != PlayResult.Success)
{
Logger.LogWarning("Impossibile riprodurre il messaggio di benvenuto (Risultato:
{Result})", result); return;
}
await Play("next_prompt.wav", ct);
}
Riproduce un messaggio audio e raccoglie una singola cifra DTMF.
Description
- Riproduce un messaggio di menu (es. ‘Premi 1 per le vendite, 2 per il supporto, 3 per lasciare un messaggio’).
- Attende una singola cifra DTMF: 0-9, *, o #.
- Destinato alle selezioni del menu principale.
Parameters
audioFile- File del messaggio da riprodurre.timeoutSeconds- Quanto tempo attendere una cifra (predefinito 10).ct- Token di cancellazione; cancellato quando il chiamante si disconnette.
Returns
MenuResult.Successcon Digit impostato quando viene ricevuta una cifra.MenuResult.Timeoutquando non viene ricevuta alcuna cifra entrotimeoutSeconds.MenuResult.Cancelquando l’operazione viene cancellata.
Throws
OperationCanceledException- Se ct viene cancellato (es. il chiamante riaggancia).
Signatures
Task<(MenuResult Result, char? Digit)> PromptDigit(
string audioFile,
int timeoutSeconds = 10,
CancellationToken ct = default);
Example
protected override async Task HandleCallAsync(CancellationToken ct)
{
Answer();
await Play("welcome.wav", ct);
var (menuResult, digit) = await PromptDigit(
"main_menu.wav",
timeoutSeconds: 10,
ct);
if (menuResult == MenuResult.Success && digit.HasValue)
{
switch (digit.Value)
{
case '1':
await HandleSales(ct);
break;
case '2':
await HandleSupport(ct);
break;
default:
await Play("invalid_option.wav", ct);
await Hangup(ct);
break;
}
}
else if (menuResult == MenuResult.Timeout)
{
await Play("no_input_goodbye.wav", ct);
await Hangup(ct);
}
else
{
await Play("system_error.wav", ct);
await Hangup(ct);
}
}
Riproduce un messaggio e raccoglie più cifre DTMF (es. numero conto, PIN).
Description
- Riproduce un messaggio chiedendo al chiamante di inserire diverse cifre.
- Si ferma quando:
- viene raggiunto
maxDigits
- viene raggiunto
- viene premuta una cifra di terminazione (es. #)
- scade il timeout
Parameters
audioFile– Messaggio da riprodurre (es. “Inserisci il tuo numero di conto seguito da #”).maxDigits– Numero massimo di cifre da raccogliere prima di fermarsi.terminationDigits– Stringa di cifre che terminano la raccolta quando inserite.timeoutSeconds– Tempo massimo di attesa per l’input.ct– Token di cancellazione.
Returns
- Tuple (
GatherResult Result,string? Digits): GatherResult.Successe Digits impostati quando l’input è raccolto.GatherResult.Timeoutquando non viene ricevuto alcun input.GatherResult.Cancelquando l’operazione viene cancellata.GatherResult.Errorin caso di errore imprevisto.
Throws
OperationCanceledException- Se ct viene cancellato (il chiamante riaggancia).
Signatures
Task<(GatherResult Result, string? Digits)> GatherDigits(
string audioFile,
int maxDigits = 20,
string terminationDigits = "#",
int timeoutSeconds = 30,
CancellationToken ct = default);
Example
protected override async Task
HandleCallAsync(CancellationToken ct)
{
Answer();
await Play("welcome.wav", ct);
var (result, digits) = await GatherDigits(
"enter_account.wav",
maxDigits: 10,
terminationDigits: "#",
timeoutSeconds: 30,
ct);
if (result == GatherResult.Success && !string.IsNullOrEmpty(digits))
{
await ProcessAccountNumber(digits, ct);
}
else if (result == GatherResult.Timeout)
{
await Play("no_input_goodbye.wav", ct);
await Hangup(ct);
}
else
{
await Play("system_error.wav", ct);
await Hangup(ct);
}
}
Chiama uno o più numeri di telefono in uscita e restituisce un OutboundChannel quando viene risposta.
Description
- Avvia una chiamata in uscita verso una singola destinazione o verso più destinazioni in parallelo.
- Per destinazioni multiple, il primo che risponde vince; tutte le altre vengono cancellate.
Parameters
destination/destinations– Numero(i) di telefono da chiamare.callerId– Numero da presentare come ID chiamante.ringTimeoutSeconds– Tempo massimo di squillo prima di rinunciare.ct– Token di cancellazione.
Returns
- Singola destinazione:
(DialerResult Result, OutboundChannel? Channel)- Multiple destinazioni:
(DialerResult Result, string? AnsweredDestination, OutboundChannel? Channel)DialerResultpuò essere: Init, Ringing, Answered, Busy, Rejected, NoAnswer, Failed, Cancel.
Throws
OperationCanceledException– Se l’operazione viene cancellata durante la composizione.
Signatures
Task<(DialerResult Result, OutboundChannel? Channel)> Dial(
string destination,
string callerId,
int ringTimeoutSeconds = 60,
CancellationToken ct = default);
Task<(DialerResult Result, string? AnsweredDestination,
OutboundChannel? Channel)> Dial(
string[] destinations,
string callerId,
int ringTimeoutSeconds = 40,
CancellationToken ct = default);
Esempio (singola destinazione)
private async Task TransferToSupport(CancellationToken ct)
{
var (dialResult, channel) = await Dial(
destination: "18885554444",
callerId: Context.Ani,
ringTimeoutSeconds: 30,
ct);
if (dialResult == DialerResult.Answered && channel != null)
{
await Play("connecting_to_support.wav", ct);
await Connect(channel, ct);
}
else
{
await Play("support_unavailable.wav", ct);
await HandleVoicemail(ct);
}
}
Esempio (multiple destinazioni)
private async Task TransferToSalesHuntGroup(CancellationToken ct)
{
var salesTeam = new[]
{
"18885551111",
"18885552222",
"18885553333"
};
var (result, answeredNumber, channel) = await Dial(
destinations: salesTeam,
callerId: Context.Ani,
ringTimeoutSeconds: 40,
ct);
if (result == DialerResult.Answered && channel != null)
{
Logger.LogInformation("Connesso all'agente di vendita {Number}", answeredNumber);
await Connect(channel, ct);
}
else
{
await Play("sales_unavailable.wav", ct);
await HandleVoicemail(ct);
}
}
Collega l'audio tra due canali.
Description
- Per i flussi in arrivo: collega il chiamante in arrivo a un canale in uscita.
- Solo per scenari in uscita: collega due canali in uscita insieme.
- Blocca finché un lato non riaggancia o la connessione non viene altrimenti terminata.
Parameters
channel– Canale in uscita da connettere alla chiamata in arrivo.primary,secondary– Due canali in uscita da collegare.ct– Token di cancellazione.
Returns
ConnectResult.Success– Connessione terminata normalmente (chiamata terminata).ConnectResult.Error– Impossibile stabilire la connessione o connessione fallita.
Throws
OperationCanceledException– Se ct viene cancellato mentre connesso.
Signatures
Task<ConnectResult> Connect(
OutboundChannel channel,
CancellationToken ct = default);
Task<ConnectResult> Connect(
OutboundChannel primary,
OutboundChannel secondary,
CancellationToken ct = default);
Example
protected override async Task HandleCallAsync(CancellationToken ct)
{
Answer();
await Play("connecting_you_now.wav", ct);
var (dialResult, channel) = await Dial(
destination: "18885550000",
callerId: Context.Ani,
ringTimeoutSeconds: 30,
ct);
if (dialResult == DialerResult.Answered && channel != null)
{
var connectResult = await Connect(channel, ct);
Logger.LogInformation("Connessione terminata con risultato: {Result}", connectResult);
}
else
{
await Play("agent_unavailable.wav", ct);
}
await Hangup(ct);
}
Registra l'audio dal chiamante o da un canale in uscita.
Description
- Avvia la registrazione dal chiamante in arrivo o da uno specifico canale in uscita.
- Termina quando:
- viene raggiunto
timeLimitSeconds
- viene raggiunto
- viene premuta una cifra di terminazione (se configurata)
- il chiamante o il canale riaggancia
Parameters
timeLimitSeconds– Durata massima della registrazione.fileName– Nome file personalizzato opzionale (generato automaticamente se null).terminationDigits– Cifre DTMF che fermano la registrazione.playBeep– Se riprodurre un bip prima della registrazione.channel– Canale in uscita opzionale.ct– Token di cancellazione.
Returns
- Tuple (
RecordResult Result,string? FilePath): RecordResult.SuccessconFilePathsalvato.RecordResult.Timeout,MaxDurationReached,TerminationDigit,Cancel,Error.
Throws
OperationCanceledExceptionse cancellato.
Signatures
Task<(RecordResult Result, string? FilePath)> Record(
int timeLimitSeconds = 120,
string? fileName = null,
string? terminationDigits = null,
bool playBeep = true,
CancellationToken ct = default);
Task<(RecordResult Result, string? FilePath)> Record(
OutboundChannel channel,
int timeLimitSeconds = 120,
string? fileName = null,
string? terminationDigits = null,
bool playBeep = true,
CancellationToken ct = default);
Example
private async Task HandleVoicemail(CancellationToken ct)
{
await Play("leave_message_after_beep.wav", ct);
var (recordResult, filePath) = await Record(
timeLimitSeconds: 180,
fileName: null,
terminationDigits: "#",
playBeep: true,
ct: ct);
if (recordResult == RecordResult.Success && !string.IsNullOrEmpty(filePath))
{
Logger.LogInformation("Messaggio vocale salvato in {Path}", filePath);
await Play("thank_you_message_received.wav", ct);
}
else
{
Logger.LogWarning("Registrazione fallita: {Result}", recordResult);
await Play("recording_failed.wav", ct);
}
await Hangup(ct);
}
Rifiuta una chiamata in arrivo con un codice motivo SIP e termina la chiamata.
Description
- Usato per filtrare le chiamate, bloccare e gestire il comportamento fuori orario.
- Restituisce un codice di errore SIP all’operatore a monte.
Parameters
reason–RejectReason.Busy,.TemporarilyUnavailable,.Declined.ct– Token di cancellazione.
Returns
RejectResult.Success– Chiamata rifiutata.RejectResult.AlreadyAnswered– Chiamata già risposta.RejectResult.Error– Impossibile rifiutare.
Throws
OperationCanceledExceptionse cancellato.
Signatures
Task<RejectResult> Reject(
RejectReason reason = RejectReason.Busy,
CancellationToken ct = default);
Example
protected override async Task HandleCallAsync(CancellationToken ct)
{
if (IsBlockedNumber(Context.Ani))
{
await Reject(RejectReason.Declined, ct);
return;
}
if (!IsWithinBusinessHours(DateTime.UtcNow))
{
await Reject(RejectReason.TemporarilyUnavailable, ct);
return;
}
// Flusso normale
Answer();
await Play("welcome.wav", ct);
}
Termina in modo pulito la chiamata attiva.
Description
- Termina la chiamata dal lato IVR.
Returns
HangupResult.Success– Chiamata terminata con successo.HangupResult.NotAnswered– Mai risposto.HangupResult.AlreadyDisconnected– Il chiamante ha riagganciato.HangupResult.Error– Riaggancio fallito.
Throws
OperationCanceledExceptionse cancellato.
Signature
Task<HangupResult> Hangup(CancellationToken ct = default);
Example
protected override async Task HandleCallAsync(CancellationToken ct)
{
Answer();
await Play("goodbye.wav", ct);
var result = await Hangup(ct);
Logger.LogInformation("Risultato del riaggancio: {Result}", result);
}
Mette in pausa l'esecuzione per un dato numero di secondi.
Description
- Attende per durationSeconds mantenendo la chiamata aperta.
- Può essere interrotto da input DTMF a seconda dell’implementazione.
Parameters
durationSeconds– Durata in secondi.ct– Token di cancellazione.
Returns
PauseResult.Success– Pausa completata normalmente.PauseResult.Interrupted– Il chiamante ha premuto un tasto durante la pausa (se supportato).PauseResult.Cancel– Operazione cancellata.PauseResult.Error– Pausa fallita.
Throws
OperationCanceledException– Se ct viene cancellato.
Signatures
Task<PauseResult> Pause(
int durationSeconds,
CancellationToken ct = default
);
Example
protected override async Task HandleCallAsync(CancellationToken ct)
{
Answer();
await Play("please_wait.wav", ct);
var result = await Pause(3, ct);
if (result == PauseResult.Interrupted)
{
await Play("you_pressed_a_key.wav", ct);
}
else
{
await Play("thank_you_for_waiting.wav", ct);
}
await Hangup(ct);
}
Invia un segnale di occupato al chiamante e termina la chiamata.
Description
- Presenta un tono di occupato standard.
- Comunemente usato quando tutti gli agenti/linee sono occupati.
Returns
BusyResult.Success– Segnale di occupato inviato e chiamata terminata.BusyResult.Cancel– Operazione cancellata.BusyResult.Error– Impossibile inviare il segnale di occupato o terminare la chiamata.
Throws
OperationCanceledException– Se ct viene cancellato.
Signature
Task<BusyResult> Busy(CancellationToken ct = default);
Example
protected override async Task HandleCallAsync(CancellationToken ct)
{
if (AllAgentsBusy())
{
var result = await Busy(ct);
Logger.LogInformation("Risultato occupato: {Result}", result);
return;
}
// Altrimenti, procedi con il flusso normale
Answer();
await Play("welcome.wav", ct);
}
Avvia lo streaming dell'audio live della chiamata verso un endpoint esterno (es. IA o motore STT).
Description
- Apre un flusso multimediale in tempo reale dalla chiamata all’url dato (es. endpoint WebSocket).
- Tipicamente usato per inviare audio a:
- un assistente IA,
- un motore speech-to-text,
- un servizio di analisi/monitoraggio personalizzato.
- È raccomandato un solo flusso attivo per chiamata.
Parameters
url– Endpoint di streaming di destinazione (es.wss://ai.callfactory.nl/voice-stream).options– Configurazione di streaming opzionale (direzione, metadati, nome).ct– Token di cancellazione. Se cancellato, il flusso viene interrotto.
Throws
OperationCanceledException– Se ct cancellato durante la configurazione.- Eccezioni di connessione/trasporto a seconda dell’implementazione.
Firme
Task<StreamResult> StartStream(
string url,
StreamOptions? options = null,
CancellationToken ct = default
);
Parametri
public class StreamOptions
{
public string? Name { get; set; } //
Nome flusso opzionale
public StreamDirection Direction { get; set; } =
StreamDirection.Both;
public Dictionary<string, string>? Metadata { get; set; }
}
public enum StreamDirection
{
Inbound, // Dal chiamante all'IA
Outbound, // Dall'agente/sistema all'IA
Both // Entrambi
}
Ritorni
public enum StreamResult
{
Started, // Flusso avviato con successo
Stopped, // Flusso fermato con successo (per
StopStream)
AlreadyStarted, // Un flusso è già attivo
NotActive, // Nessun flusso attivo (per StopStream)
Error // Avvio/arresto fallito
}
Example
protected override async Task
HandleCallAsync(CancellationToken ct)
{
Answer();
// Avvia lo streaming dell'audio del chiamante all'IA
var streamResult = await StartStream(
url: "wss://ai.callfactory.nl/voice-stream",
options: new StreamOptions
{
Name = "support-ai",
Direction = StreamDirection.Inbound,
Metadata = new Dictionary<string, string>
{
["caller"] = Context.Ani,
["dnis"] = Context.Dnis
}
},
ct
);
if (streamResult != StreamResult.Started)
{
Logger.LogWarning("Impossibile avviare il flusso IA:
{Result}", streamResult);
await Play("ai_unavailable.wav", ct);
await Hangup(ct);
return;
}
await Play("connected_to_ai.wav", ct);
// Continua la logica IVR mentre lo streaming è attivo...
var (menuResult, digit) = await
PromptDigit("ai_menu.wav", 30, ct);
if (menuResult == MenuResult.Success && digit == '0')
{
// Il chiamante vuole un agente umano
await StopStream(ct);
await Play("transferring_to_human_agent.wav", ct);
await TransferToHuman(ct);
}
else
{
await Play("thank_you_goodbye.wav", ct);
await StopStream(ct);
await Hangup(ct);
}
}
Ferma un flusso audio attivo che è stato precedentemente avviato con StartStream.
Description
- Chiude in modo pulito il flusso multimediale attivo.
- Non riaggancia la chiamata - smette solo di inviare audio.
- Sicuro da chiamare anche se nessun flusso è attivo (restituisce
NotActive).
Parameters
ct– Token di cancellazione.
Returns
StreamResult.Stopped– Flusso fermato con successo.StreamResult.NotActive– Nessun flusso attivo trovato.StreamResult.Error– Impossibile fermare il flusso.
Throws
OperationCanceledException– Sectviene cancellato.
Signatures
Task<StreamResult> StopStream(
CancellationToken ct = default);
Example
private async Task TransferToHuman(CancellationToken ct)
{
// Ferma lo streaming IA prima di trasferire all'umano
var stopResult = await StopStream(ct);
Logger.LogInformation("Risultato StopStream: {Result}",
stopResult);
await Play("transferring_to_agent.wav", ct);
var (dialResult, channel) = await Dial(
destination: "18005550000",
callerId: Context.Ani,
ringTimeoutSeconds: 30,
ct
);
if (dialResult == DialerResult.Answered && channel !=
null)
{
await Connect(channel, ct);
}
else
{
await Play("agent_unavailable.wav", ct);
await Hangup(ct);
}
}
Perché è importante
Il toolkit IVR offre al tuo team il controllo completo sui flussi di chiamata. Dai menu semplici alle interazioni complesse guidate dall’IA - tutto è possibile con la nostra libreria di azioni.
Questi strumenti sono particolarmente utili per i team che costruiscono soluzioni telefoniche personalizzate, implementano integrazioni IA o estendono i sistemi esistenti con logiche di chiamata avanzate.
Questa funzione è inclusa gratuitamente in ogni numero aziendale o numero internazionale.
Scopri di più su altre funzionalità
Trova maggiori informazioni sulle nostre funzionalità che possono potenziare le comunicazioni della tua azienda.
FAQ Toolkit IVR
Ottieni risposte chiare sul toolkit IVR e su come funziona per la tua azienda.
Puoi creare flussi usando le nostre azioni IVR nella tua dashboard. Ogni azione include esempi, firme e comportamenti prevedibili, così puoi implementare logiche senza bisogno di nuovo hardware telefonico.
Puoi creare flussi semplici senza programmare, ma il toolkit è costruito per i team che vogliono automatizzare o integrare logiche. Gli sviluppatori possono usare azioni strutturate per attivare messaggi, catturare cifre o connettere chiamanti programmaticamente.
Sì. Puoi attivare chiamate API, inviare dati al tuo back-end o trasmettere audio a servizi di IA o STT. Il toolkit si adatta naturalmente alla tua infrastruttura esistente.
Assolutamente. Non hai bisogno di cambiare la tua configurazione. Tutte le azioni IVR funzionano con i tuoi numeri Callfactory esistenti, il routing e le impostazioni di chiamata.
Sì. Puoi costruire e visualizzare in anteprima i tuoi flussi in sicurezza. Il toolkit ti permette di simulare messaggi, raccolta di input e comportamenti di routing prima di attivare le modifiche per i chiamanti reali.
Tu decidi il comportamento. Puoi riprodurre nuovamente un messaggio, indirizzare alla segreteria, connettere al supporto o terminare la chiamata. Ogni azione IVR supporta la gestione degli errori personalizzata.
Sì. Ogni azione include la gestione dei timeout e una logica di fallback opzionale. Puoi definire cosa succede quando non viene ricevuto alcun input o quando un chiamante riaggancia.
Sì. Il toolkit è stato progettato per concatenare le azioni. Puoi riprodurre audio, raccogliere cifre, eseguire logiche, chiamare un’API e trasferire chiamanti - tutto in un unico flusso.
Sì. Il sistema è progettato per affidabilità e scalabilità. Che tu gestisca una piccola impresa o un call center ad alto volume, tutte le azioni offrono prestazioni prevedibili.
Se il tuo team ha bisogno di guida, possiamo aiutare a revisionare il design del tuo flusso, testare la tua configurazione o supportare logiche di routing più avanzate.









