# Web SDK (/docs/sdks/web)

> The @omnidim-ai/client package. Put a live voice conversation with your agent on any page with the WebSession class.

`@omnidim-ai/client` is the browser SDK for web call sessions. One small
class, `WebSession`, turns a session into a working voice conversation:
microphone capture, agent audio playback, barge-in, and transcripts are
all handled for you.

It pairs with a server-side call to create the session: your backend
holds the API key, the page only ever receives a short-lived `ws_url`.

  Create sessions on your server. The create response's `ws_url` is the
  only thing the page needs, and it is single-conversation and
  short-lived, so page source, network traces, and logs never expose a
  reusable credential.

## Installation [#installation]

```bash
npm install @omnidim-ai/client
```

No bundler? A script tag works too and exposes the global `OmnidimensionClient`:

```html
<script src="https://unpkg.com/@omnidim-ai/client"></script>
```

## Quickstart [#quickstart]

### 1. Create a session on your server [#1-create-a-session-on-your-server]

  
    ```bash
    curl -X POST https://omnidim.io/api/v1/sessions/create \
      -H "Authorization: Bearer $OMNIDIM_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{"agent_id": 158910, "type": "voice", "custom_variables": {"name": "Demo User"}}'
    ```
  

  
    ```js
    const response = await fetch('https://omnidim.io/api/v1/sessions/create', {
      method: 'POST',
      headers: {
        Authorization: `Bearer ${process.env.OMNIDIM_API_KEY}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        agent_id: 158910,
        type: 'voice',
        custom_variables: { name: 'Demo User' },
      }),
    });
    const { ws_url } = await response.json();
    ```
  

The response contains `session_id`, `token`, `expires_at`, and the
`ws_url` your page connects to. See
[create session](/docs/api-reference/sessions/createSession) for the
full contract, including the balance and concurrency errors.

### 2. Start the conversation in the browser [#2-start-the-conversation-in-the-browser]

```js
import { WebSession } from '@omnidim-ai/client';

const session = new WebSession();

session.on('status', (s) => console.log('status', s));
session.on('transcript', (t) => console.log(t.role, t.text));
session.on('error', (e) => console.error(e));

await session.start({ wsUrl }); // asks for mic permission, then talks
```

That is the whole integration: the visitor talks, the agent answers, and
interrupting the agent mid-sentence stops its audio immediately.

## API [#api]

### `session.start({ wsUrl })` [#sessionstart-wsurl-]

Requests microphone permission, connects, and resolves once the
conversation is live. Audio is echo-cancelled and noise-suppressed.

### `session.mute(muted)` [#sessionmutemuted]

`true` stops sending microphone audio, `false` resumes. The stream stays
warm, so unmuting never re-prompts for permission.

### `session.stop()` [#sessionstop]

Hangs up and releases the microphone.

### Events [#events]

| Event        | Payload                                                                                                                                                                                                  |
| ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `status`     | `'connecting'`, `'active'`, or `{ state: 'ended', reason }`. Reasons include `hangup`, `stopped`, `insufficient_balance`, and `connection_lost`.                                                         |
| `transcript` | `{ role: 'user' \| 'agent', text, final }`. For both roles, `text` is a cumulative snapshot of the current turn (render the latest, do not append); `final: false` is interim, `final: true` is settled. |
| `error`      | An `Error`. The conversation may still continue.                                                                                                                                                         |

If the connection drops mid-call, the SDK reconnects once automatically
and the session re-attaches to the same conversation.

## Integrating without the SDK [#integrating-without-the-sdk]

On platforms without an official SDK (iOS, Android, Flutter, kiosks),
speak the WebSocket protocol directly. It is small: one frame type to
send, a handful of events to receive. See the
[web call protocol](/docs/api-reference/web-call-protocol) in the API
reference.