Last updated July 13, 2026

VoiceBlender v0.11.0 API v1.0.0 http://localhost:8080/v1

VoiceBlender bridges SIP and WebRTC voice calls with multi-party audio mixing, real-time speech-to-text, text-to-speech, AI agent integration, recording, and webhook-based event delivery.

Configuration

VariableDefaultDescription
INSTANCE_ID(auto-generated UUID)Instance identifier included in all API responses and webhook events
HTTP_ADDR:8080REST API listen address
ALLOWED_IPS(empty = allow all)Comma-separated allowlist of IPs and CIDR ranges (IPv4 and IPv6) gating every HTTP endpoint, including /v1/vsi, /v1/legs/websocket, /v1/legs/moq, /metrics, and pprof. Bare addresses become /32 (v4) or /128 (v6); malformed entries fail server startup. Only X-Forwarded-For is consulted as a proxy header (see TRUST_PROXY_HEADERS).
TRUST_PROXY_HEADERSfalseWhen true, the client IP used for the ALLOWED_IPS check is taken from the leftmost X-Forwarded-For entry (falling back to the socket peer if absent). Enable only behind a trusted reverse proxy that overwrites the header — otherwise it is client-spoofable.
SIP_BIND_IP127.0.0.1IPv4 address advertised in SDP, Contact, and Via headers (and used as the listen address when SIP_LISTEN_IP is empty)
SIP_LISTEN_IP(same as SIP_BIND_IP)UDP socket bind IP. Accepts 127.0.0.1, 0.0.0.0, ::, or any literal v4/v6 address
SIP_BIND_IPV6(empty = v4-only)IPv6 address advertised in SDP/Contact/Via for IPv6 calls. Set this for IPv6-only or dual-stack deployments
SIP_LISTEN_IPV6(same as SIP_BIND_IPV6)Optional separate IPv6 socket bind address (used when running with both 0.0.0.0 and a specific v6 literal)
SIP_EXTERNAL_IPPublic IPv4 address for NAT/Docker deployments. When set, used in SIP Contact headers and SDP media (c=) lines instead of the bind IP. IPv6 has no equivalent — set SIP_BIND_IPV6 to the address you want advertised.
SIP_PORT5060SIP listen port
SIP_TLS_PORT(disabled)SIP-over-TLS listen port (typically 5061). When set, SIP_TLS_CERT and SIP_TLS_KEY must also be provided. Required for WhatsApp Business Calling integration.
SIP_TLS_CERTPath to PEM-encoded TLS certificate (e.g. fullchain.pem). Meta rejects self-signed certs — use a CA-signed cert matching a public FQDN.
SIP_TLS_KEYPath to PEM-encoded TLS private key (e.g. privkey.pem).
SIP_DEBUGfalseWhen true, log the full RFC 3261 wire form of every inbound and outbound SIP request and response. Very verbose — use only for troubleshooting.
SIP_DOMAIN(falls back to advertised IP)FQDN advertised in From, Contact and Via on all outbound SIP signalling (classic trunks and WhatsApp). Should match the SAN on SIP_TLS_CERT and any allowlist your carrier or Meta keeps.
SIP_HOSTvoiceblenderSIP User-Agent name
SIP_CODECSPCMU,PCMAComma-separated, preference-ordered list of codecs the SIP engine offers on outbound INVITEs and accepts on inbound INVITEs. Recognized names (case-insensitive): PCMU, PCMA, G722, opus, AMR-WB, AMR-NB (bare token AMR resolves to AMR-NB per RFC 4867 §8.1). Unknown names and duplicates are dropped silently.
SIP_AUTO_RINGINGfalseWhen true, the server sends 180 Ringing automatically after 100 Trying. Default sends only 100 Trying; the API caller drives ringing via /ring, /early-media, or /answer.
SIP_USE_SOURCE_SOCKETfalseWhen true, route SIP responses and in-dialog requests (BYE, re-INVITE, UPDATE, INFO, NOTIFY, REFER) back to the request's source UDP socket instead of the peer's Contact / Via sent-by. Enable when peers advertise unroutable addresses (e.g. private IPs in Contact from behind NAT).
SIP_REGISTRATION_DEFAULT_EXPIRES_SECONDS3600Expiry used when an inbound REGISTER carries no Expires value.
SIP_REGISTRATION_MAX_EXPIRES_SECONDS7200Upper clamp on the granted REGISTER expiry. Requests above this value are honored at this maximum.
SIP_REGISTRATION_SWEEP_INTERVAL_MS1000Sweeper period (ms) for evicting expired AOR bindings.
SIP_REGISTRATION_ALLOW_MULTIPLE_CONTACTStrueWhen true, the same AOR may be bound from multiple Contacts simultaneously (and POST /v1/legs parallel-forks to every bound contact). When false, each REGISTER replaces any prior Contacts for the AOR.
ICE_SERVERSstun:stun.l.google.com:19302STUN/TURN URLs for WebRTC ICE, comma-separated
WEBRTC_EXTERNAL_IPS(empty)Comma-separated public IPs advertised as host ICE candidates (pion SetNAT1To1IPs). Required when VB runs behind NAT/Docker so peers behind firewalls can reach it; supports IPv4 and IPv6 literals. The literal value "auto" triggers STUN-based public-IP discovery at startup using the configured ICE_SERVERS; failure is non-fatal.
RTP_PORT_MIN10000Minimum UDP port for RTP/RTCP media
RTP_PORT_MAX20000Maximum UDP port for RTP/RTCP media
DEFAULT_SAMPLE_RATE16000Default mixer sample rate (Hz) for new rooms when sample_rate is not specified. Allowed: 8000, 16000, 48000.
SPEECH_DETECTION_ENABLEDfalseEmit speaking.started / speaking.stopped events for every connected leg by default. Per-call speech_detection on POST /v1/legs or POST /v1/legs/{id}/answer overrides this.
VSI_EVENT_BUFFER_SIZE256Per-client buffer (in events) on the /v1/vsi WebSocket. When the client falls behind, new events are dropped and the next delivered event carries an events_dropped notification. Clamped to [16, 1000000]. Memory: ~1 KB × buffer per connection at the default.
AMRWB_MODE2AMR-WB (G.722.2) encoder speech-mode ceiling 0..8: 0=6.60, 1=8.85, 2=12.65, 3=14.25, 4=15.85, 5=18.25, 6=19.85, 7=23.05, 8=23.85 kbit/s. The actual transmit mode is this ceiling clamped to the peer's negotiated mode-set. Default 2 matches GSMA IR.92 / VoLTE.
AMRWB_OCTET_ALIGNEDtrueOffer octet-aligned AMR-WB framing (RFC 4867) in outbound SDP. When false, offers bandwidth-efficient framing. On answers, VoiceBlender always echoes the framing the peer negotiated.
AMRNB_MODE7AMR-NB (RFC 4867) encoder speech-mode ceiling 0..7: 0=4.75, 1=5.15, 2=5.90, 3=6.70, 4=7.40, 5=7.95, 6=10.2, 7=12.2 kbit/s. The actual transmit mode is this ceiling clamped to the peer's negotiated mode-set. Default 7 is GSM-EFR-equivalent 12.2 kbit/s.
AMRNB_OCTET_ALIGNEDtrueOffer octet-aligned AMR-NB framing (RFC 4867) in outbound SDP. When false, offers bandwidth-efficient framing. On answers, VoiceBlender always echoes the framing the peer negotiated.
RECORDING_DIR/tmp/recordingsLocal directory for recording output files
LOG_LEVELinfoLog verbosity: debug, info, warn, error
WEBHOOK_URLGlobal webhook URL for event delivery (fallback when no per-leg or per-room webhook is set)
WEBHOOK_SECRETHMAC-SHA256 signing secret for the global webhook
ELEVENLABS_API_KEYAPI key for ElevenLabs TTS, STT, and Agent provider
VAPI_API_KEYAPI key for VAPI Agent provider
DEEPGRAM_API_KEYAPI key for Deepgram STT and TTS
AZURE_SPEECH_KEYSubscription key for Azure Cognitive Speech Services (TTS and STT)
AZURE_SPEECH_REGIONeastusAzure region for Speech Services (e.g. eastus, westeurope)
S3_BUCKETS3 bucket name for recording uploads
S3_REGIONus-east-1AWS region for S3
S3_ENDPOINTCustom S3-compatible endpoint (e.g. MinIO)
S3_PREFIXKey prefix applied to all S3 objects
AWS_ACCESS_KEY_ID[SDK-resolved, not read by VoiceBlender] AWS access key for S3 uploads and AWS Polly TTS. Consumed by the AWS SDK default credential chain alongside AWS_SECRET_ACCESS_KEY and the optional AWS_SESSION_TOKEN.
AWS_SECRET_ACCESS_KEY[SDK-resolved, not read by VoiceBlender] AWS secret key paired with AWS_ACCESS_KEY_ID.
AWS_SESSION_TOKEN[SDK-resolved, not read by VoiceBlender] Optional temporary-credential session token (STS / SSO) used together with AWS_ACCESS_KEY_ID/SECRET.
AWS_PROFILE[SDK-resolved, not read by VoiceBlender] Profile name in ~/.aws/credentials to use instead of static AWS_* env vars.
AWS_REGION[SDK-resolved, not read by VoiceBlender] AWS region used by S3 and Polly when S3_REGION is empty.
GOOGLE_APPLICATION_CREDENTIALS[SDK-resolved, not read by VoiceBlender] Path to a Google Cloud service-account JSON file used by Google Cloud TTS when no per-request api_key is supplied. Consumed by Google's Application Default Credentials chain.
TTS_CACHE_ENABLEDfalseEnable disk-backed TTS audio cache; cached audio persists across restarts
TTS_CACHE_DIR/tmp/tts_cacheDirectory for cached TTS audio files (used when TTS_CACHE_ENABLED=true)
TTS_CACHE_INCLUDE_API_KEYfalseInclude API key in TTS cache key; set true if different keys map to different voice clones
SIP_JITTER_BUFFER_MS0SIP ingress jitter buffer target delay in ms (0 = disabled passthrough). Applies to every SIP leg.
SIP_JITTER_BUFFER_MAX_MS300Maximum depth of the SIP ingress jitter buffer in ms. Frames beyond this are dropped oldest-first to catch up after a stall.
SIP_REFER_AUTO_DIALfalseWhen true, accept incoming SIP REFER requests and automatically originate the transferred call. Default-deny: stays off unless the SIP edge is locked down (IP allow-lists, digest auth) because auto-dialing arbitrary Refer-To URIs is a classic toll-fraud vector. Outbound transfers initiated via the REST API are unaffected by this flag.
MOQ_ENABLEDfalseEnable the experimental MoQ (Media over QUIC) inbound leg endpoint at CONNECT /v1/legs/moq over WebTransport/HTTP/3. PoC quality, tracks IETF draft-11. When enabled, both MOQ_TLS_CERT_FILE and MOQ_TLS_KEY_FILE must be set.
MOQ_LISTEN_ADDR:8443UDP address for the HTTP/3 listener that backs the MoQ leg. Independent of HTTP_ADDR — TCP/:8080 and UDP/:8443 can run side-by-side.
MOQ_TLS_CERT_FILEPath to the TLS certificate used by the HTTP/3 listener. Required when MOQ_ENABLED=true.
MOQ_TLS_KEY_FILEPath to the TLS private key used by the HTTP/3 listener. Required when MOQ_ENABLED=true.
MOQ_OPUS_BITRATE24000Target bitrate (bps) for the Opus encoder feeding the MoQ leg's mix track. Must be in 6000..510000.
LIVEKIT_ENABLEDfalseEnable the livekit_room leg type at POST /v1/legs (type=livekit_room). Lets VoiceBlender join a LiveKit room as a participant and bridge audio between SIP and LiveKit. Speaks the LiveKit signaling protocol directly via livekit/protocol protobufs over the existing pion stack — no LiveKit SDK is used.
LIVEKIT_URLDefault LiveKit server endpoint (wss://...). Required when LIVEKIT_ENABLED=true unless every request supplies livekit.url. Overridable per-request.
LIVEKIT_OPUS_BITRATE24000Target bitrate (bps) for the Opus encoder publishing audio into LiveKit. Must be in 6000..510000. Overridable per-request via livekit.opus_bitrate.
LIVEKIT_TOKEN_SIGNING_ENABLEDfalseOpt-in: when true, callers may omit livekit.token and instead pass {room,identity,permissions}; VoiceBlender mints the JWT itself. Security caveat: enabling this stores the LiveKit API secret (a high-privilege credential) in VoiceBlender. Keep off in multi-tenant deployments.
LIVEKIT_API_KEYLiveKit API key used to sign minted JWTs. Required only when LIVEKIT_TOKEN_SIGNING_ENABLED=true.
LIVEKIT_API_SECRETLiveKit API secret used to sign minted JWTs. Required only when LIVEKIT_TOKEN_SIGNING_ENABLED=true. Treat as a high-value secret; redact in logs.
LIVEKIT_DEFAULT_TOKEN_TTL6hDefault TTL applied to minted JWTs when the request omits livekit.token_ttl. Go duration string. LiveKit recommends ≤ 6 hours.