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

# Web SDK

> Start secure browser-based calls with the Phonely Web SDK.

The Phonely Web SDK lets you add browser-based voice calls to your app without exposing your Phonely API key to the browser.

Your server creates a short-lived web call session with Phonely, then your browser passes that session bundle to the SDK.

## Install

```bash theme={null}
npm install @phonely-ai/web
```

Use `@phonely-ai/web` v0.0.8 or newer.

## How It Works

1. Your browser asks your backend to start a web call for an agent.
2. Your backend calls Phonely with your API key.
3. Phonely returns a short-lived session bundle.
4. Your backend returns that bundle to your browser.
5. The Web SDK uses the bundle to join the call and read the live transcript.

<Warning>
  Never send your Phonely API key to the browser. Keep it in your backend only.
</Warning>

## Create A Web Call Session

Call this endpoint from your backend.

```http theme={null}
POST https://db.phonely.ai/api/agents/{agent_id}/web-call-session
X-Authorization: YOUR_API_KEY
Content-Type: application/json
```

### Request Body

The body is optional. Send `{}` if you do not need metadata.

```json theme={null}
{
  "metadata": {
    "callOverrides": {}
  }
}
```

### Response

Return this object from your backend to your browser.

```json theme={null}
{
  "callId": "abc123",
  "webCallUrl": "https://...",
  "meetingToken": "short-lived-meeting-token",
  "phonelyToken": "short-lived-transcript-token",
  "expiresAt": "2026-06-12T03:00:00+00:00",
  "transcriptUrl": "https://db.phonely.ai/api/calls/abc123/transcript"
}
```

| Field           | Description                                                                      |
| --------------- | -------------------------------------------------------------------------------- |
| `callId`        | The Phonely call ID for this session.                                            |
| `webCallUrl`    | The URL the SDK uses to join the web call.                                       |
| `meetingToken`  | A short-lived token for this web call session.                                   |
| `phonelyToken`  | A short-lived token the SDK uses for this call's transcript.                     |
| `expiresAt`     | When the short-lived tokens expire.                                              |
| `transcriptUrl` | The transcript endpoint for this call. Return this value to the SDK as received. |

## Backend Example

```ts theme={null}
export async function POST(request: Request) {
  const { agentId, metadata } = await request.json();

  const response = await fetch(
    `https://db.phonely.ai/api/agents/${encodeURIComponent(agentId)}/web-call-session`,
    {
      method: "POST",
      headers: {
        "X-Authorization": process.env.PHONELY_API_KEY!,
        "Content-Type": "application/json",
      },
      body: JSON.stringify(metadata ? { metadata } : {}),
    }
  );

  if (!response.ok) {
    return Response.json(await response.json(), { status: response.status });
  }

  return Response.json(await response.json());
}
```

## Browser Example

```ts theme={null}
import Phonely from "@phonely-ai/web";

const phonely = new Phonely({
  createWebCallStart: async (options) => {
    const response = await fetch("/api/web-call/start", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(options),
    });

    if (!response.ok) {
      throw new Error("Failed to start web call");
    }

    return response.json();
  },
  transcript: {
    enabled: true,
    autoStart: true,
  },
});

const callId = await phonely.call({ agentId: "agent_123" });
```

## Live Transcript

When `transcript.autoStart` is enabled, the SDK reads the transcript using the `transcriptUrl` and `phonelyToken` from the session response. Return the session response from your backend unchanged so the SDK can use those fields.

Listen for transcript updates:

```ts theme={null}
phonely.on("transcript-message", ({ allMessages }) => {
  console.log(allMessages);
});
```

## Token Expiration

Session tokens are short lived. If a token expires, start a new web call session from your backend.
