Skip to main content

2.27.2 (2026-07-01)

Reconnect and recovery hardening

  • fix(sdk): dedupe reconnect attempts and add exponential backoff (#709) Browsers commonly emit both socket.onerror and socket.onclose for one physical disconnect, previously consuming two logical reconnect attempts. BaseSession.onNetworkClose now tracks the socket generation that was already handled (_reconnectCountedGeneration) and skips same-generation duplicate events before destructive cleanup, so a stale event can no longer clear an already-scheduled reconnect timer or schedule a redundant one. Connection._registerSocketEvents captures registeredGeneration at registration time so stale events from an old socket carry their own generation, and onNetworkClose guards against eventGeneration < currentGeneration before flushing call reports or clearing timers. Reconnect delay is now exponential backoff with jitter (base 1s, doubling per attempt, capped at 30s, 25% jitter), replacing the old fixed 1000ms / randomInt(2,6)*1000ms. Backoff resets only on a confirmed REGED. BrowserSession no longer overrides the delay — it inherits the backoff from BaseSession.
  • feat: add reconnection lifecycle diagnostics for SDK WebSocket recovery visibility (#678) Adds call-report-visible diagnostics for the SDK WebSocket close/reconnect lifecycle after SignalingHealthService requests recovery, without overloading reports with noisy logs. Consolidates the previous per-source warning codes into a single SIGNALING_RECOVERY_REQUIRED warning (with a source field), and adds a new RECONNECTION_FAILED_WITH_NO_AUTO_RECONNECT (36005) warning gated on a new _intentionalClose flag so it only fires on unexpected socket close when auto-reconnect is disabled — not on normal disconnect()/cleanup. The flag resets at the end of onNetworkClose. Adds debug lifecycle logging in Connection (constructor, connect, close, _handleCloseTimeout), BrowserSession.connect(), and SignalingHealthMonitor (no pending recovery, connection not connected). reconnectDelay is now computed once before logging and setTimeout, so the logged value matches the scheduled delay.
  • Remove ICE restart Modify workarounds for trickle ICE and reattached calls (#697) Removes two temporary SDK workarounds now that b2bua-rtc supports both trickle ICE for Modify and ICE restart after attach recovery. Peer.handleNegotiationNeededEvent() no longer gates the trickle path on !isIceRestarting — trickle-enabled calls now use startTrickleIceNegotiation() for ICE restart just as they do for initial negotiation. The isIceRestarting suppression is removed from the onicecandidate handler in _registerPeerEvents(), so restart candidates route through _onTrickleIce(). _sendIceRestartModify() accepts an optional { trickle?: boolean } flag so the backend knows to expect trickled candidates. triggerIceRestart() no longer skips attach/recovered calls — reattached/recovered calls now use the same ICE restart path as normal active calls. SignalingHealthMonitor no longer forces a socket reconnect when ICE restart returns { started: false }; signaling recovery is owned by the monitor’s own health checks.
  • feat(webrtc): persist active-call recovery markers and emit SESSION_NOT_REATTACHED after page reload (#698) Before page unload (when hangupOnBeforeUnload === false), the SDK now persists a minimal safe projection of active calls to sessionStorage under a single-key IStoredActiveCalls container ({ sessionId, calls: [{ id, customHeaders }], storedAt }). After reload/reconnect recovery, VertoHandler compares saved markers against the server’s reattached sessions for the current sessid and emits SESSION_NOT_REATTACHED (48501, moved from warning 35001 to a proper error code) once for any saved call that was not reattached, then clears storage immediately (at-most-once). Storage has a 15-minute staleness deadline and is fail-safe (try/catch with debug logs on all return/catch paths). keepConnectionAliveOnSocketClose does not interfere — that path only governs PUNT/server-initiated socket disconnects and never fires beforeunload. The SDK does not recreate call objects from saved records and does not hang up calls represented only by markers (notification-only). A new UNKNOWN_REATTACHED_SESSION warning (35002) was added for the inverse case.
  • feat(webrtc): harden RECONNECTION_EXHAUSTED + WEBSOCKET_CONNECTION_FAILED local call teardown (#700) Adds a mandatory fatal: boolean to every SDK error in the registry, surfaced on ITelnyxError/TelnyxError (and toJSON). Defaults are per-code: terminal errors (UNEXPECTED_ERROR, BYE_SEND_FAILED, WEBSOCKET_CONNECTION_FAILED, LOGIN_FAILED, AUTHENTICATION_REQUIRED, RECONNECTION_EXHAUSTED, etc.) default to fatal: true; recoverable errors default to fatal: false. Emit sites override only when context flips the default (e.g. Peer media-recovery flow emits fatal: false). A new BaseSession._terminateActiveCallsLocally() tears down all active calls via call.hangup({}, false) (execute=false, no outbound BYE since the socket is already dead) before emitting RECONNECTION_EXHAUSTED at all three sites: VertoHandler (autoReconnect-disabled TIMEOUT path + retry-exhaustion path) and BaseSession.onNetworkClose exhaustion. WEBSOCKET_CONNECTION_FAILED now triggers the same local teardown. SignalingHealthMonitor.onIceRestartFailed now triggers socket reconnect via _triggerSignalingRecovery('peer_failure') instead of only logging. Peer no longer double-emits telnyx.error from _setLocalDescription/_setRemoteDescription — it propagates the TelnyxError as-is so the upper-level catch in BaseCall.invite()/answer() emits once; unexpected errors are wrapped in SDP_CREATE_OFFER_FAILED/SDP_CREATE_ANSWER_FAILED. The fire-and-forget startTrickleIceNegotiation() call sites in init() and handleNegotiationNeededEvent() now have .catch(_emitNegotiationError) to avoid an unhandled rejection regressing telnyx.error delivery during trickle ICE setup. Top-level recoverable field is untouched for backward compatibility.

Call/media state and lifecycle

  • fix(webrtc): add null guards to connection state event handlers (#671) Adds null-guard clauses to _handleIceConnectionStateChange and handleConnectionStateChange that return early with debug logging if the peer connection instance is already null/closed, preventing NullReferenceException crashes on event handlers fired during teardown.
  • feat: emit MULTIPLE_ACTIVE_CALLS_DETECTED warning (#676) Emits a diagnostic warning (33010) via SwEvent.Warning when a new call is created (outbound via newCall) or received (inbound via Invite) while other calls are already active in the session. The payload includes safe correlation IDs per call (callId, state, direction, and telnyxSessionId/telnyxLegId/sipCallId where present) — no credentials, SDP, or phone numbers. Recovered calls reached via Attach are treated as active calls (no recovery-call filtering). Warning-only: it does not block or reject any call. A debug log in answer() (filtering this.id out of the active-calls check) records when an inbound call is actually answered while other calls exist, complementing the ring-time warning.
  • feat: add LOW_INBOUND_AUDIO warning to detect one-way audio with RTP flow (#701) The SDK already monitored local microphone audio (LOW_LOCAL_AUDIO) and whether any bytes arrived at all (LOW_BYTES_RECEIVED), but had no warning for the case where RTP packets flow normally yet carry silence or comfort-noise instead of real speech — the exact signature of one-way audio caused by a media bridge (e.g. FreeSWITCH comfort-noise injection). Adds LOW_INBOUND_AUDIO (31006) which fires when inboundAudioLevelAvg stays below 0.001 for 3 consecutive stats intervals (the same consecutive-breach mechanism used by other quality warnings). The interval resets when no inbound audio data is available for a given interval to avoid false positives.
  • BYE execution timeout guard (#671) BaseCall.hangup() now wraps _execute(bye) in a Promise.race with a 5-second BYE_TIMEOUT_MS guard. If BYE execution hangs (socket stalled, server unresponsive), the call proceeds to Destroy after 5s so the call is always cleaned up. The timeout handle is cleared in all paths (resolve, reject, timeout) via the finally block.
  • Audio mute state now persists across track replacement (#671) Introduces a _desiredAudioMuted field on BaseCall (initialized from mutedMicOnStart) that is the source of truth for isAudioMuted (previously derived from !isAudioTrackEnabled(localStream)). muteAudio/unmuteAudio/toggleAudioMute now update _desiredAudioMuted and call a new internal _applyDesiredAudioMuteState(), which is also exposed to Peer via options.applyDesiredAudioMuteState and re-applied whenever Peer creates or replaces local audio tracks (init, reattach, setAudioInDevice, setVideoDevice, ICE restart). This fixes mute being lost when the SDK swaps the local audio track. setAudioInDevice now defaults the muted argument to _desiredAudioMuted (instead of mutedMicOnStart).
  • AUDIO_INPUT_DEVICE_CHANGE_SKIPPED warning + setAudioInDevice hardening (#671) setAudioInDevice now warns (33009, AUDIO_INPUT_DEVICE_CHANGE_SKIPPED) and returns early when no audio sender is found, instead of silently no-op’ing. getUserMedia failures no longer change the desired mute state (the old track stays active). Added structured debug logging for the device-change flow (state, deviceId, previous/new desired mute, current sender track, local tracks) via new getTrackDebugInfo/getStreamTrackDebugInfo helpers.
  • MediaDeviceCollector for device-change diagnostics (#671) New MediaDeviceCollector logs all enumerated audio input/output devices at debug level on call start, and logs connect/disconnect events on devicechange. Helps identify whether the right mic/speaker was available and whether devices changed mid-call when a customer reports “agent could not hear audio” but inbound RTP stats are healthy.

Call reports and observability

  • fix: include selected ICE evidence in call reports (#686) Call reports now include the selected candidate pair (resolved from transportStats.selectedCandidatePairId, with a fallback search when the stat isn’t directly retrievable) plus the localCandidateId/remoteCandidateId references and the selectedCandidatePairId itself, so investigators can reconstruct the actually-nominated ICE path rather than only candidate-pair snapshots.
  • Collect call report stats every second for full call duration (#702) Replaces the previous two-phase cadence (1s for the first 10s, then 5s) with a constant 1-second collection interval for the full call duration, giving full-resolution stats for every call regardless of length. Removed the now-dead intervalStartTime parameter from _collectionIntervalFor.
  • feat(webrtc): collect additional inbound RTP fields in call reports (#705) Adds nackCount, jitterBufferTargetDelay, and jitterBufferMinimumDelay to inbound RTP stats, plus a per-stream codec snapshot.
  • feat(webrtc): collect additional outbound RTP fields in call reports (#706) Extends outbound RTP stats with the additional fields needed for outbound loss/jitter/RTT visibility.
  • feat(webrtc): collect remote RTCP stats for outbound loss/jitter/RTT visibility (#703) Parses remote-inbound-rtp (RTCP Receiver Report describing our outbound stream) and remote-outbound-rtp (RTCP Sender Report from the remote peer) into a new remoteRtcp block on call reports: inbound carries packetsLost, jitter (ms), roundTripTime, roundTripTimeMeasurements, nackCount, localId; outbound carries localId, remoteId, roundTripTime. roundTripTimeSource is recorded on the audio stats so investigators know which RTCP report the RTT came from.
  • feat(webrtc): collect codec identity in call reports (#704) Adds an extended RTCCodecStats snapshot (mimeType, clockRate, channels, payloadType, codecId) referenced by outbound-rtp/inbound-rtp via codecId, so call reports identify the negotiated codec for each RTP stream.
  • feat(webrtc): collect media-playout stats in call reports (#707) Adds extended media-playout stats (type media-playout, audio) reporting playout delay and synthesized-sample indicators — useful for detecting client-side playout anomalies and comfort-noise/synthesized audio.

Public API / configuration

  • feat: add skipTrailing option to IClientOptions / IVertoOptions (#671) When true, appends skip_trailing=true to the VSP WebSocket URL so VSP skips pre-routing identity resolution (telephony-tokens validation and UsersClass trailing checks) for this connection. Intended for internal/test-infra usage (e.g. BBT-generated credentials) where the connection should not participate in trailing-release routing. The actual login still goes to the upstream RTC service for normal authentication — this only skips VSP’s pre-routing lookup. Default false.
  • docs: clarify target_params.conversation_id semantics (#671) Rewrites the TargetParams.conversation_id JSDoc to make explicit that it is not a customer-defined correlation ID — it joins an existing Telnyx AI conversation. When omitted, the TeXML endpoint starts a new conversation by rendering <AIAssistant id="...">; when provided, voice-sdk-proxy maps it to X-AI-Assistant-Conversation-ID and the TeXML endpoint renders <AIAssistant join="...">. Documents that a non-existent / non-owned conversation id will fail (e.g. AI Assistant error code 10007).

Internal / tooling

  • History between the two tags was re-based through a squashed root commit (#671, orphan commit with no parent); the squashed state folded in the audio-mute, BYE-timeout, MediaDeviceCollector, skipTrailing, and conversation_id docs work above, which did not land as standalone PRs. Functional end-state diff between v2.27.1 and v2.27.2 is the source of truth for this changelog.

Consumer-visible notes

  • Reconnect behavior: socket reconnect now uses exponential backoff (1s → 30s cap, 25% jitter) and is dedup’d against duplicate onerror/onclose events for the same socket generation. Reset happens only on a confirmed REGED.
  • Fatal errors: ITelnyxError now carries a fatal: boolean. Terminal errors (RECONNECTION_EXHAUSTED, WEBSOCKET_CONNECTION_FAILED, LOGIN_FAILED, AUTHENTICATION_REQUIRED, UNEXPECTED_ERROR, BYE_SEND_FAILED, …) default to fatal: true; recoverable ones default to false. When reconnect is exhausted or the WebSocket fails to connect, all active calls are now torn down locally (no BYE) before the error is emitted.
  • Recovery after page reload: if hangupOnBeforeUnload is false, active calls are persisted to sessionStorage (15-min TTL) and a SESSION_NOT_REATTACHED error is emitted post-reload for any saved call the server did not reattach. The SDK does not recreate or hang up those calls.
  • ICE restart: reattached/recovered calls now go through the same ICE restart path as normal calls (workarounds removed); trickle ICE is used for ICE restart Modify; a failed ICE restart now triggers signaling/socket recovery.
  • Mute: mute now survives track replacement (device switch, reattach, ICE restart). isAudioMuted reflects the desired state, not the live track flag. setAudioInDevice no longer silently no-ops when no sender exists — it emits AUDIO_INPUT_DEVICE_CHANGE_SKIPPED.
  • Diagnostics: new warnings LOW_INBOUND_AUDIO, MULTIPLE_ACTIVE_CALLS_DETECTED, AUDIO_INPUT_DEVICE_CHANGE_SKIPPED, RECONNECTION_FAILED_WITH_NO_AUTO_RECONNECT, UNKNOWN_REATTACHED_SESSION; new error SESSION_NOT_REATTACHED; removed warning codes SESSION_NOT_REATTACHED (35001, promoted to error), SIGNALING_HEALTH_PROBE_TIMEOUT, SIGNALING_REQUEST_TIMEOUT.
  • Call reports: 1-second collection for the full call duration; richer inbound/outbound RTP, remote RTCP (loss/jitter/RTT), codec identity, media-playout, and selected ICE evidence for RTC investigations.
  • Config: new skipTrailing option (internal/test-infra).

2.27.2-beta.1 (2026-06-29)

  • No notable changes

2.27.2-beta.0 (2026-06-29)

  • docs: update ts docs

2.27.1 (2026-05-27)

  • fix: include sessid on reconnect login (#657)
  • fix: preserve reconnect token across unload (#656)
  • fix: relax signaling health probe cadence (#655)
  • fix: allow disabling beforeunload BYE (#653)
  • chore: release webrtc@2.27.0 (#652)

2.27.0 (2026-05-22)

Call/media recovery

  • Feat: initial restart ice implementation (#607) Adds active-call ICE restart support. When RTCPeerConnection.connectionState becomes failed or disconnected, the SDK can call restartIce(), create a new offer, and exchange the renegotiated SDP with Verto using telnyx_rtc.modify / updateMedia instead of leaving the call stuck until hangup or socket-level attach recovery. The implementation keeps socket reconnect / attach recovery as the owner when signaling is offline or disconnected.
  • Fix: signaling health recovery for half-dead WebSocket (#650) Handles cases where a network interface changes and the browser still reports the WebSocket as OPEN, but the underlying TCP path no longer receives signaling frames. SignalingHealthMonitor now centralizes the recovery decision: unhealthy or stale signaling forces socket reconnect, while healthy signaling plus peer/media failure can use ICE restart. The SDK also tracks all inbound WebSocket activity as liveness evidence and scopes request timeouts to critical signaling methods (modify, bye, ping).
  • fix: skip ice restart for reattached calls (#651) Detects calls recovered through telnyx_rtc.attach / reattach and avoids running another ICE restart against that recovered call. Later media failures on reattached calls now route through socket reconnect + attach recovery, and the SDK avoids emitting MEDIA_RECOVERY_REQUIRED when ICE restart is intentionally bypassed.
  • fix: recover VPN media stalls over relay (#642) Adds a conservative relay-only escalation path for recovered calls that stall again on VPN/non-relay paths. First recovery still uses normal ICE behavior. If an already recovered call stalls again with evidence such as ICE disconnected/failed, requests increasing without responses, or outbound bytes increasing while inbound stays flat, the next attach recovery can request forceRelayCandidate: true / iceTransportPolicy: 'relay'.

Call state and lifecycle fixes

  • fix: ignore late SDP responses after hangup (#643) Ignores delayed invite/answer SDP execute responses after the call has already moved to hangup, destroy, or purge. This prevents a late invite result from reviving an outbound call from hangup back to trying.
  • fix: prevent duplicate inbound answers (#622) Adds a per-credential inbound-answer guard so duplicate TelnyxRTC instances in the same JS runtime cannot both answer duplicate inbound call legs. When a duplicate answer is ignored, the SDK emits a DUPLICATE_INBOUND_ANSWER warning and releases the guard when the owning call is destroyed.
  • VSDK-199: detach media elements on call finalization (#628) Clears local and remote media element srcObject references during call finalization after streams are stopped. This fixes Chromium setSinkId() failures caused by elements remaining attached to ended MediaStream objects.

Reconnect behavior

  • VSDK-197: Add maxReconnectAttempts option for socket reconnection limit (#629) Adds maxReconnectAttempts to IClientOptions / IVertoOptions. The default is bounded automatic reconnect behavior (10 attempts), while explicit 0 keeps unlimited retries. When the limit is reached, the SDK disables automatic reconnect and emits telnyx.error with RECONNECTION_EXHAUSTED (45003). Attempts reset on successful REGED, manual connect() after exhaustion, and disconnect().

Call reports and observability

  • fix: collect initial call report stats every second (#633) Samples call-report stats every second for the first 10 seconds of each call, then falls back to the configured longer interval. This improves diagnostics for short calls and early-call media problems while preserving the existing report payload contract.
  • feat: warn on low local audio (#634) Adds a LOW_LOCAL_AUDIO warning through the existing telnyx.warning quality-event path. The warning is based on sustained low outbound local audio level, including values derived from local totalAudioEnergy deltas, while suppressing alerts when the local track is intentionally disabled or muted.
  • fix: retry failed call report uploads (#635) Retries failed call-report POSTs on non-2xx responses and network errors with bounded backoff. Final reports can use fetch(..., { keepalive: true }) during teardown, and disconnect() drains pending report uploads for up to 10 seconds before closing the WebSocket. Active calls can also submit intermediate report segments using callReportFlushInterval.
  • fix: flush call reports on socket close (#639) Flushes active calls as intermediate call-report segments when the socket closes. Flush reasons now include structured socket-close metadata such as close code, code name, reason, wasClean, and error details when available.
  • VSUP-65: Fix stale call establishment timing marks (#637) Scopes performance marks by call_id so stale marks from previous calls cannot pollute later call-establishment timing calculations. This fixes inflated timing values such as the reported 237-second ringing duration and adds cleanup coverage for peer close/finalization paths.
  • fix: log local audio source diagnostics (#625) Adds local audio sender track metadata and outbound media-source stats to call reports, including selected input settings, track state, audioLevel, totalAudioEnergy, and related local source details. This helps distinguish RTP transport issues from wrong, muted, ended, or silent local input devices.
  • fix: log hangup caller metadata (#624) Logs structured hangup() invocation metadata before teardown, including pre-hangup state, execute flag, selected cause/causeCode, SIP fields, recovery/custom-header flags, and a caller stack snapshot.
  • fix: ICE candidate pair change log with full path details (#645) Replaces opaque previous/current candidate-pair IDs with full candidate-pair snapshots. Candidate-pair change logs now include local/remote candidate details such as address, port, candidate type, protocol, network type, nominated/writable state, and request/response counters.

Documentation and generated artifacts

  • docs: clarify SDK STUN and TURN firewall URLs (#621) Documents the JavaScript SDK production STUN/TURN URL list and clarifies TURN TCP fallback guidance for restrictive firewall environments.
  • docs: update ts docs Regenerates TypeScript API documentation for the public surfaces changed in this release, including Call, TelnyxRTC, VertoModifyAction, IClientOptions, ILocalAudioSourceStats, and ILocalAudioTrackSnapshot.

Consumer-visible notes

  • Active-call media recovery is now more explicit: healthy signaling plus media failure uses ICE restart; unhealthy or stale signaling uses socket reconnect / attach recovery; already reattached calls skip ICE restart and recover through reconnect / attach.
  • maxReconnectAttempts is now available and defaults to bounded reconnect attempts. Set it to 0 to preserve unlimited automatic reconnect retries.
  • Call-report payloads and SDK warnings now include richer local audio, socket-close, candidate-pair, hangup, and upload/retry diagnostics for RTC investigations.

2.26.4 (2026-04-29)

  • docs: update ts docs
  • feat: add skipLastVoiceSdkId option for voice-sdk-proxy PR #122 (#616)
  • fix: prevent double answer when peer connection already exists (#614)
  • chore: release webrtc@2.26.3 (#613)

2.26.3 (2026-04-24)

  • feat: expose clearReconnectToken() to break b2bua-rtc stickiness on retry (#610)

2.26.2 (2026-04-13)

Region & Datacenter Visibility

  • feat: log region and dc at info level on connect and new call (#605) client.region and client.dc are now logged at info level (previously debug) when the client connects and on every new call. Logs now show:

Documentation

  • docs: update region/DC info and DNS routing details (#604) Updated network connectivity docs: fixed CN1 location (Chennai, not Hong Kong), added regional signaling endpoints table, documented client.region and client.dc properties.

Other

  • fix(types): point types field at lib/src/index.d.ts (#601)
  • chore: add workflow to deprecate/undeprecate npm package versions (#568)

2.26.1 (2026-04-10)

Structured Errors & Warnings

  • Feat: wire structured errors and warnings across SDK (#548) Comprehensive overhaul introducing typed error codes (40xxx49xxx) and warning codes (3xxxx) throughout the SDK. Replaces previously swallowed errors with structured TelnyxError events and ITelnyxWarning notifications while maintaining backward compatibility.
    • SDP errors (400xx): offer, answer, local/remote description, and send failures
    • Media errors (420xx): microphone permission denied, device not found, general media failures
    • Call-control errors (440xx): hold failed, invalid parameters, BYE send failed, subscribe failed
    • WebSocket/transport errors (450xx): connection failed, reconnection exhausted, gateway failures
    • Authentication errors (460xx): login failed, invalid credentials, authentication required
    • Network errors (480xx): network offline
    • Quality warnings (310xx): high RTT, jitter, packet loss, low MOS
    • Connection warnings (320xx): low bytes received/sent
    • ICE warnings (330xx): connectivity lost, gathering timeout, peer connection failed, host-only candidates
    • Auth warnings (340xx): token expiring soon
    • Session warnings (350xx): session not reattached
  • Chore: improve errors docs and export error/warning code constants (#602) Restructured error-handling documentation for clarity. Exports TELNYX_ERROR_CODES and TELNYX_WARNING_CODES from the main package index so consumers can reference them directly. Listening for errors and warnings:

Media Recovery

  • Fix: interrupt call negotiation on media failure for non-receive-only peers (#582) When media retrieval (e.g. microphone access) fails during peer initialization, the SDK now interrupts call negotiation immediately instead of continuing into SDP setup. Previously, media failures triggered hangup asynchronously, creating a race condition where an answer SDP could be created before hangup executed on inbound calls. Receive-only peers are unaffected since they do not require local media. Media recovery on inbound calls:
  • Fix: remove trickleIce guard for attach method (WEBRTC-3395) (#584) Removes the forced trickleIce=false override for the attach (reconnection) method. The guard was originally added for b2bua-rtc codec negotiation compatibility but is no longer needed.

Call Teardown & Disconnect

  • Fix: separate client.disconnect() and PUNT disconnect paths with correct BYE behavior (#580) Distinguishes between client-initiated graceful disconnect and server-initiated disconnect (PUNT). client.disconnect() now sends BYE messages to active calls before purging; PUNT triggers serverDisconnect() which purges calls without BYE since the server connection is already gone.
  • Feat: make hangup async, properly await BYE execution (#581) Breaking: hangup() is now an async method returning Promise<void> (previously synchronous/fire-and-forget). Callers can now await hangup() to ensure BYE messages are fully sent before proceeding, enabling clean call termination sequences.

Features

  • Feat: store source datacenter identifier from REGED message (#583) The SDK now extracts and stores dc and region fields from the REGED WebSocket message, allowing consumers to identify which Telnyx regional infrastructure handled their connection.

Bug Fixes

  • fix(types): point types field at lib/src/index.d.ts (#601)

Documentation

  • docs: Voice SDK Network Connectivity Requirements (#564) New comprehensive guide covering signaling server endpoints, STUN/TURN addresses, media server IP subnets, port ranges (UDP 16384–32768), bandwidth requirements (Opus ~40 kbps, PCMU ~100 kbps), firewall configuration, and best practices for enterprise/VPN environments.

CI / Chores

  • fix(ci): push release branch before pinning draft release target (#597)
  • fix(ci): pin draft target to bump SHA, publish from tag (#596)
  • fix(ci): single release-it call for bump + tag + draft (#593, #594)
  • fix(ci): allow non-immutable installs for draft release tagging step (#592)
  • fix(ci): drop lockfile update step, set YARN_ENABLE_IMMUTABLE_INSTALLS=false (#591)
  • fix(ci): use —mode update-lockfile to avoid upgrading all deps (#589)
  • fix(ci): update lockfile after version bump in draft-release (#587)
  • fix(ci): create release tag after version bump commit (#586)
  • chore: include README.md in npm packages and remove Slack notifications (#578)

2.26.1-beta.2 (2026-04-08)

  • chore: release webrtc@2.26.1-beta.1 (#595)
  • fix(ci): allow non-immutable installs for draft release tagging step (#592)
  • fix(ci): allow non-immutable installs for draft release tagging step
  • fix(ci): drop lockfile update step, set YARN_ENABLE_IMMUTABLE_INSTALLS=false (#591)
  • fix(ci): use —mode update-lockfile to avoid upgrading all deps (#589)
  • fix(ci): update lockfile after version bump in draft-release (#587)
  • fix(ci): create release tag after version bump commit (#586)
  • Fix: interrupt call negotiation on media failure for non-receive-only peers (#582)
  • feat: make hangup async, properly await BYE execution (#581)
  • Feat: wire structured errors and warnings across SDK (#548)

2.26.1-beta.1 (2026-04-08)

  • fix(ci): allow non-immutable installs for draft release tagging step (#592)
  • fix(ci): allow non-immutable installs for draft release tagging step
  • fix(ci): drop lockfile update step, set YARN_ENABLE_IMMUTABLE_INSTALLS=false (#591)
  • fix(ci): use —mode update-lockfile to avoid upgrading all deps (#589)
  • fix(ci): update lockfile after version bump in draft-release (#587)
  • fix(ci): create release tag after version bump commit (#586)
  • Fix: interrupt call negotiation on media failure for non-receive-only peers (#582)
  • feat: make hangup async, properly await BYE execution (#581)
  • Feat: wire structured errors and warnings across SDK (#548)

2.26.1-beta.0 (2026-04-07)

  • docs: update ts docs
  • fix: read dc/region instead of local_dc/local_region from REGED params
  • refactor: rename localDc/localRegion to dc/region and use structured logging
  • feat: store local_dc and local_region from REGED message
  • feat: store source datacenter identifier from REGED message
  • chore: include README.md in npm packages and remove Slack notifications (#578)

2.26.0 (2026-03-31)

  • chore: upgrade Node.js to 24.5.0 (npm 11.5.1 for OIDC trusted publishing) (#576)

2.25.29 (2026-03-31)

  • fix: upgrade actions/setup-node from v4 to v6 for OIDC compatibility (#574)

2.25.28 (2026-03-31)

  • chore: upgrade Node.js from 18 to 22.14 across all workflows (#572)
  • chore: release webrtc@2.25.27 (#571)

2.25.27 (2026-03-31)

  • chore: remove NODE_AUTH_TOKEN from publish steps for OIDC auth (#570)

2.25.26 (2026-03-31)

  • fix: guard against null localDescription in _onIceSdp (#557)
  • chore: consolidate publish workflows for npm trusted publisher OIDC (#567)
  • fix: reset keepalive on any inbound message to prevent false ping/pong warnings (#556)
  • fix: don’t null global LogCollector on call cleanup (#555)
  • chore: add OIDC permissions and npm provenance to prerelease workflow (#566)
  • chore: add OIDC permissions and npm provenance to publish-release workflow (#565)

2.25.26-beta.2 (2026-03-13)

  • docs: update ts docs
  • feat: add recoveredCallId to call object for recovery correlation (ENGDESK-50308)

2.25.25 (2026-03-11)

  • docs: update ts docs
  • fix: disable trickle ICE for attach (reconnection) (#550)
  • feat: add recvonly audio transceiver when audio=false (WEBRTC-3394) (#549)
  • feat(WEBRTC-3324): support target_params in anonymous_login (#542)
  • feat: auto-trigger developer docs update on JS SDK release (#545)

2.25.24 (2026-03-03)

  • docs: update ts docs
  • fix: handle getUserMedia failure gracefully (no microphone) (#541)
  • feat: add audioLevel + transport stats to call report (WEBRTC-3321) (#540)

2.25.23 (2026-02-27)

  • docs: update ts docs
  • feat: add ICE candidate pair stats to call report (WEBRTC-3302) (#538)
  • chore: release webrtc@2.25.22 (#536)

2.25.22 (2026-02-26)

  • fix: retry once on network error when posting call report (#534)

2.25.21 (2026-02-25)

  • fix: send call reports for calls shorter than the collection interval (#532)

2.25.20 (2026-02-25)

  • fix: serialize log context to capture DOM Event properties in call reports (#520)
  • chore: update CODEOWNERS to @lucasassisrosa @ArtemPapazian (#530)
  • fix: set direction before setState on inbound invite (#527)
  • fix: use state-dependent hangup cause code (#528)

2.25.19 (2026-02-23)

  • fix: commit CHANGELOG.md before yarn release to avoid dirty worktree error (#524)
  • fix: strip localElement and remoteElement from dialogParams (#450) (#521)
  • fix: keep loglevel at debug so LogCollector captures all logs for call reports (#522)
  • feat: enable prefetchIceCandidates by default (#523)
  • fix: Apply safety timeout to all close() calls (#515)
  • chore: generate CHANGELOG.md in draft-release workflow (#519)
  • chore: use ubuntu-latest runner for draft-release workflow (#517)
  • feat: automatic call quality reporting to voice-sdk-proxy (#494)
  • fix: reuse single VertoHandler instance and convert static state to instance state (#509)
  • fix(WEBRTC-3267): Fire telnyx.ready event on reconnection (#513)
  • fix(WEBRTC-3266): Prevent race condition in network reconnection by deferring _wasOffline reset (#511)
  • fix(ENGDESK-49463): use correct hangup code (16) instead of hardcoded USER_BUSY (17) (#506)
  • fix: set TURN transport to udp as default and tcp as fallback (#495)
  • fix: stop debug reporter when peer connection is closing (#498)
  • fix: remove canary flag requirement for trickleIce (#507)
  • fix: remove trickle ICE support check that sends empty candidate on login (#500)
  • docs: add 4014 gateway down close code to error handling (#504)
  • chore: fix TelnyxRTC.md (#497)
  • fix: if we get attach always run reconnection flow (#503)
  • FIX: Reconnection flow (#492)
  • feat: getUserMedia fallback for device-specific errors (#490)
  • docs: add authentication error handling documentation (#491)
  • fix: documentation on event listening (#489)

2.25.18 (2026-02-10)

  • fix: use correct hangup code (16) instead of hardcoded USER_BUSY (17)
  • fix: stop debug reporter when peer connection is closing
  • fix: remove canary flag requirement for trickleIce
  • fix: remove trickle ICE support check that sends empty candidate on login
  • fix: set TURN transport to udp as default and tcp as fallback
  • fix: if we get attach always run reconnection flow
  • docs: add 4014 gateway down close code to error handling
  • chore: fix TelnyxRTC.md
  • chore: add meta-dev.yml for GitHub access control

2.25.17 (2026-02-02)

  • fix: reconnection flow
  • feat: implement manual Login function
  • feat: getUserMedia fallback for device-specific errors

2.25.16 (2026-01-22)

  • fix: documentation on event listening
  • docs: add authentication error handling documentation
  • docs: document manual re-authentication with new token

2.25.15 (2026-01-12)

  • fix: recreate call if peer connection signaling state is closed
  • chore: restart debug stats reporter on session reconnect
  • chore: expose PeerConnectionSignalingStateClosed event
  • chore: update documentation for event and error handling
  • fix: remote stream assignment to properly persist (@maiconpavi)
  • fix: propagate session forceRelayCandidate option to call
  • fix: address race condition on peer creation during reconnect
  • fix: active call leg on reconnection with ice restart
  • fix: send hangup msg before reconnectionOnAttach flag activation
  • fix: avoid creating multiple calls on reconnection
  • fix: flag usage on attach handler nested condition
  • fix: hangup bye execute logic and buffer manipulation
  • feat: update documentation on flag optimistic behavior

2.25.14 (2025-12-16)

  • fix: make sure offerToReceiveAudio is set if call audio options is undefined

2.25.12 (2025-12-15)

  • feat: clear intervals setup on device sleep wake

2.25.11 (2025-12-15)

Enhancements

  • normalize logging calls
  • improve debug logs and socket disconnect on retry
  • add device sleep mode detection code

Fixes

  • address connection state not transitioning
  • maintain call state on peer connection signaling state change

2.25.10 (2025-12-04)

  • fix: consider keepConnectionAliveOnSocketClose in session call for Punt
  • fix: do not empty execution queue on keepConnectionAliveOnSocketClose to avoid old refs

2.25.9 (2025-12-02)

Enhancements

  • move mutedMicOnStart from call to client options

2.25.8 (2025-11-28)

Features

  • add iceServers to client options
  • add mutedMicOnStart to call options

2.25.7 (2025-11-25)

Features

  • add useCanaryRtcServer to client options

Enhancements

  • add call_id for debug_report_start and debug_report_stop messages

2.25.6 (2025-11-18)

Fixes

  • received authentication required counter cleanup

2.25.5 (2025-11-13)

Fixes

  • punt message handling logic on keepConnectionAliveOnSocketClose option set

Enhancements

  • add SwEvent handling reference with session readiness, notifications, diagnostics, and telemetry docs
  • add SwEvent error reference to error handling docs

2.25.4 (2025-11-12)

  • fix: ws connection down case on reconnection
  • chore: update keepConnectionAliveOnSocketClose docs to point users to client options usage

2.25.3 (2025-11-12)

  • fix: called createWebRTCStatsReporter before use statsReporter

2.25.2 (2025-11-07)

Enhancements

  • update audio constraints types in call options
  • update ts docs
  • log audio constraints applied to peer connection

Fixes

  • correct typings declaration file export

2.25.1 (2025-11-05)

Features

  • add keepConnectionAliveOnSocketClose to client options

Enhancements

  • improve logs on peer connection failure
  • remove legacy code
  • keep alive check on ping messages

Fixes

  • correct method scope in browser session
  • clear call and peer connection on unrecoverable state
  • add cleanup to network listeners
  • reconnect on false positive reged state from gateway
  • restart ice on offer peer only
  • do not disconnect session on punt if keepConnectionAliveOnSocketClose is set
  • hangup and recreate call if peer connection instance is destroyed

2.24.2 (2025-11-04)

  • chore: socket connection error handling documentation (#460)

2.24.1 (2025-10-30)

  • fix: update inner voice_sdk_id state on first trickle ice canary use (#459)

2.24.0 (2025-10-29)

Features

  • true trickle ice implementation (#439)

Enhancements

  • check for gateway trickle ice support and add fallback
  • improve logging on connection state changes
  • add trickle ice performance metrics
  • remove legacy video code

2.22.19 (2025-10-29)

fix: enforce callID from call options to be string (#456)

2.22.18 (2025-10-23)

fix: expose getIsRegistered (#448) fix: preferred codecs should only be enforced on INVITE, not on ANSWER (#452)

2.22.17 (2025-08-04)

chore: add detailed performance measuring for invite (#438)

2.22.16 (2025-08-04)

feat: add support for image attachments (#436)

2.22.15 (2025-07-24)

feat: pass target_version_id for anonymous login (#434)

2.22.14 (2025-07-09)

feat: send messages to AI agents (#432)

2.22.13 (2025-07-04)

fix: improve p2p connection establishment time (#431) fix: export Call via relative path (#429)

2.22.12 (2025-05-20)

chore: Tidy up exposed interfaces in entrypoint (#428)

2.22.11 (2025-05-14)

Bug fixes

fix: the pre-call diagnosis report sometimes doesn’t resolve. (#426)

2.22.10 (2025-05-09)

Bug fixes

fix: debug report file is not generated (#425)

2.22.9 (2025-04-14)

Features

feat: anonymous login and ai_agent calls (#420)

2.22.8 (2025-03-28)

Features

feat: regional subdomains for voice-sdk (#417)

2.22.7 (2025-03-06)

Features

feat: implement real time call quality metrics (#414) feat: implement pre-call diagnosis (#407)

Bug fixes

fix: disable automatic video response in favor of answer option (#413)

2.22.6 (2025-02-20)

Bug fixes

fix: attach with video when receiving m=video sdp (#409)

2.22.5 (2025-01-17)

Bug Fixes

fix(webrtc): Stop ringback tone when call is hung up (#406)

2.22.4 (2025-01-14)

Bug fixes

Fix inconsistency in reporting addConnection debug event through the websocket

2.22.3 (2024-12-03)

Bug fixes

fix: Fix compatibility with NextJS

Features

feat: add option to force usage of relay candidate (#400)

2.22.2 (2024-11-14)

Enhancement

  • WebRTC Debug Report: Enhance collected data.

Features

  • add an option to allow ice candidate prefetching (#396)

2.22.1 (2024-10-14)

Bug Fixes

Improve stability for ICE gathering process. (See #391)

2.22.0 (2024-10-14)

Features

2.21.2 (2024-09-05)

Bug Fixes

2.21.1 (2024-08-22)

Bug Fixes

2.21.0 (2024-08-14)

Features

2.20.0 (2024-08-01)

Features

  • get registration state from the gateway (#366) (c5af08b)

2.19.0 (2024-06-20)

Features

Bug Fixes

2.18.0 (2024-06-10)

Features

2.17.0 (2024-05-28)

Features

  • propagate session id with error event (#358) (0f931ed)

2.16.0 (2024-05-14)

Features

2.15.0 (2024-04-30)

Features

2.14.0 (2024-04-26)

Features

  • implement debug output for file and websocket (#352) (8d1f8e6)

2.13.0 (2024-04-22)

Features

  • add probe to fetch webrtc statistics periodically (#350) (2a72b60)

2.12.0 (2024-04-05)

Features

  • add a faster work-around for ice gathering never completing (#349) (47e1863)

2.11.0 (2024-02-26)

Features

  • TELAPPS-4794: expose user agent on login (#343) (a8b9606)

Bug Fixes

  • ENGDESK-23349: bind telnyxids on ringing event for outbound calls (#342) (1b1df78)
  • ENGDESK-28811: call object direction is undefined upon receiving call (#341) (8ac5a3f)

2.10.2 (2024-02-20)

Bug Fixes

  • ENGDESK-26922: Make login_token optional (#340) (1c0b36a)

2.10.1 (2023-11-23)

Bug Fixes

  • the params.customHeaders was not being destructuring correctly the values (#339) (b7e1c2a)

2.10.0 (2023-11-22)

Features

  • ENGDESK-26634: add custom headers to invite and answer messages (#338) (69814b4)
  • ENGDESK-27107: Upgrade WebRTC library to support React 18 (#321) (66d0c0e)

2.9.0 (2023-01-31)

Features

  • ENGDESK-21003: add beforeunload event to hang up active calls when the browser is closed or refreshed (#304) (5f4a899)

2.8.2 (2022-09-28)

Bug Fixes

  • ENGDESK-19054: Voice SDK missing types when installed in TypeScript projects. (#299) (ae76c98)

2.8.1 (2022-07-07)

2.8.0 (2022-05-25)

Features

  • WEBRTC-1798: add ping request to the server to keep connected (#287) (95ce187)

2.7.6 (2022-04-26)

2.7.5 (2022-04-26)

2.7.4 (2022-04-25)

Bug Fixes

  • change timeout value of 500 to use a random number between 3000 (#246) (34a232a)
  • WEBRTC-1705: reverting dependabot updates to fix typedoc generation (#278) (5ac667d)

2.7.3 (2021-12-14)

Bug Fixes

  • change previousGatewayState only if gateWayState exist to avoid send many REGISTER messages (#244) (70c10fa)

2.7.2 (2021-12-13)

Bug Fixes

  • ENGDESK-12851: add code to avoid multiples REGED messages on the client side (#235) (86b3a0e)

2.7.1 (2021-12-09)

Bug Fixes

2.7.0 (2021-12-08)

Features

Bug Fixes

  • Hotfix: package.lock update and node upgrade to 14 (#228) (29b7c27)
  • WEBRTC-746: recursive call to getDevices when the browser does not support audiooutput like Safari and Firefox. (#223) (bbc2231)

2.2.7 (2021-01-08)

2.2.6 (2021-01-08)

2.2.5 (2021-01-06)

2.2.4 (2020-12-11)

2.2.3 (2020-12-04)

Changed

  • Updates to docs

2.2.2 (2020-11-19)

Bug Fixes

  • ENGDESK-7173: change the STUN_SERVER port from 3843 to 3478 (#60) (cc8f78f)

2.1.6 - 2020-10-05

Changed

  • Added cause and causeCode when hangup the call

2.1.5 - 2020-08-26

Changed

  • Removed adapter-webrtc it was breaking the react-native SDK

Added

  • Added improvements in production bundle code.

2.1.4 - 2020-08-26

Changed

  • Enabled multiple connections in multiple devices (browsers, tabs, and etc)
  • Changed localStorage to use sessionStorage on Login class to save sessid

2.1.3 - 2020-08-13

Added

  • Added SipReason SipCode and SIP Call ID to show friendly error messages.

Changed

  • Changed the project structure to use monorepo yarn workspaces.

2.1.2 - 2020-08-06

Fixed

  • Fixed alert message about Authentication required

2.1.1 - 2020-08-03

Added

  • Added a new react video example to make video call.

Updated

  • Updated storybook react example, removed deprecated methods, and added new ones.

Fixed

  • Fixed audio call on Firefox v78. It only add offerToReceiveAudio/offerToReceiveVideo when provided in the options

Security

  • Fixed vulnerabilities in some dev dependencies.

2.1.0 - 2020-07-09

Added

  • Added the property ringbackFile to provide a ringback audio file.
  • Added support to play ringback file when receive the event telnyx_rtc.ringing.
  • Added the property login_token to support login with ephemeral token.
  • Added CHANGELOG file.

Changed

  • Changed the property ringFile to be ringtoneFile.

Security

  • Fixed vulnerabilities in some dev dependencies.

2.0.3 - 2020-06-08

Added

  • Added setStateTelnyx method to BaseCall.ts.

2.0.2 - 2020-05-12

Added

  • Added support to react-native

2.0.1 - 2020-05-12

First Release!

Release: WebRTC SDK V2.22.17

feat: add call initialization metrics