IVR toolkit
Créez des flux d’appels entièrement personnalisés et automatisez chaque étape de vos interactions clients avec notre puissant kit d’outils d’actions SVI.
Utilisez des commandes simples pour lire de l’audio, collecter des chiffres, connecter des appelants, déclencher une logique, diffuser de l’audio vers des systèmes d’IA, et plus encore - le tout dans votre configuration de téléphonie existante.
- Intégrez l’IA, l’automatisation ou une logique back-end personnalisée
- Créez des flux SVI complets sans matériel supplémentaire
- Contrôlez le comportement des appels avec des commandes précises
Avantages de la fonctionnalité Kit d'outils SVI
Découvrez comment nos fonctionnalités vous aident à travailler plus intelligemment, à gagner du temps et à améliorer la communication de votre entreprise.
Automatisation des appels flexible
Définissez exactement comment chaque appel doit se comporter. Jouez des invites, recueillez des entrées, acheminez les appelants ou exécutez une logique conditionnelle - le tout à partir d'un kit d'outils clair et adapté aux développeurs.
Conçu pour les équipes de développement
Utilisez des actions structurées qui s'intègrent naturellement à votre logique back-end. Chaque action a des résultats prévisibles, une gestion des erreurs et des exemples pour vous aider à construire en toute confiance.
Fonctionne avec votre configuration existante
Aucune nouvelle infrastructure nécessaire. Utilisez votre numéro CallFactory et étendez simplement votre logique d'appel via l'API, vos scripts ou des outils d'automatisation internes.
Kit d'outils d'actions SVI
Cliquez sur une action pour voir sa description, sa signature et des exemples.
Répond à un appel entrant. Doit être appelé avant de lire de l'audio ou de collecter des entrées sur un appel entrant.
Description
- Marque l’appel comme répondu du côté de la téléphonie.
- Requis avant d’utiliser des actions comme
Play,PromptDigit,GatherDigits,Dial,Record, etc., sur les appels entrants.
Throws
InvalidOperationException- si l’appel a déjà été répondu.
Signature
void Answer();Example
protected override async Task
HandleCallAsync(CancellationToken ct)
{
// Toujours répondre en premier aux appels entrants
Answer();
await Play("welcome.wav", ct);
}
Lit un fichier audio pour l'appelant ou pour un canal sortant.
Description
- Lit un fichier audio (par exemple,
.wav) situé dans le répertoire audio du serveur. - Peut cibler l’appelant entrant ou un OutboundChannel spécifique.
Parameters
audioFile- Nom/chemin du fichier relatif au répertoire audio SVI.channel- (optionnel) Canal sortant sur lequel lire l’audio.ct- Jeton d’annulation ; annulé lorsque l’appelant ou le canal se déconnecte.
Returns
PlayResult.Success- Audio lu entièrement.PlayResult.Fail- Échec de la lecture (par exemple, fichier invalide).PlayResult.Cancel- Opération annulée (par exemple, l’appelant a raccroché).PlayResult.Error- Erreur inattendue pendant la lecture.
Throws
OperationCanceledException- Si ct est annulé pendant la lecture.- Autres exceptions de transport/IO selon l’implémentation.
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("Échec de la lecture du message de bienvenue (Résultat :
{Result})", result); return;
}
await Play("next_prompt.wav", ct);
}
Lit une invite audio et collecte un seul chiffre DTMF.
Description
- Lit une invite de menu (par exemple, ‘Appuyez sur 1 pour les ventes, 2 pour le support, 3 pour laisser un message’).
- Attend un seul chiffre DTMF : 0-9, *, ou #.
- Destiné aux sélections du menu principal.
Parameters
audioFile- Fichier d’invite à lire.timeoutSeconds- Combien de temps attendre un chiffre (par défaut 10).ct- Jeton d’annulation ; annulé lorsque l’appelant se déconnecte.
Returns
MenuResult.Successavec Digit défini lorsqu’un chiffre est reçu.MenuResult.Timeoutlorsqu’aucun chiffre n’est reçu danstimeoutSeconds.MenuResult.Cancellorsque l’opération est annulée.
Throws
OperationCanceledException- Si ct est annulé (par exemple, l’appelant raccroche).
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);
}
}
Lit une invite et collecte plusieurs chiffres DTMF (par exemple, numéro de compte, code PIN).
Description
- Lit une invite demandant à l’appelant d’entrer plusieurs chiffres.
- S’arrête lorsque soit :
maxDigitsest atteint
- Un chiffre de terminaison (par exemple, #) est pressé
- Le délai d’attente expire
Parameters
audioFile– Invite à lire (par exemple, “Veuillez entrer votre numéro de compte suivi de #”).maxDigits– Nombre maximum de chiffres à collecter avant d’arrêter.terminationDigits– Chaîne de chiffres qui terminent la collecte lorsqu’ils sont entrés.timeoutSeconds– Temps maximum d’attente pour l’entrée.ct– Jeton d’annulation.
Returns
- Tuple (
GatherResult Result,string? Digits) : GatherResult.Successet Digits définis lorsque l’entrée est collectée.GatherResult.Timeoutlorsqu’aucune entrée n’est reçue.GatherResult.Cancellorsque l’opération est annulée.GatherResult.Errorsur erreur inattendue.
Throws
OperationCanceledException- Si ct est annulé (l’appelant raccroche).
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);
}
}
Compose un ou plusieurs numéros de téléphone sortants et renvoie un OutboundChannel lorsqu'il est répondu.
Description
- Initie un appel sortant vers une destination unique ou vers plusieurs destinations en parallèle.
- Pour plusieurs destinations, le premier à répondre gagne ; tous les autres sont annulés.
Parameters
destination/destinations– Numéro(s) de téléphone à composer.callerId– Numéro à présenter comme identifiant de l’appelant.ringTimeoutSeconds– Temps maximum de sonnerie avant d’abandonner.ct– Jeton d’annulation.
Returns
- Destination unique :
(DialerResult Result, OutboundChannel? Channel)- Destinations multiples :
(DialerResult Result, string? AnsweredDestination, OutboundChannel? Channel)DialerResultpeut être : Init, Ringing, Answered, Busy, Rejected, NoAnswer, Failed, Cancel.
Throws
OperationCanceledException– Si l’opération est annulée pendant la composition.
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);
Exemple (destination unique)
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);
}
}
Exemple (destinations multiples)
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("Connecté à l'agent commercial {Number}", answeredNumber);
await Connect(channel, ct);
}
else
{
await Play("sales_unavailable.wav", ct);
await HandleVoicemail(ct);
}
}
Relie l'audio entre deux canaux.
Description
- Pour les flux entrants : relie l’appelant entrant à un canal sortant.
- Pour les scénarios sortants uniquement : relie deux canaux sortants ensemble.
- Bloque jusqu’à ce qu’un côté raccroche ou que la connexion soit autrement terminée.
Parameters
channel– Canal sortant à connecter à l’appel entrant.primary,secondary– Deux canaux sortants à relier.ct– Jeton d’annulation.
Returns
ConnectResult.Success– Connexion terminée normalement (appel terminé).ConnectResult.Error– La connexion n’a pas pu être établie ou a échoué.
Throws
OperationCanceledException– Si ct est annulé pendant la connexion.
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("Connexion terminée avec le résultat : {Result}", connectResult);
}
else
{
await Play("agent_unavailable.wav", ct);
}
await Hangup(ct);
}
Enregistre l'audio de l'appelant ou d'un canal sortant.
Description
- Commence l’enregistrement soit de l’appelant entrant, soit d’un canal sortant spécifique.
- Se termine lorsque :
timeLimitSecondsest atteint
- Un chiffre de terminaison est pressé (si configuré)
- L’appelant ou le canal raccroche
Parameters
timeLimitSeconds– Durée maximale d’enregistrement.fileName– Nom de fichier personnalisé optionnel (généré automatiquement si null).terminationDigits– Chiffres DTMF qui arrêtent l’enregistrement.playBeep– Si un bip doit être joué avant l’enregistrement.channel– Canal sortant optionnel.ct– Jeton d’annulation.
Returns
- Tuple (
RecordResult Result,string? FilePath) : RecordResult.SuccessavecFilePathenregistré.RecordResult.Timeout,MaxDurationReached,TerminationDigit,Cancel,Error.
Throws
OperationCanceledExceptionsi annulé.
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("Messagerie vocale enregistrée dans {Path}", filePath);
await Play("thank_you_message_received.wav", ct);
}
else
{
Logger.LogWarning("Échec de l'enregistrement : {Result}", recordResult);
await Play("recording_failed.wav", ct);
}
await Hangup(ct);
}
Rejette un appel entrant avec un code de motif SIP et termine l'appel.
Description
- Utilisé pour le filtrage d’appels, le blocage et le comportement hors horaires.
- Renvoie un code d’erreur SIP à l’opérateur en amont.
Parameters
reason–RejectReason.Busy,.TemporarilyUnavailable,.Declined.ct– Jeton d’annulation.
Returns
RejectResult.Success– Appel rejeté.RejectResult.AlreadyAnswered– Appel déjà répondu.RejectResult.Error– Échec du rejet.
Throws
OperationCanceledExceptionsi annulé.
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;
}
// Flux normal
Answer();
await Play("welcome.wav", ct);
}
Termine proprement l'appel actif.
Description
- Termine l’appel du côté SVI.
Returns
HangupResult.Success– Appel terminé avec succès.HangupResult.NotAnswered– Jamais répondu.HangupResult.AlreadyDisconnected– L’appelant a raccroché.HangupResult.Error– Échec du raccrochage.
Throws
OperationCanceledExceptionsi annulé.
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("Résultat du raccrochage : {Result}", result);
}
Met en pause l'exécution pendant un nombre donné de secondes.
Description
- Attend pendant durationSeconds tout en gardant l’appel ouvert.
- Peut être interrompu par une entrée DTMF selon l’implémentation.
Parameters
durationSeconds– Durée en secondes.ct– Jeton d’annulation.
Returns
PauseResult.Success– Pause terminée normalement.PauseResult.Interrupted– L’appelant a appuyé sur une touche pendant la pause (si pris en charge).PauseResult.Cancel– Opération annulée.PauseResult.Error– Échec de la pause.
Throws
OperationCanceledException– Si ct est annulé.
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);
}
Envoie un signal d'occupation à l'appelant et termine l'appel.
Description
- Présente une tonalité d’occupation standard.
- Couramment utilisé lorsque tous les agents/lignes sont occupés.
Returns
BusyResult.Success– Signal d’occupation envoyé et appel terminé.BusyResult.Cancel– Opération annulée.BusyResult.Error– Échec de l’envoi du signal d’occupation ou de la fin de l’appel.
Throws
OperationCanceledException– Si ct est annulé.
Signature
Task<BusyResult> Busy(CancellationToken ct = default);
Example
protected override async Task HandleCallAsync(CancellationToken ct)
{
if (AllAgentsBusy())
{
var result = await Busy(ct);
Logger.LogInformation("Résultat d'occupation : {Result}", result);
return;
}
// Sinon, poursuivre avec le flux normal
Answer();
await Play("welcome.wav", ct);
}
Commence à diffuser l'audio en direct de l'appel vers un point de terminaison externe (par exemple, IA ou moteur STT).
Description
- Ouvre un flux multimédia en temps réel de l’appel vers l’url donnée (par exemple, point de terminaison WebSocket).
- Typiquement utilisé pour envoyer de l’audio à :
- un assistant IA,
- un moteur de synthèse vocale,
- un service d’analyse/surveillance personnalisé.
- Un seul flux actif par appel est recommandé.
Parameters
url– Point de terminaison de streaming cible (par exemple,wss://ai.callfactory.nl/voice-stream).options– Configuration de streaming optionnelle (direction, métadonnées, nom).ct– Jeton d’annulation. Si annulé, le flux est arrêté.
Throws
OperationCanceledException– Si ct annulé pendant la configuration.- Exceptions de connexion/transport selon l’implémentation.
Signatures
Task<StreamResult> StartStream(
string url,
StreamOptions? options = null,
CancellationToken ct = default
);
Paramètres
public class StreamOptions
{
public string? Name { get; set; } //
Nom de flux optionnel
public StreamDirection Direction { get; set; } =
StreamDirection.Both;
public Dictionary<string, string>? Metadata { get; set; }
}
public enum StreamDirection
{
Inbound, // De l'appelant vers l'IA
Outbound, // De l'agent/système vers l'IA
Both // Les deux
}
Retours
public enum StreamResult
{
Started, // Flux démarré avec succès
Stopped, // Flux arrêté avec succès (pour StopStream)
AlreadyStarted, // Un flux est déjà actif
NotActive, // Aucun flux actif (pour StopStream)
Error // Échec du démarrage/arrêt
}
Example
protected override async Task
HandleCallAsync(CancellationToken ct)
{
Answer();
// Commencer à diffuser l'audio de l'appelant vers l'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("Échec du démarrage du flux IA :
{Result}", streamResult);
await Play("ai_unavailable.wav", ct);
await Hangup(ct);
return;
}
await Play("connected_to_ai.wav", ct);
// Continuer la logique SVI pendant que le streaming est actif...
var (menuResult, digit) = await
PromptDigit("ai_menu.wav", 30, ct);
if (menuResult == MenuResult.Success && digit == '0')
{
// L'appelant veut un agent humain
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);
}
}
Arrête un flux audio actif qui a été précédemment démarré avec StartStream.
Description
- Arrête proprement le flux multimédia actif.
- Ne raccroche pas l’appel - arrête seulement l’envoi d’audio.
- Sûr à appeler même si aucun flux n’est actif (renvoie
NotActive).
Parameters
ct– Jeton d’annulation.
Returns
StreamResult.Stopped– Flux arrêté avec succès.StreamResult.NotActive– Aucun flux actif trouvé.StreamResult.Error– Échec de l’arrêt du flux.
Throws
OperationCanceledException– Sictest annulé.
Signatures
Task<StreamResult> StopStream(
CancellationToken ct = default);
Example
private async Task TransferToHuman(CancellationToken ct)
{
// Arrêter le streaming IA avant de transférer à l'humain
var stopResult = await StopStream(ct);
Logger.LogInformation("Résultat de 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);
}
}
Pourquoi c'est important
Le kit d’outils SVI donne à votre équipe un contrôle complet sur les flux d’appels. Des menus simples aux interactions complexes pilotées par l’IA - tout est possible avec notre bibliothèque d’actions.
Ces outils sont particulièrement utiles pour les équipes créant des solutions de téléphonie personnalisées, implémentant des intégrations d’IA ou étendant les systèmes existants avec une logique d’appel avancée.
Cette fonctionnalité est incluse gratuitement avec chaque numéro d’entreprise français ou numéro international.
En savoir plus sur d'autres fonctionnalités
Trouvez plus d'informations sur nos fonctionnalités qui peuvent booster les communications de votre entreprise.
FAQ du Kit d'outils SVI
Obtenez des réponses claires sur le kit d’outils SVI et son fonctionnement pour votre entreprise.
Vous pouvez créer des flux en utilisant nos actions SVI dans votre tableau de bord. Chaque action comprend des exemples, des signatures et un comportement prévisible, afin que vous puissiez implémenter une logique sans avoir besoin de nouveau matériel de téléphonie.
Vous pouvez créer des flux simples sans codage, mais le kit d’outils est conçu pour les équipes qui souhaitent automatiser ou intégrer une logique. Les développeurs peuvent utiliser des actions structurées pour déclencher des invites, capturer des chiffres ou connecter des appelants par programmation.
Oui. Vous pouvez déclencher des appels API, envoyer des données à votre back-end ou diffuser de l’audio vers des services d’IA ou de STT. Le kit d’outils s’intègre naturellement à votre infrastructure existante.
Absolument. Vous n’avez pas besoin de changer votre configuration. Toutes les actions SVI fonctionnent avec vos numéros Callfactory, votre routage et vos paramètres d’appel existants.
Oui. Vous pouvez créer et prévisualiser vos flux en toute sécurité. Le kit d’outils vous permet de simuler des invites, la collecte d’entrées et le comportement de routage avant d’activer les modifications pour les appelants réels.
Vous décidez du comportement. Vous pouvez rejouer une invite, router vers la messagerie vocale, connecter au support ou terminer l’appel. Chaque action SVI prend en charge la gestion des erreurs personnalisée.
Oui. Chaque action inclut la gestion des délais d’attente et une logique de repli optionnelle. Vous pouvez définir ce qui se passe lorsqu’aucune entrée n’est reçue ou lorsqu’un appelant raccroche.
Oui. Le kit d’outils a été conçu pour enchaîner les actions. Vous pouvez jouer de l’audio, recueillir des chiffres, exécuter une logique, appeler une API et transférer des appelants - le tout dans un seul flux.
Oui. Le système est conçu pour la fiabilité et l’échelle. Que vous dirigiez une petite entreprise ou un centre d’appels à volume élevé, toutes les actions offrent des performances prévisibles.
Si votre équipe a besoin de conseils, nous pouvons vous aider à revoir votre conception de flux, tester votre configuration ou soutenir une logique de routage plus avancée.









