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

# Test your WebSocket endpoint

> Send real Plivo-shaped audio frames to your bot and check it answers: before any phone number is involved.

## Test a WebSocket endpoint

Open a WebSocket to your server and send exactly what a real call sends: one `start` frame, then a `media` frame every 20 ms for `--duration` seconds, then one `stop` frame. Reports connection latency, frames sent, and (with `--bidirectional`) whether your server sent audio back. No call is placed and Plivo's backend is not involved; this is a pure client-side check you can run in CI.

#### `plivo voice streams test`

Pre-flight a WebSocket endpoint with synthetic Plivo audio frames

**Command:**

```bash theme={null}
plivo voice streams test [flags]
```

**Flags**

* `--bidirectional`: also read frames back from the endpoint (test bot→caller path)
* `--codec <string>`: audio codec: mulaw | l16 (default "mulaw")
* `--duration <int>`: seconds of synthetic audio to stream (max 30) (default 3)
* `--insecure`: skip TLS verification (self-signed dev certs only)
* `--rate <int>`: sample rate in Hz (mulaw: 8000; l16: 8000 or 16000) (default 8000)
* `--to <string>`: WebSocket URL of the endpoint to test (ws\:// or wss\://, required)

**Examples**

```bash theme={null}
  plivo voice streams test --to wss://my-bot.example.com/ws
  plivo voice streams test --to ws://localhost:7860/ws --duration 5
  plivo voice streams test --to wss://localhost:7860/ws --insecure   # self-signed dev cert
  plivo voice streams test --to wss://my-bot.example.com/ws --bidirectional
```

If `Received N frames back from endpoint` is missing with `--bidirectional`, your server never sent a `playAudio` message: callers would hear silence.

### The audio contract

The XML attribute and the WebSocket frame spell the audio format differently, which is the part that is easiest to get wrong.

`<Stream>` carries a single combined `contentType` attribute holding the codec and the sample rate together. There is no `sampleRate` attribute on `<Stream>`.

```xml theme={null}
<Response>
  <Stream bidirectional="true" contentType="audio/x-mulaw;rate=8000">wss://your-bot.example.com/ws</Stream>
</Response>
```

The WebSocket `start` frame spells the same two things out separately, under `mediaFormat`:

```json theme={null}
{"event":"start","start":{"streamId":"...","callId":"...","accountId":"...",
  "mediaFormat":{"encoding":"audio/x-mulaw","sampleRate":8000,"channels":1}}}
```

The l16 MIME type is `audio/x-l16`, not `audio/l16`. Exactly three combinations are supported:

| `contentType`             | `--codec` | `--rate` | Bytes per 20 ms frame |
| ------------------------- | --------- | -------- | --------------------- |
| `audio/x-mulaw;rate=8000` | `mulaw`   | `8000`   | 160                   |
| `audio/x-l16;rate=8000`   | `l16`     | `8000`   | 320                   |
| `audio/x-l16;rate=16000`  | `l16`     | `16000`  | 640                   |

There is no mu-law 16 kHz stream. Any other codec and rate pair is rejected before the connection is opened, with `BAD_FLAG` and exit code 1, so a bad combination fails on your laptop instead of as a dropped stream mid-call. `--codec l16` generates real little-endian 16-bit PCM, so a bot that decodes the payload sees a genuine waveform rather than mu-law bytes under an l16 header.
