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

# Methods

> The imperative API: start calls, send chat messages, and manage consent from your own UI

All methods exist in three places - use whichever fits your setup:

1. The `<voiceai-widget>` DOM element
2. The object returned by `VoiceAIWidget.init()`
3. `window.VoiceAIWidget.*` (proxies to the first mounted instance)

```js theme={null}
// All three are equivalent on a single-widget page:
document.querySelector('voiceai-widget').startCall();
instance.startCall();
window.VoiceAIWidget.startCall();
```

## The readiness model

The widget fetches its configuration asynchronously after the script loads. **You do not need to wait** - `startCall()` and `sendChatMessage()` are safe to call immediately:

* A `startCall()` made before the widget is ready is **buffered** (one pending start) and fires right after `widget.ready`.
* `sendChatMessage()` calls made before ready are **FIFO-queued** and flushed in order.

The `widget.ready` event exists so careful integrators can gate their UI - for example, enabling the button only when the widget is ready. Its payload tells you which modes (`voice`, `chat`) the widget supports.

## At a glance

| Method                                          | What it does                                             |
| ----------------------------------------------- | -------------------------------------------------------- |
| [`startCall()`](#startcall)                     | Starts a voice call.                                     |
| [`stopCall()`](#stopcall)                       | Ends the active call.                                    |
| [`sendChatMessage(text)`](#sendchatmessagetext) | Sends a chat message, auto-starting a session if needed. |
| [`endChatSession()`](#endchatsession)           | Ends the active chat session.                            |
| [`acceptConsent()`](#acceptconsent)             | Records consent and resumes the paused action.           |

## `startCall()`

Starts a voice call.

```js theme={null}
widget.startCall();
```

**Edge behavior:**

* Called before the config loads → **buffered** (one pending start), fires right after `widget.ready`.
* Called while a call is active or connecting → no-op plus a `console.warn`.
* Voice not enabled on the widget (or no voice assistant configured) → fires `widget.error`.

## `stopCall()`

Ends the active call. Also works for calls started from a visible launcher.

```js theme={null}
widget.stopCall();
```

**Edge behavior:** no-op when idle. Always safe to call.

## `sendChatMessage(text)`

Sends a chat message. **Auto-starts a chat session** if none is active - there is no separate "connect" step.

```js theme={null}
widget.sendChatMessage('Hi! What are your opening hours?');
```

**Edge behavior:**

* Called before ready → messages are **FIFO-queued** and flushed in order.
* Empty or whitespace-only text → ignored.
* Chat not enabled (or chat assistant missing for Retell/ElevenLabs) → fires `widget.error`.

## `endChatSession()`

Ends the active chat session (server-side end plus cleanup). The next `sendChatMessage()` starts a fresh session.

```js theme={null}
widget.endChatSession();
```

**Edge behavior:** no-op when there is no session. Clears any queued messages.

## `acceptConsent()`

Records the visitor's consent (persisted in `localStorage` under the widget's configured key) and **automatically resumes** the action that triggered `widget.consent-required` - the pending call starts, or the queued chat message sends.

```js theme={null}
widget.addEventListener('widget.consent-required', () => {
  // show your own consent UI, then on accept:
  widget.acceptConsent();
});
```

**Edge behavior:** no-op if consent wasn't requested. "Declining" is simply not calling it.

<Info>
  See [Consent in Headless Mode](/documentation/widget/headless-mode/consent) for the full consent flow, including the compliance responsibilities that come with rendering your own consent UI.
</Info>
