> ## Documentation Index
> Fetch the complete documentation index at: https://developers.telnyx.com/llms.txt
> Use this file to discover all available pages before exploring further.

# WebRTC JS ChangeLog

> Release notes for the Telnyx JavaScript Voice SDK (@telnyx/webrtc). Track new features, breaking changes, bug fixes, and deprecations by version.

## [2.27.9](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.27.8...webrtc/v2.27.9) (2026-08-06)

### Features

* **expose supported regions** (VSDK-447) (#745): Export a new `Region` constant from the package entry point with the seven supported signaling regions (`EU`, `US_CENTRAL`, `US_EAST`, `US_WEST`, `CA_CENTRAL`, `APAC`, `SOUTH_ASIA`). `IClientOptions.region` now links to `Region` for the accepted values; omitting it keeps automatic routing, and arbitrary strings remain supported for backwards compatibility.
* **accept outbound AI conversation items** (#751): `Call.sendAIConversationMessage()` now accepts any `AIConversationOutboundItem` rather than only a `function_call_output`. In addition to returning client-side tool results, callers can now send a `response.audio_stream.subscribe` item to subscribe to ACA pre-playout assistant audio events. The new `AIConversationOutboundItem`, `AIConversationOutboundParams`, and `ResponseAudioStreamSubscribeItem` types are exported from the package entry point.

### Bug Fixes

* **preserve forceRelayCandidate across attach recovery and page refresh** (VSDK-467) (#753): A relay-only call could regress to `iceTransportPolicy:"all"` on a later attach-recovery or page-refresh reconstruction because the recovery heuristic returns false when relay is already enabled. The handler now ORs a carried `preservedForceRelayCandidate` flag with the heuristic decision, so an already-enabled relay policy is never cleared. The persisted recovery marker stores only a genuine `true` (checked with `=== true`, not truthiness) so malformed legacy markers never force relay.
* **detect a socket that receives but no longer sends** (VSUP-171) (#760): The `SignalingHealthMonitor` previously judged health solely from the last inbound WebSocket frame, so a socket where nothing the SDK sends is ever answered stayed "healthy" indefinitely while the registration was held uselessly. A second clock now tracks the last outbound request that came back answered; when frames keep arriving but nothing outbound has been answered for 45s (three b2bua-rtc ping cycles), a probe is sent, and if that probe is also unanswered within the existing 5s window the session is declared unhealthy and the normal reconnect path is taken. The inbound-silence trigger still fires first at 20s.
* **ignore deferred signaling after hangup** (#762): Deferred ICE and trickle-ICE callbacks (`_onIceSdp`, `_onTrickleIceSdp`, `_onIce`, `_onTrickleIce`) could fire after a call was already terminating or terminated, re-animating a torn-down peer. All four handlers now early-return when `_isTerminatingOrTerminated()` is true.

### Refactors

* **simplify host-only ICE diagnostics** (#755): Replace the `_requestAnotherLocalDescription` retry-and-error flow (which fired `onSdpReadyTwice` and re-requested a local description) with a single `_warnIfOnlyHostIceCandidates` check that emits an `ONLY_HOST_ICE_CANDIDATES` warning when the SDP contains only host candidates. The diagnostic is now non-blocking and no longer forces a renegotiation cycle.
* **remove legacy React Native support** (#757): Drop the unused `.native.ts` platform shims (`Call.native.ts`, `storage/index.native.ts`, `webrtc/index.native.ts`) and the `setSpeakerPhone` call method. These shims targeted React Native, which was never a supported platform for `@telnyx/webrtc` — the React Native Voice SDK lives in a separate repo. This is a dead-code removal, not a breaking change for any supported target.

### Documentation

* Sync internal docs with the current implementation (#761): Restore internal API types to `docs/internal/`, clean `docs/ts/` to public-only content, mark deprecated notification types, and add the `response.audio_stream.subscribe` README example. TSDoc auto-generation is now off; `docs/ts/` and `docs/internal/` are hand-maintained on release.

## [2.27.8](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.27.7...webrtc/v2.27.8) (2026-07-23)

* docs: update ts docs
* fix: post CallRecorder tracks concurrently so the remote segment is not dropped (VSDK-453) (#746)

## [2.27.7](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.27.6...webrtc/v2.27.7) (2026-07-22)

* fix(js): suppress silence warnings and no-RTP recovery while held (VSUP-145) (#747)

## [2.27.6](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.27.5...webrtc/v2.27.6) (2026-07-20)

* feat(js): add internal PN late fanout login flag (#741)

## [2.27.5](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.27.4...webrtc/v2.27.5) (2026-07-15)

* docs: split CN1 (Chennai) into its own South Asia region (VSDK-82) (#739)
* feat(js): support push when active (#735)
* feat(ice): add primary TURNS 443 endpoint (#738)

## [2.27.4](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.27.3...webrtc/v2.27.4) (2026-07-08)

* docs: update ts docs
* fix(ice): keep TURN TCP/3478 in prod defaults; sync prod/dev ICE lists (#731)
* feat: export TELNYX\_ICE\_SERVERS public ICE server catalog (#730)
* feat: add TURNS (TURN over TLS/TCP) port 443 ICE servers (#674)
* feat: CallRecorder — single-submission raw audio capture at end of call (VSDK-279) (#708)
* refactor(sdk): move browser offline/online listeners into SignalingHealthMonitor (VSDK-214 part 2) (#710)
* feat: scoped inbound answer blocking per callID (#724)
* feat: add AI conversation signaling API for client-side tools (#682)
* feat: flush call report on beforeunload (keepalive) (#718)

## [2.27.3](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.27.2...webrtc/v2.27.3) (2026-07-01)

* fix(js): re-stamp reconnect session-id on visibilitychange → hidden (#717)
* fix(sdk): send login synchronously on WebSocket open to avoid event loop congestion (#713)

## [2.27.2](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.27.1...webrtc/v2.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.1](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.27.0...webrtc/v2.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](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.26.4...webrtc/v2.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](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.26.0...webrtc/v2.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](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.26.0...webrtc/v2.26.3) (2026-04-24)

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

## [2.26.2](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.26.1...webrtc/v2.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:
  ```text theme={null}
  Connected to Telnyx — region: apac, dc: cn1
  New Call — region: apac, dc: cn1 { destinationNumber: "...", ... }
  ```

### 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](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.26.0...webrtc/v2.26.1) (2026-04-10)

### Structured Errors & Warnings

* **Feat: wire structured errors and warnings across SDK** (#548)
  Comprehensive overhaul introducing typed error codes (`40xxx`–`49xxx`) 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:**

  ```ts theme={null}
  import {
    SwEvent,
    TelnyxError,
    TELNYX_ERROR_CODES,
    TELNYX_WARNING_CODES,
  } from '@telnyx/webrtc';

  client.on(SwEvent.Error, (event) => {
    switch (event.error.code) {
      case TELNYX_ERROR_CODES.MICROPHONE_PERMISSION_DENIED:
        showMessage('Microphone access was denied.');
        break;
      case TELNYX_ERROR_CODES.NETWORK_OFFLINE:
        showMessage('You appear to be offline.');
        break;
      case TELNYX_ERROR_CODES.AUTHENTICATION_REQUIRED:
        showMessage('Session expired. Please re-authenticate.');
        break;
      default:
        showMessage(event.error.message);
    }
  });

  client.on(SwEvent.Warning, (event) => {
    if (event.warning.code === TELNYX_WARNING_CODES.PEER_CONNECTION_FAILED) {
      showBanner('Call connectivity degraded.');
    }
    if (event.warning.code === TELNYX_WARNING_CODES.TOKEN_EXPIRING_SOON) {
      refreshToken();
    }
  });
  ```

### 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:**

  ```ts theme={null}
  import { isMediaRecoveryErrorEvent } from '@telnyx/webrtc';

  const client = new TelnyxRTC({
    login_token: '...',
    mediaPermissionsRecovery: {
      enabled: true,
      timeout: 20000,
      onSuccess: () => console.log('Media recovered, call proceeding'),
      onError: (err) => console.error('Recovery failed', err),
    },
  });

  client.on(SwEvent.Error, (event) => {
    if (isMediaRecoveryErrorEvent(event)) {
      // Show a prompt so the user can grant microphone access
      // User need to implement it on their side
      showPermissionDialog({
        deadline: event.retryDeadline,
        onAllow: () => event.resume(), // retries getUserMedia
        onDeny: () => event.reject(), // terminates the call
      });
    }
  });
  ```

* **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.

  ```ts theme={null}
  // Before (fire-and-forget)
  call.hangup();

  // After (await to ensure BYE is sent)
  await call.hangup();
  ```

### 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.0](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.25.29...webrtc/v2.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](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.25.28...webrtc/v2.25.29) (2026-03-31)

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

## [2.25.28](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.25.27...webrtc/v2.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](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.25.26...webrtc/v2.25.27) (2026-03-31)

* chore: remove NODE\_AUTH\_TOKEN from publish steps for OIDC auth (#570)

## [2.25.26](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.25.26-beta.4...webrtc/v2.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.25](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.25.24...webrtc/v2.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](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.25.23...webrtc/v2.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](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.25.22...webrtc/v2.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](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.25.21...webrtc/v2.25.22) (2026-02-26)

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

## [2.25.21](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.25.20...webrtc/v2.25.21) (2026-02-25)

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

## [2.25.20](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.25.19...webrtc/v2.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](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.25.15...webrtc/v2.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](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.25.17...webrtc/v2.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](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.25.16...webrtc/v2.25.17) (2026-02-02)

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

## [2.25.16](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.25.15...webrtc/v2.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](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.25.14...webrtc/v2.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](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.25.13...webrtc/v2.25.14) (2025-12-16)

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

## [2.25.12](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.25.11...webrtc/v2.25.12) (2025-12-15)

* feat: clear intervals setup on device sleep wake

## [2.25.11](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.25.10...webrtc/v2.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](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.25.9...webrtc/v2.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](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.25.8...webrtc/v2.25.9) (2025-12-02)

### Enhancements

* move `mutedMicOnStart` from call to client options

## [2.25.8](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.25.7...webrtc/v2.25.8) (2025-11-28)

### Features

* add `iceServers` to client options
* add `mutedMicOnStart` to call options

## [2.25.7](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.25.6...webrtc/v2.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](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.25.5...webrtc/v2.25.6) (2025-11-18)

### Fixes

* received authentication required counter cleanup

## [2.25.5](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.25.4...webrtc/v2.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](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.25.3...webrtc/v2.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](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.25.2...webrtc/v2.25.3) (2025-11-12)

* fix: called createWebRTCStatsReporter before use statsReporter

## [2.25.2](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.25.1...webrtc/v2.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](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.24.2...webrtc/v2.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](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.24.1...webrtc/v2.24.2) (2025-11-04)

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

## [2.24.1](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.24.0...webrtc/v2.24.1) (2025-10-30)

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

## [2.24.0](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.22.19...webrtc/v2.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](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.22.18...webrtc/v2.22.19) (2025-10-29)

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

## [2.22.18](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.22.17...webrtc/v2.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](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.22.16...webrtc/v2.22.17) (2025-08-04)

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

## [2.22.16](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.22.15...webrtc/v2.22.16) (2025-08-04)

feat: add support for image attachments (#436)

## [2.22.15](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.22.14...webrtc/v2.22.15) (2025-07-24)

feat: pass target\_version\_id for anonymous login (#434)

## [2.22.14](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.22.13...webrtc/v2.22.14) (2025-07-09)

feat: send messages to AI agents (#432)

## [2.22.13](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.22.12...webrtc/v2.22.13) (2025-07-04)

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

## [2.22.12](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.22.11...webrtc/v2.22.12) (2025-05-20)

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

## [2.22.11](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.22.10...webrtc/v2.22.11) (2025-05-14)

### Bug fixes

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

## [2.22.10](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.22.9...webrtc/v2.22.10) (2025-05-09)

### Bug fixes

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

## [2.22.9](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.22.8...webrtc/v2.22.9) (2025-04-14)

### Features

feat: anonymous login and ai\_agent calls (#420)

## [2.22.8](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.22.7...webrtc/v2.22.8) (2025-03-28)

### Features

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

## [2.22.7](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.22.6...webrtc/v2.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](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.22.5...webrtc/v2.22.6) (2025-02-20)

### Bug fixes

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

## [2.22.5](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.22.4...webrtc/v2.22.5) (2025-01-17)

### Bug Fixes

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

## [2.22.4](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.22.3...webrtc/v2.22.4) (2025-01-14)

### Bug fixes

Fix inconsistency in reporting `addConnection` debug event through the websocket

## [2.22.3](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.22.2...webrtc/v2.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](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.22.1...webrtc/v2.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](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.22.0...webrtc/v2.22.1) (2024-10-14)

### Bug Fixes

Improve stability for ICE gathering process. (See [#391](https://github.com/team-telnyx/webrtc/pull/391))

## [2.22.0](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.21.2...webrtc/v2.22.0) (2024-10-14)

### Features

* add reconnection flag to login message ([#380](https://github.com/team-telnyx/webrtc/issues/380)) ([643e252](https://github.com/team-telnyx/webrtc/commit/643e25240ec34a3262811e53fe46d907a2c32390))
* change reconnection logic ([#383](https://github.com/team-telnyx/webrtc/issues/383)) ([8ac1d8c](https://github.com/team-telnyx/webrtc/commit/8ac1d8ca14293dc09dc57e7c89b45ef4e6a6b5ff))
* publish generated docs to gh pages ([#385](https://github.com/team-telnyx/webrtc/issues/385)) ([d3a3d37](https://github.com/team-telnyx/webrtc/commit/d3a3d37d59678a4ad292b72c19fe8954ea91b16b))
* set client\_state from bye message ([#382](https://github.com/team-telnyx/webrtc/issues/382)) ([b2c4611](https://github.com/team-telnyx/webrtc/commit/b2c461124ccc70cf5604d40a6d2708c6014c4f83))

### [2.21.2](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.21.1...webrtc/v2.21.2) (2024-09-05)

### Bug Fixes

* keep socket open for longer ([#379](https://github.com/team-telnyx/webrtc/issues/379)) ([89b92ec](https://github.com/team-telnyx/webrtc/commit/89b92ec7b6a92647da5f35a710d33206a170bacb))
* use npm publish ([#376](https://github.com/team-telnyx/webrtc/issues/376)) ([ca965c4](https://github.com/team-telnyx/webrtc/commit/ca965c4d6c998977f637b9d47edf549d56492308))

### [2.21.1](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.21.0...webrtc/v2.21.1) (2024-08-22)

### Bug Fixes

* add .yarn/install\_state.gz to .gitignore ([#369](https://github.com/team-telnyx/webrtc/issues/369)) ([7b2b7a4](https://github.com/team-telnyx/webrtc/commit/7b2b7a41a5ed6a1ea992732549fff25fdab093ac))
* query param is appended multiple times ([#368](https://github.com/team-telnyx/webrtc/issues/368)) ([14c2711](https://github.com/team-telnyx/webrtc/commit/14c2711549e6738e4f09a6489e76d5bc4c84b442))
* upgrade ci to use yarn v2 ([#370](https://github.com/team-telnyx/webrtc/issues/370)) ([cc46e49](https://github.com/team-telnyx/webrtc/commit/cc46e491b057c67d1a884e3678098ab0515bb09a))

## [2.21.0](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.20.0...webrtc/v2.21.0) (2024-08-14)

### Features

* attach reconnection token to host ([#367](https://github.com/team-telnyx/webrtc/issues/367)) ([27be846](https://github.com/team-telnyx/webrtc/commit/27be8463f59a00d8e3369c2826efc3d3d8236b70))

## [2.20.0](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.19.0...webrtc/v2.20.0) (2024-08-01)

### Features

* get registration state from the gateway ([#366](https://github.com/team-telnyx/webrtc/issues/366)) ([c5af08b](https://github.com/team-telnyx/webrtc/commit/c5af08bcd45f53ea1dba3861a0a53229cf2dbc54))

## [2.19.0](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.18.0...webrtc/v2.19.0) (2024-06-20)

### Features

* log ice events ([#363](https://github.com/team-telnyx/webrtc/issues/363)) ([f591bcb](https://github.com/team-telnyx/webrtc/commit/f591bcb360c395863155936b5686a1d0ca6d28df))

### Bug Fixes

* add debug typespec ([#362](https://github.com/team-telnyx/webrtc/issues/362)) ([479e745](https://github.com/team-telnyx/webrtc/commit/479e7459ca006ad6395c249794562e9b074fbfa5))

## [2.18.0](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.17.0...webrtc/v2.18.0) (2024-06-10)

### Features

* support caller codec preference ([#361](https://github.com/team-telnyx/webrtc/issues/361)) ([cac97ac](https://github.com/team-telnyx/webrtc/commit/cac97acf042d7820dd41e501b6b8281e0a67e80d))

## [2.17.0](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.16.0...webrtc/v2.17.0) (2024-05-28)

### Features

* propagate session id with error event ([#358](https://github.com/team-telnyx/webrtc/issues/358)) ([0f931ed](https://github.com/team-telnyx/webrtc/commit/0f931ede12f637b7ec6db265162deb73dd2f2ff1))

## [2.16.0](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.15.0...webrtc/v2.16.0) (2024-05-14)

### Features

* chunk debug log ([#356](https://github.com/team-telnyx/webrtc/issues/356)) ([70b6e5e](https://github.com/team-telnyx/webrtc/commit/70b6e5ed1bd5e04443885497dccd2288284092d4))

## [2.15.0](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.14.0...webrtc/v2.15.0) (2024-04-30)

### Features

* add custom headers on bye ([#353](https://github.com/team-telnyx/webrtc/issues/353)) ([a17781c](https://github.com/team-telnyx/webrtc/commit/a17781c0df72256aab38f386fa90eb521f4aa246))

## [2.14.0](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.13.0...webrtc/v2.14.0) (2024-04-26)

### Features

* implement debug output for file and websocket ([#352](https://github.com/team-telnyx/webrtc/issues/352)) ([8d1f8e6](https://github.com/team-telnyx/webrtc/commit/8d1f8e6c6a0874d9a4a4be21c101f81678084afb))

## [2.13.0](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.12.0...webrtc/v2.13.0) (2024-04-22)

### Features

* add probe to fetch webrtc statistics periodically ([#350](https://github.com/team-telnyx/webrtc/issues/350)) ([2a72b60](https://github.com/team-telnyx/webrtc/commit/2a72b60843599dd824ee40ef79bdce2d8ba1ce52))

## [2.12.0](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.11.0...webrtc/v2.12.0) (2024-04-05)

### Features

* add a faster work-around for ice gathering never completing ([#349](https://github.com/team-telnyx/webrtc/issues/349)) ([47e1863](https://github.com/team-telnyx/webrtc/commit/47e18633b142263d49ca061f8b0c29fd5d5edf2a))

## [2.11.0](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.10.2...webrtc/v2.11.0) (2024-02-26)

### Features

* **TELAPPS-4794:** expose user agent on login ([#343](https://github.com/team-telnyx/webrtc/issues/343)) ([a8b9606](https://github.com/team-telnyx/webrtc/commit/a8b96068255c4cec50d43d737a85fea267f3b52a))

### Bug Fixes

* **ENGDESK-23349:** bind telnyxids on ringing event for outbound calls ([#342](https://github.com/team-telnyx/webrtc/issues/342)) ([1b1df78](https://github.com/team-telnyx/webrtc/commit/1b1df782c3c4034d412be079b92019e661dbd5ce))
* **ENGDESK-28811:** call object direction is undefined upon receiving call ([#341](https://github.com/team-telnyx/webrtc/issues/341)) ([8ac5a3f](https://github.com/team-telnyx/webrtc/commit/8ac5a3f6626d67cde4cf14c541aa26085be19ae6))

### [2.10.2](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.10.1...webrtc/v2.10.2) (2024-02-20)

### Bug Fixes

* **ENGDESK-26922:** Make `login_token` optional ([#340](https://github.com/team-telnyx/webrtc/issues/340)) ([1c0b36a](https://github.com/team-telnyx/webrtc/commit/1c0b36a8daec1d2552da7dde7842763c1aa477ca))

### [2.10.1](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.10.0...webrtc/v2.10.1) (2023-11-23)

### Bug Fixes

* the params.customHeaders was not being destructuring correctly the values ([#339](https://github.com/team-telnyx/webrtc/issues/339)) ([b7e1c2a](https://github.com/team-telnyx/webrtc/commit/b7e1c2a4dcc974b36f32c59a54a6380a8cbd4d07))

## [2.10.0](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.9.0...webrtc/v2.10.0) (2023-11-22)

### Features

* **ENGDESK-26634:** add custom headers to invite and answer messages ([#338](https://github.com/team-telnyx/webrtc/issues/338)) ([69814b4](https://github.com/team-telnyx/webrtc/commit/69814b4f4123b7dba777813836551ac771e54892))
* **ENGDESK-27107:** Upgrade WebRTC library to support React 18 ([#321](https://github.com/team-telnyx/webrtc/issues/321)) ([66d0c0e](https://github.com/team-telnyx/webrtc/commit/66d0c0ee8bcd458b20e7fe67c0561663c3190417))

## [2.9.0](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.8.2...webrtc/v2.9.0) (2023-01-31)

### Features

* **ENGDESK-21003:** add beforeunload event to hang up active calls when the browser is closed or refreshed ([#304](https://github.com/team-telnyx/webrtc/issues/304)) ([5f4a899](https://github.com/team-telnyx/webrtc/commit/5f4a8992e128c9ca9b7c7d5b84412daae2636dcc))

### [2.8.2](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.8.1...webrtc/v2.8.2) (2022-09-28)

### Bug Fixes

* **ENGDESK-19054:** Voice SDK missing types when installed in TypeScript projects. ([#299](https://github.com/team-telnyx/webrtc/issues/299)) ([ae76c98](https://github.com/team-telnyx/webrtc/commit/ae76c984d57c423d8bcac935be680670cfa8614e))

### [2.8.1](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.8.0...webrtc/v2.8.1) (2022-07-07)

## [2.8.0](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.7.6...webrtc/v2.8.0) (2022-05-25)

### Features

* **WEBRTC-1798:** add ping request to the server to keep connected ([#287](https://github.com/team-telnyx/webrtc/issues/287)) ([95ce187](https://github.com/team-telnyx/webrtc/commit/95ce187758112edba9f66a4e904c56f9a749dee7))

### [2.7.6](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.7.5...webrtc/v2.7.6) (2022-04-26)

### [2.7.5](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.7.4...webrtc/v2.7.5) (2022-04-26)

### [2.7.4](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.7.3...webrtc/v2.7.4) (2022-04-25)

### Bug Fixes

* change timeout value of 500 to use a random number between 3000 ([#246](https://github.com/team-telnyx/webrtc/issues/246)) ([34a232a](https://github.com/team-telnyx/webrtc/commit/34a232a768683aa8e60c395b658ce9ac44db47a6))
* **WEBRTC-1705:** reverting dependabot updates to fix typedoc generation ([#278](https://github.com/team-telnyx/webrtc/issues/278)) ([5ac667d](https://github.com/team-telnyx/webrtc/commit/5ac667d8d01df418dcbbc814968628121631e4e7))

### [2.7.3](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.7.2...webrtc/v2.7.3) (2021-12-14)

### Bug Fixes

* change previousGatewayState only if gateWayState exist to avoid send many REGISTER messages ([#244](https://github.com/team-telnyx/webrtc/issues/244)) ([70c10fa](https://github.com/team-telnyx/webrtc/commit/70c10faae274e08e019fdf2187af839dd0ad744c))

### [2.7.2](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.7.1...webrtc/v2.7.2) (2021-12-13)

### Bug Fixes

* **ENGDESK-12851:** add code to avoid multiples REGED messages on the client side ([#235](https://github.com/team-telnyx/webrtc/issues/235)) ([86b3a0e](https://github.com/team-telnyx/webrtc/commit/86b3a0e98cd7b6f60bc00beb1fb21773cdcb2401))

### [2.7.1](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.7.0...webrtc/v2.7.1) (2021-12-09)

### Bug Fixes

* add stop stream after query it ([#233](https://github.com/team-telnyx/webrtc/issues/233)) ([0e4fba9](https://github.com/team-telnyx/webrtc/commit/0e4fba97cfd98fd464f2076d1c32f7366366e9f2))

## [2.7.0](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.6.2...webrtc/v2.7.0) (2021-12-08)

### Features

* **WEBRTC-558:** add slack notification ([#219](https://github.com/team-telnyx/webrtc/issues/219)) ([3925a82](https://github.com/team-telnyx/webrtc/commit/3925a822d5c42658a23a7e9fd1df8ff563a723a1))

### Bug Fixes

* **Hotfix:** package.lock update and node upgrade to 14 ([#228](https://github.com/team-telnyx/webrtc/issues/228)) ([29b7c27](https://github.com/team-telnyx/webrtc/commit/29b7c2789dfac30083a0cb62ae4677e943cb5767))
* **WEBRTC-746:** recursive call to getDevices when the browser does not support audiooutput like Safari and Firefox. ([#223](https://github.com/team-telnyx/webrtc/issues/223)) ([bbc2231](https://github.com/team-telnyx/webrtc/commit/bbc2231cc1a62a1bff62bbcb974c7f0231fef06e))

### [2.2.7](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.2.7...webrtc/v2.2.7) (2021-01-08)

### [2.2.6](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.2.6...webrtc/v2.2.6) (2021-01-08)

### [2.2.5](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.2.5...webrtc/v2.2.5) (2021-01-06)

### [2.2.4](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.2.4...webrtc/v2.2.4) (2020-12-11)

### [2.2.3](https://github.com/team-telnyx/webrtc/compare/webrtc/v2.2.2...webrtc/v2.2.3) (2020-12-04)

### Changed

* Updates to `docs`

## [2.2.2](https://github.com/team-telnyx/webrtc/compare/v2.2.1-50-g0d4d2364801153f2d24afdee90fc15c856b000df...webrtc/v2.2.2) (2020-11-19)

### Bug Fixes

* **ENGDESK-7173:** change the STUN\_SERVER port from 3843 to 3478 ([#60](https://github.com/team-telnyx/webrtc/issues/60)) ([cc8f78f](https://github.com/team-telnyx/webrtc/commit/cc8f78f1454039efb55b921c0de54df5c1326e8f))

## 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
