> ## Documentation Index
> Fetch the complete documentation index at: https://daily-docs-source-analytics-user-turn-strategies.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Bandwidth

> Telephony serializer for Bandwidth Programmable Voice WebSocket media streams

export const CommunityMaintained = ({maintainer, maintainerUrl, repo}) => <Note>
    <strong>Community-maintained integration.</strong> This service is built and
    maintained by{" "}
    <a href={maintainerUrl} target="_blank" rel="noreferrer">
      {maintainer}
    </a>
    . Pipecat does not test or officially support it. Please report issues and
    request changes on the{" "}
    <a href={repo} target="_blank" rel="noreferrer">
      source repository
    </a>
    . Learn more about{" "}
    <a href="/api-reference/server/services/community-integrations">
      community integrations
    </a>
    .
  </Note>;

<CommunityMaintained maintainer="Bandwidth" maintainerUrl="https://github.com/Bandwidth" repo="https://github.com/Bandwidth/pipecat-bandwidth" />

## Overview

`BandwidthFrameSerializer` is a `FrameSerializer` that converts between Pipecat
frames and [Bandwidth Programmable Voice](https://dev.bandwidth.com/docs/voice/)'s
bidirectional WebSocket media stream protocol. Plug it into a
`FastAPIWebsocketTransport` to use Bandwidth as the telephony layer for your
Pipecat voice bots.

<CardGroup cols={2}>
  <Card title="Source Repository" icon="github" href="https://github.com/Bandwidth/pipecat-bandwidth">
    Source code, examples, and issues for the Bandwidth integration
  </Card>

  <Card title="PyPI Package" icon="cube" href="https://pypi.org/project/pipecat-bandwidth/">
    The `pipecat-bandwidth` package on PyPI
  </Card>

  <Card title="Bandwidth StartStream BXML" icon="book" href="https://dev.bandwidth.com/docs/voice/programmable-voice/bxml/startStream/">
    Bandwidth's media-stream protocol reference
  </Card>

  <Card title="Bandwidth Voice API" icon="key" href="https://dev.bandwidth.com/apis/voice/">
    Manage credentials and calls via the Bandwidth Voice API
  </Card>
</CardGroup>

## Installation

This is a community-maintained package distributed separately from `pipecat-ai`:

```bash theme={null}
uv add pipecat-bandwidth
```

## Prerequisites

### Bandwidth Account Setup

Before using `BandwidthFrameSerializer`, you need:

1. **Bandwidth Account**: Sign up at [Bandwidth](https://www.bandwidth.com/)
2. **Programmable Voice**: A phone number and application configured for
   Programmable Voice with a `<StartStream mode="bidirectional">` BXML response
3. **OAuth 2.0 Credentials**: A Client ID and Client Secret for the Bandwidth
   Voice API (required for auto hang-up)

### Required Environment Variables

* `BANDWIDTH_CLIENT_ID`: OAuth 2.0 Client ID for Bandwidth API authentication
* `BANDWIDTH_CLIENT_SECRET`: OAuth 2.0 Client Secret for Bandwidth API
  authentication

<Warning>
  `call_id` and `account_id` flow into an authenticated POST to the Bandwidth
  Voice API on auto hang-up. They must come from a server-trusted source —
  typically the authenticated inbound voice webhook body — and **not** from the
  WebSocket `start` event metadata, which is unauthenticated and
  attacker-controllable.
</Warning>

## Configuration

<ParamField path="stream_id" type="str" required>
  The Bandwidth Stream ID, available in the `start` event metadata.
</ParamField>

<ParamField path="call_id" type="str" default="None">
  The Bandwidth Call ID. Required when `auto_hang_up` is enabled. Must come from
  a server-trusted source (e.g. the signed inbound voice webhook).
</ParamField>

<ParamField path="account_id" type="str" default="None">
  The Bandwidth account ID. Required when `auto_hang_up` is enabled. Same trust
  requirement as `call_id`.
</ParamField>

<ParamField path="client_id" type="str" default="None">
  OAuth 2.0 Client ID for Bandwidth API authentication. Required when
  `auto_hang_up` is enabled.
</ParamField>

<ParamField path="client_secret" type="str" default="None">
  OAuth 2.0 Client Secret for Bandwidth API authentication. Required when
  `auto_hang_up` is enabled.
</ParamField>

<ParamField path="params" type="InputParams" default="None">
  Configuration parameters for audio encoding and hang-up behavior. See
  [InputParams](#inputparams) below.
</ParamField>

### InputParams

Configuration passed via the `params` constructor argument using
`BandwidthFrameSerializer.InputParams(...)`.

| Parameter                  | Type   | Default  | Description                                                                                                          |
| -------------------------- | ------ | -------- | -------------------------------------------------------------------------------------------------------------------- |
| `bandwidth_sample_rate`    | `int`  | `8000`   | Sample rate Bandwidth uses on the wire for PCMU audio. Always 8000 Hz; exposed for symmetry with other serializers.  |
| `sample_rate`              | `int`  | `None`   | Optional override for the pipeline input sample rate.                                                                |
| `outbound_encoding`        | `str`  | `"PCMU"` | Audio encoding for media sent back to the call: `"PCMU"` (μ-law 8 kHz) or `"PCM"` (16-bit signed little-endian PCM). |
| `outbound_pcm_sample_rate` | `int`  | `24000`  | Sample rate used when `outbound_encoding == "PCM"`. One of `8000`, `16000`, or `24000`. Higher improves TTS quality. |
| `auto_hang_up`             | `bool` | `True`   | Whether to automatically terminate the call via the Voice API on `EndFrame` or `CancelFrame`.                        |
| `ignore_rtvi_messages`     | `bool` | `False`  | Inherited from the base `FrameSerializer`.                                                                           |

## Usage

Wire the serializer into a `FastAPIWebsocketTransport`:

```python theme={null}
import os

from pipecat.transports.websocket.fastapi import (
    FastAPIWebsocketParams,
    FastAPIWebsocketTransport,
)
from pipecat_bandwidth import BandwidthFrameSerializer

# call_id and account_id MUST come from a server-trusted source — typically
# the authenticated inbound voice webhook body — not the WebSocket "start"
# event metadata.
serializer = BandwidthFrameSerializer(
    stream_id=stream_id,
    call_id=call_id,
    account_id=account_id,
    client_id=os.getenv("BANDWIDTH_CLIENT_ID"),
    client_secret=os.getenv("BANDWIDTH_CLIENT_SECRET"),
)

transport = FastAPIWebsocketTransport(
    websocket=websocket,
    params=FastAPIWebsocketParams(
        audio_in_enabled=True,
        audio_out_enabled=True,
        add_wav_header=False,
        serializer=serializer,
    ),
)
```

For higher-fidelity outbound audio, configure linear PCM:

```python theme={null}
from pipecat_bandwidth import BandwidthFrameSerializer

serializer = BandwidthFrameSerializer(
    stream_id=stream_id,
    call_id=call_id,
    account_id=account_id,
    client_id=os.getenv("BANDWIDTH_CLIENT_ID"),
    client_secret=os.getenv("BANDWIDTH_CLIENT_SECRET"),
    params=BandwidthFrameSerializer.InputParams(
        outbound_encoding="PCM",
        outbound_pcm_sample_rate=24000,
    ),
)
```

<Note>
  DTMF is **not** delivered over the media-stream WebSocket on Bandwidth. It is
  captured by the BXML `<Gather>` verb and posted to a separate webhook, so DTMF
  handling belongs in your application's webhook handler, not the serializer.
</Note>

## Compatibility

Tested with Pipecat v1.4.0. Check the [source
repository](https://github.com/Bandwidth/pipecat-bandwidth) for the latest
tested version and changelog.
