# Start a web call

`POST https://api.morevoice.ai/v1/web_calls`

From the browser with a publishable key (`mv_live_pk_…`), or from your server with a secret key: returns the call ID and a single-use client token for `/ws/call`. With a publishable key the assistant must be public, the page must be one of the key's allowed origins (and of the assistant's widget origins, when it lists any), and each visitor may start 10 web calls a minute. The org's concurrent-call quota applies.

Authenticate with a secret API key: `Authorization: Bearer $MOREVOICE_API_KEY`.

Operation ID: `web_calls_create`.

## Parameters

### Headers

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `MoreVoice-Version` | `string` | no | The API version to use for this request. Defaults to the version the API key is pinned to. |
| `Idempotency-Key` | `string` | no | A unique key (for example a UUID) that makes this request safe to retry: for 24 hours, a retry with the same key and parameters returns the first response instead of acting twice. |

## Request body

Required, `application/json`.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `assistant_id` | `string` | yes | The assistant to talk to. With a publishable key it must be public (widget settings). |
| `metadata` | `MetadataInput` | no | Up to 50 key/value pairs (keys up to 40 characters, values up to 500) you attach to an object. Returned as sent. |

Example:

```json
{
  "assistant_id": "asst_8tRPaZp5hLMbrGqdJ9AmNa",
  "metadata": {
    "page": "/pricing"
  }
}
```

## Responses

### 201 Created

The web call, ready to connect. Returns `WebCall`.

| Field | Type | Description |
| --- | --- | --- |
| `object` | `"web_call"` | — |
| `call_id` | `string` | The call this web call will be (GET /v1/calls/{id} once it starts). |
| `assistant_id` | `string` | A assistant ID (prefix `asst_`). |
| `client_token` | `string` | Single use; connect within `expires_at`. |
| `ws_url` | `string` | Connect to `<ws_url>?client_token=<client_token>`. |
| `expires_at` | `string` | An ISO-8601 timestamp in UTC. |
| `livemode` | `boolean` | `true` in live mode, `false` in test mode. |

Example:

```json
{
  "assistant_id": "asst_8tRPaZp5hLMbrGqdJ9AmNa",
  "call_id": "call_3slqGaD2htUzxdRsI",
  "client_token": "<client_token: short-lived JWT, pass it through unchanged>",
  "expires_at": "2026-11-03T09:19:22.000Z",
  "livemode": true,
  "object": "web_call",
  "ws_url": "wss://api.morevoice.ai/ws/call"
}
```

### 400 Bad Request

The request is invalid: a parameter is missing, malformed or unknown, or the version header is unknown. Returns `ErrorEnvelope`.

### 401 Unauthorized

No valid API key was sent. Returns `ErrorEnvelope`.

### 403 Forbidden

The key may not do this (a missing scope, a plan limit, or a compliance block). Returns `ErrorEnvelope`.

### 409 Conflict

The request conflicts with the object's state, or the Idempotency-Key was reused with other parameters. Returns `ErrorEnvelope`.

### 429 Too Many Requests

Too many requests, or no call capacity right now. Retry after the Retry-After delay. Returns `ErrorEnvelope`.

### 500 Internal Server Error

Something went wrong on MoreVoice's side. Retry with the same Idempotency-Key. Returns `ErrorEnvelope`.

## Code samples

**TypeScript**

```ts
import MoreVoice from "@morevoice/sdk";

const mv = new MoreVoice(); // MOREVOICE_API_KEY from the environment

const webCall = await mv.webCalls.create({
	assistant_id: "asst_8tRPaZp5hLMbrGqdJ9AmNa",
	metadata: {
		page: "/pricing",
	},
});
console.log(webCall);
```

**Python**

```python
from morevoice import MoreVoice

client = MoreVoice()  # MOREVOICE_API_KEY from the environment

web_call = client.web_calls.create({
    "assistant_id": "asst_8tRPaZp5hLMbrGqdJ9AmNa",
    "metadata": {
        "page": "/pricing",
    },
})
print(web_call)
```

**cURL**

```sh
curl -X POST https://api.morevoice.ai/v1/web_calls \
  -H "Authorization: Bearer $MOREVOICE_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
  "assistant_id": "asst_8tRPaZp5hLMbrGqdJ9AmNa",
  "metadata": {
    "page": "/pricing"
  }
}'
```
