Are you an LLM? You can read better optimized documentation at /docs/embedding/voice.md for this page in Markdown format
Voice & Dial-Out
A visitor clicks "Talk to us" and, seconds later, they're mid-conversation with your AI agent — no phone number, no app to install, just their browser. Or they'd rather take the call on their mobile, so the agent rings them. That's what voice chat and dial-out make possible, and this page shows you how they work in your widget.
If you haven't embedded the widget yet, start with the Quickstart first, then come back here.
What gets enabled and when
Both capabilities are opt-in switches on your agent's Web Chat trigger node (Configure tab → Capabilities): Enable voice chat and Enable dial-out (Call Me). When your widget loads, it calls /init and receives a capabilities object:
json
{ "voice_chat": true, "dial_out": false, "file_upload": true, "show_history": false, "allow_new_chat": true, "allow_export": false }If a switch is on but something it needs is missing — say, the agent has no chat model, or no phone number is connected for dial-out — the capability comes back false and you also receive a capability_warnings list explaining what's incomplete. When a capability is off, the widget hides the matching button automatically, so your visitors never see a broken control.
In-browser voice chat
When voice_chat is true, your visitors can speak to your agent directly in the browser over a real-time audio connection — no phone call needed. Voice runs on Perfox-managed infrastructure; there's nothing to host.
To enable it: turn on Enable voice chat and pick a voice mode:
| Mode | What the visitor sees |
|---|---|
| Nova animation (default) | An audio-reactive animation instead of the live transcript. Choose its Animation style: Cloud, Radial, Circle or Bars. The agent speaks everything. |
| Voice call | Like a phone call — the live transcript, the agent speaks everything, no cards, tables or charts. |
| Copilot (Beta) | Voice plus on-screen visuals — the agent speaks a short answer and shows cards, tables or charts in the chat. |
When the visitor starts a call, the widget first asks for microphone access, then opens the session. The mic stays muted until the agent's greeting finishes, so nobody talks over it. Behind the scenes the widget uses three endpoints:
| Endpoint | What it does |
|---|---|
POST /api/public/widget/voice/start | Opens a session and returns a room token + connection URL, the voice_session_id, and the voice mode to render. |
POST /api/public/widget/voice/inject_text | Pushes a typed text turn ({ voice_session_id, text }) into the live session. The widget uses it when the visitor types or attaches a file mid-call. |
POST /api/public/widget/voice/stop | Ends the session ({ voice_session_id }). |
Each call is recorded as three audio files — caller audio, AI audio, and a combined stereo mix — which you can play back from the conversation in Studio. Spoken turns are also saved to the transcript, so after a reload they replay as ordinary text.
/voice/start can refuse with:
| Status | Code | Cause |
|---|---|---|
| 403 | voice_chat_not_enabled | The switch is off. |
| 503 | voice_chat_prereq_failed | Something voice needs is missing — see remediation in the response. |
| 402 | out_of_credits | Your workspace has no credits left. |
| 429 | concurrent_voice_limit_reached | Too many voice sessions are running at once. |
Worked example
Setup: Acme Diagnostics has a support widget on their patient portal. Asha (their workspace admin) turns on Enable voice chat on the Web Chat trigger with the Voice call mode.
Action: Priya visits the portal and clicks the voice button. She allows her microphone, the widget calls /voice/start and joins the session, and after the greeting Priya asks about her appointment — the agent answers in real time.
Result: When Priya hangs up, the widget calls /voice/stop. The session ends, and the call's transcript and recordings appear on the conversation in Studio.
What just happened: The widget managed the entire session lifecycle — microphone, connect, conversation, disconnect — using the three endpoints above. Asha didn't write a single line of audio handling code.
Outbound dial-out
When dial_out is true, your widget can place an outbound phone call to a number your visitor provides — useful when a visitor prefers to talk over their mobile rather than through the browser.
To enable it: turn on Enable dial-out (Call Me) on your Web Chat trigger, and make sure a Plivo phone number for calls is connected on the Credentials page.
The widget sends:
POST /api/public/widget/call
{ "phone_number": "+919876543210", "conversation_id": "…", "customer_id": "…", "user_context": { … } }and gets back { call_id, status: "calling", phone }, where phone is the number actually dialled. Send numbers in international format; a number without a country code is read as an Indian number. The call uses the same agent persona and tools as the chat — so the conversation feels continuous.
| Status | Code | Cause |
|---|---|---|
| 400 | invalid_phone_number | The number can't be dialled — ask for it with the country code. |
| 403 | dial_out_not_enabled | The switch is off. |
| 503 | dial_out_prereq_failed / missing_credential | No phone number or calling credential is available — see remediation. |
Adapting your own UI to capabilities
You don't have to use the built-in widget buttons. Read the capabilities from the ready event and show or hide your own controls:
js
Perfox('on', 'ready', (info) => {
if (!info.capabilities.voice_chat) {
// hide your "Talk to me" CTA
}
});This lets you build a fully custom UI that stays in sync with what your agent actually has enabled. To drive voice from your own UI entirely, use the headless library.
What's next
You can now add voice chat and dial-out to your widget without managing audio sessions or phone infrastructure directly. To go further:
- Public Widget API — the full reference for every widget endpoint and init option.
- Events — the complete list of widget events (including
ready), so you can react to capabilities and session state in your own UI code. - File Upload — another opt-in capability that works the same way, good to set up alongside voice if your visitors share documents.