> ## Documentation Index
> Fetch the complete documentation index at: https://docs.poly.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Web Calling

> A voice widget your visitors click to talk to your agent. End-to-end browser audio, no phone numbers.

Web Calling is a voice widget you embed on your website. Visitors click it, their browser connects to PolyAI over WebRTC, and they're in a call with your agent. No phone number, no app install, no callback queue. You configure it from **Configure > Web Calling** in Agent Studio.

<Frame caption="Web Calling launcher on a website">
  <img src="https://mintcdn.com/polyai/Q-CGDMOxOSX2tBiN/images/polyphone/hero-launcher.png?fit=max&auto=format&n=Q-CGDMOxOSX2tBiN&q=85&s=117b578b51899f4866b66a86d5faf4ac" alt="Web Calling launcher in the bottom-right of a website" style={{ maxWidth: '720px', width: '100%', margin: '0 auto', display: 'block' }} width="954" height="842" data-path="images/polyphone/hero-launcher.png" />
</Frame>

<div className="simplified-only">
  ## Embed it

  The install is a single script tag, generated for you under **Configure > Web Calling > Embed**. Paste it just before `</body>` on your site:

  ```html theme={"theme":{"light":"github-light","dark":"github-dark"}}
  <script src="https://messaging.poly.ai/widget/YOUR_UNIQUE_CODE.js"></script>
  ```

  The launcher shows up bottom-right on any page that loads the script. Styling, content, and agent changes take effect on the next page load; no re-embed needed.

  <Tip>
    **No website yet?** Use the [shareable page](/widgets/test) instead. It's a hosted URL on PolyAI's domain that anyone can call without logging in.
  </Tip>

  For Tag Manager, HTTPS, and the rest of the deployment details, see [Install on your site](/widgets/install). For styling, language, and consent options, see [Configure](/widgets/configure).
</div>

<div className="simplified-only">
  ## The agent's voice

  Web Calling uses whichever voice you've set under **Configure > Agent voice**. The same voice plays whether someone reaches you through the embedded widget or a [shareable page link](/polyphone/share).
</div>

<div className="full-only">
  ## Web Calling in the channel mix

  Web Calling is a voice channel, just like a phone number. The only thing that changes between them is how the audio gets to PolyAI.

  |                     | Web Calling                 | Numbers (telephony)                | Chat (webchat)                   | Voice (TTS settings)               |
  | ------------------- | --------------------------- | ---------------------------------- | -------------------------------- | ---------------------------------- |
  | What customers do   | Click a button on your site | Dial a phone number                | Type in a widget on your site    | (configures how your agent sounds) |
  | Modality            | Voice                       | Voice                              | Text                             | Shared by all voice channels       |
  | Where you set it up | Configure > Web Calling     | Channels > Numbers                 | Configure > Web Calling          | Channels > Voice                   |
  | Docs                | This section                | [Numbers](/telephony/introduction) | [Webchat](/webchat/introduction) | [Voice](/voice/introduction)       |

  Web Calling and Numbers are two ways into the same voice agent. They share the agent's spoken [voice](/voice/introduction) (set once, under **Channels > Voice**) and the same conversation logic. Switching a visitor between them doesn't require a separate flow.
</div>

## What the widget does

A consent step before the mic opens. Mute and end-call controls. The usual connecting / in-call / ended / error states. Only one call active per visitor across tabs. You can lock the widget to specific domains, run multiple variants per brand or region, and surface whichever languages your agent speaks.

## Compliance

Privacy and consent controls are off by default. Turn them on under [Widget configuration](/widgets/configure).

<Warning>
  You are responsible for meeting transparency, disclosure, and consent requirements in every jurisdiction you operate in (notably EU and some US states).
</Warning>

## Before you embed

| Need                                             | Notes                                                          |
| ------------------------------------------------ | -------------------------------------------------------------- |
| An Agent Studio project with a published variant | Sandbox is fine for testing; promote to Live for real traffic. |
| The domain(s) the widget will load on            | Used for the domain allow-list.                                |
| Access to your site's HTML or tag manager        | One script tag goes just before `</body>`.                     |
| **HTTPS** on the host page                       | Browsers block mic access on insecure origins.                 |

<span className="full-only">Phone and Chat widgets share a single Studio surface, which is why both live under **Configure > Web Calling**. Pick **Phone** or **Chat** when you create one.</span>

## Reference pages

<CardGroup cols={2}>
  <Card title="Widget" href="/widgets/configure" icon="phone">
    Create, style, and configure a Web Calling widget in Agent Studio.
  </Card>

  <Card title="Installation" href="/widgets/install" icon="code">
    Embed the script tag on your website with HTML or Tag Manager.
  </Card>

  <Card title="Test widget" href="/widgets/test" icon="circle-play">
    Walk through a real call from the editor preview link.
  </Card>

  <Card title="Troubleshooting" href="/widgets/troubleshooting" icon="wrench">
    Mic permissions, ICE failures, cross-tab lock, and more.
  </Card>
</CardGroup>

## Technical details

<Accordion title="How a call connects">
  Web Calling is loaded by a single `<script>` tag on your site. The script injects an iframe pinned to the bottom-right of the page. When a visitor clicks the launcher, the widget requests microphone access, opens a WebSocket to PolyAI's WebRTC gateway, and starts an Opus 48 kHz audio call with your agent.

  Two endpoints are involved:

  * **HTTPS** to PolyAI's widget script endpoint, which loads the widget JS.
  * **WSS** to the WebRTC gateway, which carries signaling and Opus audio to your agent.

  Only one Web Calling call can be active per browser at a time. The widget enforces this with a cross-tab lock so a visitor with multiple tabs open cannot start parallel calls.
</Accordion>

<div className="full-only">
  <Accordion title="Web Calling vs. telephony, side by side">
    |                   | Web Calling                            | Telephony                                 |
    | ----------------- | -------------------------------------- | ----------------------------------------- |
    | Transport         | WebRTC over the browser                | Phone network (PSTN / SIP)                |
    | Visitor sees      | A widget on your website               | A phone number to dial                    |
    | Latency / quality | Opus 48 kHz over WebRTC                | Carrier-dependent                         |
    | Setup             | Embed a script tag                     | Provision a number, configure SIP         |
    | Best for          | Web-first journeys, support deflection | Inbound call centers, omnichannel routing |

    You can run both: Web Calling for visitors already on your site, telephony for callers from anywhere else. Both connect to the same agent.
  </Accordion>
</div>

<Accordion title="Programmatic control (JavaScript SDK)">
  The widget script also exposes a `window.PolyphoneAPI` object that lets your page drive the call programmatically, useful when you want to trigger Web Calling from a custom button, an in-app event, or an existing chat experience.

  ```js theme={"theme":{"light":"github-light","dark":"github-dark"}}
  // Open the widget and start a call in one step.
  window.PolyphoneAPI.connectAndCall();

  // Pass context to the agent mid-call.
  window.PolyphoneAPI.sendInfo("user_signed_in", { userId: "abc123" });

  // React to lifecycle events.
  window.PolyphoneAPI.onConnected(() => console.log("Call connected"));
  window.PolyphoneAPI.onEnded(() => console.log("Call ended"));

  // Remove a handler when you're done.
  window.PolyphoneAPI.off("connected", myHandler);
  ```

  Available commands: `connect`, `disconnect`, `startCall`, `endCall`, `connectAndCall`, `mute`, `unmute`, `sendInfo`, `isConnected`, `getCurrentSession`, `destroy`. Event registration uses dedicated methods: `onReady`, `onConnecting`, `onConnected`, `onDisconnected`, `onRegistered`, `onUnregistered`, `onRinging`, `onAnswered`, `onEnded`, `onFailed`, `onMuted`, `onUnmuted`, `onCaptureAudio`, `onAudioEnded`, `onInfoSent`, `onInfoReceived`, `onTranscription`, `onError`. Use `off(eventName, handler)` to remove a registered handler.
</Accordion>

<Accordion title="Browser support">
  Web Calling uses standard WebRTC primitives. Verified browsers:

  | Browser           | Minimum version |
  | ----------------- | --------------- |
  | Chrome / Chromium | 72              |
  | Firefox           | 60              |
  | Safari (macOS)    | 14.1            |
  | Safari (iOS)      | 16              |
  | Edge              | 79              |

  Visitors on unsupported browsers see a disabled call button with a brief explanation. Mobile-browser and in-app-webview behavior can vary, so test in your intended deployment environment before launch.
</Accordion>

## Related pages

<div className="simplified-only">
  * [Voice](/voice/introduction), pick the voice your agent speaks with
  * [Agent Builder](/agent-builder/introduction), ask it to adjust Web Calling behavior in plain language
  * [Install on your site](/widgets/install), Tag Manager and HTTPS notes
  * [Configure](/widgets/configure), styling, language, consent
</div>

<div className="full-only">
  * [Voice](/voice/introduction), the agent's TTS voice, shared by Web Calling and telephony
  * [Numbers (telephony)](/telephony/introduction), the phone-network route into the same voice agent
  * [Webchat](/webchat/introduction), the text channel that uses the same widget framework
  * [Variant management](/variant-management/introduction), per-domain or per-region widget configuration
</div>

* [WebRTC gateway API](/api-reference/webrtc-gateway/introduction), the underlying transport (advanced)
