Skip to main content

Carrier

The carrier delivers the phone call to Patter. Patter supports Twilio, Telnyx, and Plivo. All three share inbound DTMF, call transfer, AMD, status callbacks, recording, voicemail drop, and cost tracking. Plivo additionally supports native DTMF send over the media WebSocket — a capability Twilio Media Streams lacks. You configure one carrier per Patter instance by passing an instance to the carrier field. Each carrier class falls back to environment variables when constructor arguments are omitted. All three carriers are imported by name from the package barrel: import { Twilio, Telnyx, Plivo } from "getpatter".

Twilio

On serve(), Patter automatically sets the voice_url on the Twilio number to https://<webhookUrl>/webhooks/twilio/voice via the Twilio REST API — no manual Console configuration needed.

How caller / callee reach the agent

Inbound Twilio calls deliver the caller and callee numbers via TwiML <Parameter name="caller" value="..."/> / <Parameter name="callee" value="..."/> children of <Stream> — Twilio surfaces these on the WS start frame as start.customParameters. Patter’s /webhooks/twilio/voice route emits this TwiML automatically. If you construct the TwiML yourself, build it with TwilioAdapter.generateStreamTwiml(streamUrl, { caller, callee }) so the values land on the WS start frame. Query-string parameters on the <Stream url=...> are stripped by Twilio before the WS handshake and will not work.

Signature verification

The Auth Token is also used to verify every Twilio webhook with HMAC-SHA1 against the X-Twilio-Signature header. Requests with invalid signatures are rejected with HTTP 403.

Telnyx

How caller / callee reach the agent

The Telnyx WS upgrade URL carries the metadata as query-string parameters: wss://<webhookUrl>/ws/stream/<callControlId>?caller=<from>&callee=<to>. Telnyx preserves the query string through the WebSocket handshake, so no equivalent of TwiML <Parameter> is needed.

Signature verification

When publicKey is set (or TELNYX_PUBLIC_KEY is present), every Telnyx webhook is verified with Ed25519. Requests older than 5 minutes are rejected (replay protection).

Plivo

On serve(), Patter best-effort creates a Plivo Application bound to https://<webhookUrl>/webhooks/plivo/voice and links it to your phone number via the Plivo REST API. Most production deployments pre-configure the Plivo Application in the console — pass manageWebhook: false on serve() to opt out.

How caller / callee reach the agent

Plivo preserves the WebSocket query string through the handshake, so caller and callee travel on the WSS URL: wss://<webhookUrl>/ws/plivo/stream/<callUuid>?caller=<from>&callee=<to>. Patter also forwards them via the extraHeaders attribute on <Stream> as a belt-and-suspenders fallback — Plivo delivers extraHeaders back on the WS start frame’s extra_headers field.

Wire format and parity gains

  • Audio: mulaw 8 kHz, pinned via the <Stream contentType="audio/x-mulaw;rate=8000"> answer XML. Plivo’s <Stream> element places the WSS URL as its text content (not a url= attribute, as Twilio does).
  • Native DTMF send over the media WebSocket via sendDTMF — a parity gain over Twilio Media Streams.
  • Voicemail drop uses Plivo’s live-call Speak API + DELETE /Call/{uuid}/ hangup.
  • AMD is async: Patter sets machine_detection="true" + machine_detection_url=/webhooks/plivo/amd so human pickups don’t incur the detection-window latency.
  • Status callback: Patter wires hangup_url=/webhooks/plivo/status on outbound calls so no-answer / busy / failed transitions reach the dashboard before any media webhook fires.

Signature verification

The Auth Token doubles as the V3 webhook signature key. The V3 scheme is:
  • POST: signed = url + sortedPostParams + "." + nonce — POST params sorted alphabetically by key (case-sensitive) and concatenated as key1value1key2value2… with no delimiters.
  • GET: signed = url + "." + nonce — query parameters live in the URL already.
Both are HMAC-SHA256 keyed on the Auth Token and base64-encoded, delivered as the X-Plivo-Signature-V3 header alongside X-Plivo-Signature-V3-Nonce. The signature header may carry comma-separated values during key rotation; any matching value accepts. Requests with invalid signatures are rejected with HTTP 403.

Webhook Endpoints

The embedded server exposes these endpoints regardless of carrier choice:

What’s Next

STT

Speech-to-text providers.

LLM

Language model providers.

TTS

Text-to-speech providers.

Tunneling

Expose your local server publicly.