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

# WebRTC browser calls

> Talk to a Sendora voice agent in a browser, embed a website voice widget, or build your own browser call UI.

Sendora supports **two-way WebRTC audio calls between a browser visitor and a voice agent**. The visitor speaks through their microphone and hears the agent in the browser. No phone number or phone call is required. For a call to a real phone number, see [Voice Calls](/guides/voice-calls).

| What you want to do | Use this path |
| - | - |
| Try your agent yourself | [Browser test call](#test-an-agent-in-sendora) in the Sendora app |
| Let website visitors talk to your agent | [Embeddable voice widget](#add-a-web-voice-widget-to-your-site) |
| Build your own website call interface | [Widget runtime API and browser client](#build-a-custom-browser-call-interface) |

All three paths create a real voice session and can consume credits. A browser test call does not dial a phone number. A website widget can collect visitor details before connecting if you configure a pre-call form.

## How the browser call connects

The short version for a website call is:

1. Create an active widget for a published voice agent and allow your website's origin.
2. From that website, read `GET https://api.sendora.ai/api/v1/public/widget/{widget_public_id}/config` and show its pre-call fields and consent notice.
3. After the visitor chooses to start, call `POST https://api.sendora.ai/api/v1/public/widget/{widget_public_id}/calls` with `fields`, `consent_accepted`, and `metadata`. Sendora checks the widget, origin, call limits, and billing, then creates the voice session.
4. The `201` response contains `join_url`, `call_id`, and `lead_capture_status`. Give `join_url` to the browser voice client to join the call. **The join URL is a connection credential, not a web page to open.**

```json theme={"dark"}
{
  "join_url": "<provider-issued browser connection URL>",
  "call_id": "<call ID>",
  "lead_capture_status": "not_captured"
}
```

The [generated widget](#add-a-web-voice-widget-to-your-site) does these steps for you. Your website does not need a Sendora or voice-provider API key for the public widget call. If you are testing your own agent through an authenticated server integration, use [`POST /voice-agents/{agent_id}/test-call`](#start-a-browser-test-through-the-api) instead.

Sendora is the control layer: it creates the call and applies your widget settings and billing rules. The browser's WebRTC audio connects directly to Sendora's real-time voice service using the returned `join_url`; Sendora's API servers do not relay the call audio.

There is **no separate Sendora browser SDK** today. The generated widget needs no SDK installation from you. For a [fully custom browser UI](#connect-a-custom-browser-client), contact support for the supported browser client package and a working join example.

## Before you start

1. Create and configure a voice agent. Check its greeting, voice, instructions, knowledge, and tools. See [Voice-agent lifecycle](/guides/voice-agent-lifecycle).
2. Make sure the agent is ready for browser testing. For website visitors, use a published agent and an active widget.
3. Make sure the workspace has billing configured and enough credits to start calls.
4. Use a browser with microphone access. Host your website over HTTPS (or use `localhost` during development), and allow microphone permission when prompted.

## Test an agent in Sendora

This is the fastest way to confirm that WebRTC calling works before adding a widget to your site.

1. In the Sendora app, open **Voice Agents** and select your agent.
2. Open the agent's **Test** panel and select **Browser call**.
3. Prepare the agent for testing if the panel asks you to, then select **Start call** and confirm the credit notice.
4. Allow the browser to use your microphone. Speak to the agent, check its responses, and end the call from the panel.

Use **Call a phone number** only when you specifically want to test the phone channel. The browser call connects directly in the browser; it does not test phone-only behavior such as DTMF tones.

### Start a browser test through the API

For an authenticated integration, create the test session on your server with a Sendora API key:

```bash theme={"dark"}
curl -X POST "https://api.sendora.ai/api/v1/public/voice-agents/AGENT_ID/test-call" \
  -H "X-API-Key: $SENDORA_API_KEY"
```

The response contains `join_url` and `call_id`. Pass `join_url` to a browser voice client promptly to join the session. Keep your Sendora API key on the server; **never put it in browser JavaScript**. Creating a session and joining it are separate steps. See [Connect a custom browser client](#connect-a-custom-browser-client) below for the client step.

```json theme={"dark"}
{
  "join_url": "<short-lived browser call URL>",
  "call_id": "<call ID>"
}
```

Test calls are billable and may create call records. Do not automatically repeat the POST after a timeout; first check whether a call was created.

## Add a web voice widget to your site

The widget is the simplest production path. It includes the call controls and handles the WebRTC connection for you.

1. In the Sendora app, open your published voice agent's **Widgets** tab and create a widget.
2. In the widget editor, configure its appearance, greeting, consent notice, and optional pre-call form.
3. Under **Distribution & safety**, add every website origin where the widget will run, such as `https://www.example.com`. An origin is the scheme and host (and port, if used), without a path or trailing slash. Wildcards are not supported. Save the widget and leave it **Active**.
4. Copy the widget's **Embed code** from the editor and paste it just before `</body>` on each page where it should appear. Use the generated code rather than composing a script URL yourself.
5. Open the page from an allowed origin, allow microphone access, accept the consent notice if shown, and start a call. Confirm that audio works in both directions and that the call ends cleanly.

You can also retrieve the generated embed code from a server-side integration:

```bash theme={"dark"}
curl "https://api.sendora.ai/api/v1/public/voice-agents/AGENT_ID/widgets/WIDGET_ID/embed" \
  -H "X-API-Key: $SENDORA_API_KEY"
```

The response includes `snippet` (the script tag to paste) and `widget_public_id`. The management request needs an API key; the visitor's browser does not. For widget configuration and security details, see [Voice widgets](/guides/voice-widgets).

## Build a custom browser call interface

Use this path if you need your own buttons or layout instead of the generated widget. A Sendora widget still owns the public browser-call policy: its public ID, allowed origins, consent setting, pre-call fields, call limits, and active state. Create and configure that widget as described above, but use its runtime endpoints from your own browser UI.

### Call flow

1. From an allowed website origin, request `GET /api/v1/public/widget/{widget_public_id}/config` to read the visitor-safe configuration.
2. Show the configured pre-call fields and consent notice. Gather required fields and an affirmative consent choice when `require_consent` is true.
3. When the visitor chooses to start, send `POST /api/v1/public/widget/{widget_public_id}/calls` with `fields`, `consent_accepted`, and `metadata`.
4. The response supplies `join_url`, `call_id`, and `lead_capture_status`. Give `join_url` to a WebRTC browser client to connect audio, then provide an end-call control.

The two widget runtime endpoints are intentionally unauthenticated. Browser requests must come from an origin on the widget's allowlist; an origin is a browser policy check, not a visitor identity check. They do not take a Sendora API key. The public widget ID is an identifier, not a secret. The `join_url` is a short-lived call credential: use it for that call, do not publish it in logs or reuse it for later calls.

### Connect a custom browser client

A custom interface joins the session with the `join_url` returned by the call-creation step, using the supported browser voice client. Contact support for the current client package, a complete join example and the session events you can listen to. Keep the Sendora API key on your server and pass only the `join_url` to the browser.

## Troubleshooting

| Symptom | Check |
| - | - |
| Microphone prompt is missing or permission is denied | Use HTTPS or `localhost`; check browser and operating-system microphone permissions, then retry from the start button. |
| `403` when loading config or starting a widget call | Add the page's exact origin to the widget's allowed origins and save it. Include the correct scheme and port. |
| `422` when starting a widget call | Supply required pre-call fields and valid values, and accept consent if it is required. |
| `402` | Check workspace billing and available credits. |
| `429` | The widget has reached a rate, daily, or concurrent-call limit. Wait or review its limits. |
| `409` on a test call or widget call | Check that the agent is configured and ready for calls. |
| `502` or `503` | The voice service is temporarily unavailable. Inspect the call state before trying another billable start request. |

For the full request and response contracts, use the API reference for the browser test call and widget runtime endpoints. For phone calls, use [Voice Calls](/guides/voice-calls).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.