Skip to main content

Documentation Index

Fetch the complete documentation index at: https://patter-06b046ce-feat-observability-otel-attrs-0-6-1.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

Configuration

The Patter constructor accepts PatterOptions. Pass a carrier instance and a phone number — everything else flows through environment variables unless you override it.

Minimal config

import { Patter, Twilio } from "getpatter";

const phone = new Patter({ carrier: new Twilio(), phoneNumber: "+15550001234" });  // TWILIO_* from env
The carrier instance reads credentials from environment variables when you don’t pass them explicitly. See Carrier for the full list.

Constructor parameters

ParameterTypeRequiredDefaultDescription
carrierTwilio | TelnyxYesTelephony carrier instance. Reads credentials from env vars when arguments are omitted. See Carrier.
phoneNumberstringYesYour phone number in E.164 format.
webhookUrlstringConditionalPublic hostname for webhooks (no protocol prefix, no path). Required unless using tunnel: true in serve().
tunnelCloudflareTunnel | StaticTunnel | booleanNoTunnel directive. true is shorthand for new CloudflareTunnel(). See Tunneling.
pricingRecord<string, Partial<ProviderPricing>>NoOverride default provider pricing estimates. See Metrics.
persistboolean | stringNoPersist the dashboard’s call history to disk so it survives process restarts. See Persistent dashboard history below.

Webhook URL Format

The webhookUrl must be a bare hostname with no protocol prefix or path:
// Correct
webhookUrl: "abc123.ngrok.io"

// Wrong — will throw
webhookUrl: "https://abc123.ngrok.io"
webhookUrl: "abc123.ngrok.io/webhooks"
The SDK constructs full URLs internally (e.g., https://{webhookUrl}/webhooks/twilio/voice).
Telnyx: Telnyx is a fully supported alternative to Twilio, with feature parity for DTMF, call transfer, recording, and cost tracking.

Environment variables

Every credential resolves from an env var when the matching argument is omitted. See .env.example in the repo for a complete list.
Env varUsed by
TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKENnew Twilio()
TELNYX_API_KEY, TELNYX_CONNECTION_ID, TELNYX_PUBLIC_KEY (optional)new Telnyx()
OPENAI_API_KEYnew OpenAIRealtime(), new OpenAITTS(), new WhisperSTT()
ELEVENLABS_API_KEY, ELEVENLABS_AGENT_IDnew ElevenLabsTTS(), new ElevenLabsConvAI()
DEEPGRAM_API_KEYnew DeepgramSTT()
CARTESIA_API_KEYnew CartesiaSTT(), new CartesiaTTS()
RIME_API_KEYnew RimeTTS()
LMNT_API_KEYnew LMNTTTS()
SONIOX_API_KEYnew SonioxSTT()
ASSEMBLYAI_API_KEYnew AssemblyAISTT()

Runtime env vars

These tune SDK runtime behaviour (no credential lookup).
Env varDefaultEffect
PATTER_LOG_DIRunsetPersistent dashboard root (see Persistent dashboard history below).
PATTER_LOG_RETENTION_DAYS30Days of disk history to retain. 0 disables cleanup.
PATTER_LOG_REDACT_PHONE1Mask phone numbers in metadata.json (last 4 digits). Set to 0 to store full E.164.
PATTER_DASHBOARD_NOTIFYenabledSet to 0, false, no, or off (case-insensitive) to skip the fire-and-forget dashboard ingest POST. Use this when you embed Patter alongside your own Express server on port 8000 to avoid 404 spam in your access log.
PATTER_BIND_HOST127.0.0.1Host the embedded server binds to. Set to 0.0.0.0 when running inside a container whose port must be reachable from the host (e.g. docker run -p 8000:8000 — Docker’s port-mapping cannot forward to a 127.0.0.1 listener inside the container).
PATTER_BIND_HOST defaults to loopback on purpose — exposing the embedded server on 0.0.0.0 outside a containerised deployment puts the dashboard and webhook routes on every interface. Pair PATTER_BIND_HOST=0.0.0.0 with the dashboardToken option on serve() (or skip the dashboard) before going public.
PATTER_DASHBOARD_NOTIFY only gates the standalone-dashboard ingest webhook. It does not disable the embedded dashboard you can serve from phone.serve({ dashboard: true }) — that route runs in-process and is unaffected.

Examples

OpenAI Realtime on Twilio

import { Patter, Twilio, OpenAIRealtime } from "getpatter";

const phone = new Patter({ carrier: new Twilio(), phoneNumber: "+15550001234" });

const agent = phone.agent({
  engine: new OpenAIRealtime({ voice: "alloy" }),
  systemPrompt: "You are a friendly receptionist.",
  firstMessage: "Thanks for calling!",
});

OpenAI Realtime on Telnyx

import { Patter, Telnyx, OpenAIRealtime } from "getpatter";

const phone = new Patter({ carrier: new Telnyx(), phoneNumber: "+15550001234" });

const agent = phone.agent({
  engine: new OpenAIRealtime(),
  systemPrompt: "You are a friendly receptionist.",
});

Pipeline mode

import { Patter, Twilio, DeepgramSTT, ElevenLabsTTS } from "getpatter";

const phone = new Patter({ carrier: new Twilio(), phoneNumber: "+15550001234" });

const agent = phone.agent({
  stt: new DeepgramSTT({ endpointingMs: 80 }),
  tts: new ElevenLabsTTS({ voiceId: "rachel" }),
  systemPrompt: "You are a helpful assistant.",
});

Persistent dashboard history

By default the dashboard is an in-memory ring buffer — restart the process and the call list is empty. Pass persist to keep per-call records (metadata.json, transcript.jsonl, events.jsonl) on disk and rebuild the dashboard on the next startup. No external database required.
persist valueBehaviour
omitted / undefined (default)Falls back to the PATTER_LOG_DIR env var. If the env var is also unset, persistence is off — backward-compatible with prior releases.
falseForce-off. Disk writes are skipped even when PATTER_LOG_DIR is set.
trueWrite under the platform default location (see below). Equivalent to PATTER_LOG_DIR=auto.
"<path>" (string)Write under the supplied path (~ is expanded). Equivalent to PATTER_LOG_DIR=<path>.
When persist is set explicitly the env var is ignored. When persist is undefined, PATTER_LOG_DIR continues to work as a deployment-time override.

Platform default location

PlatformDefault root
macOS~/Library/Application Support/patter
Linux$XDG_DATA_HOME/patter (falls back to ~/.local/share/patter)
Windows%LOCALAPPDATA%\patter

Simplest opt-in

import { Patter, Twilio, OpenAIRealtime } from "getpatter";

const phone = new Patter({
  carrier: new Twilio(),
  phoneNumber: "+15555550100",
  persist: true,                    // platform default location
});

const agent = phone.agent({
  engine: new OpenAIRealtime(),
  systemPrompt: "You are a friendly receptionist.",
});

Custom path

const phone = new Patter({
  carrier: new Twilio(),
  phoneNumber: "+15555550100",
  persist: "/var/log/patter",       // explicit path; ~ is expanded
});

Env-var override (deployment-time)

Leave persist unset in code and let ops decide per environment:
# Production: keep history under a managed volume
export PATTER_LOG_DIR=/var/log/patter

# Dev: platform default
export PATTER_LOG_DIR=auto

# CI: leave unset → no disk writes
const phone = new Patter({ carrier: new Twilio(), phoneNumber: "+15555550100" });
// `persist` defaults to undefined → reads PATTER_LOG_DIR

Programmatic hydration on startup

phone.serve() calls MetricsStore.hydrate(logRoot) automatically when persistence is enabled, so the dashboard repopulates from disk before the first call lands. You can call it directly if you build the store yourself:
import { MetricsStore } from "getpatter/dashboard/store";

const store = new MetricsStore();
const restored = store.hydrate("/var/log/patter");
console.log(`Restored ${restored} calls from disk`);
hydrate() is idempotent — callIds already in the store are skipped, and unparseable records are logged at debug level rather than aborting.

Retention

# Default: 30 days. Old day-directories are swept on ~2% of calls (no daemon).
export PATTER_LOG_RETENTION_DAYS=30

# Keep forever — opt out of automatic cleanup
export PATTER_LOG_RETENTION_DAYS=0
Retention defaults to 30 days and phone numbers in metadata.json are masked by default (last 4 digits) via PATTER_LOG_REDACT_PHONE. If you need to keep call history indefinitely or store full E.164 numbers, set those env vars explicitly — and gate access to the log root, since transcript.jsonl is never redacted and may contain customer PII spoken during the call.
See Call logging for the full layout, schema, and reading patterns.

Loading from .env

// Node 20.6+: --env-file flag
// node --env-file=.env --loader tsx index.ts

import { Patter, Twilio, OpenAIRealtime } from "getpatter";

const phone = new Patter({
  carrier: new Twilio(),                              // reads TWILIO_* from env
  phoneNumber: process.env.PHONE_NUMBER!,
  webhookUrl: process.env.WEBHOOK_URL!,
});

const agent = phone.agent({
  engine: new OpenAIRealtime(),                       // reads OPENAI_API_KEY
  systemPrompt: "You are a helpful assistant.",
});
Telnyx delivers 16 kHz PCM audio natively, so no transcoding is needed. Twilio uses mulaw 8 kHz, which the SDK transcodes automatically.
Never hardcode API keys, tokens, or secrets in your source code. Always use environment variables or a secret manager.