For AI agents: a documentation index is available at the root level at /llms.txt and /llms-full.txt. Append /llms.txt to any URL for a page-level index, or .md for the markdown version of any page.
Log inSign up
Support
GuidesReferenceClick-to-Call
GuidesReferenceClick-to-Call
  • Getting Started
    • Overview
    • Authentication
    • RxJS Primer
    • Migrate from v3
  • Web Components
    • Overview
    • Click-to-Call
    • Theming
    • Customization
  • Build Voice & Video Apps
    • Overview
    • Outbound Calls
    • Inbound Calls
    • Device Management
    • Screen Sharing
    • Call Controls
    • Layouts
    • Messaging & Chat
  • Manage Resources
    • Overview
    • Users
    • Address Book
    • Client Preferences
    • Capabilities
  • Deploy
    • Overview
    • Framework Integration
    • SSR & Next.js
    • Troubleshooting
LogoLogoSignalWire Docs
Log inSign up
Support
On this page
  • Defaults vs. per-call overrides
  • Persistence
  • userVariables
  • Time units
  • Reference
Manage Resources

Client Preferences

|View as Markdown|Open in Claude|
Was this page helpful?
Edit this page
Previous

Capabilities

Next
Built with

client.preferences holds per-client defaults the SDK reads when no per-call options override them: which mic / camera to use, whether to receive video by default, ICE / recovery tuning, codec ordering, and custom userVariables attached to every call. Preferences live in the browser, optionally persist to localStorage, and are distinct from per-User configuration (which lives on the platform — see Users).

This page covers how preferences fit into the SDK lifecycle. For the full property list, see ClientPreferences.

Defaults vs. per-call overrides

client.preferences ← defaults
↓
client.dial(dest, options) ← per-call overrides win

Anything set on preferences applies to every subsequent dial() that doesn’t pass a competing field. Per-call options always win:

1client.preferences.receiveVideo = false; // audio-first default
2
3// This one call gets video regardless:
4await client.dial("/private/team", { video: true });

Use preferences for app-wide defaults (codec ordering, a tier-wide userVariables payload). Use per-call options for situational values.

Persistence

By default, preferences live in memory only. Set savePreferences: true to hydrate from localStorage on startup and write back on every setter:

1const client = new SignalWire(provider, { savePreferences: true });

Persisted: timeouts, ICE settings, codec preferences, device-management flags, and userVariables — anything cleanly JSON-serializable.

Not persisted: MediaDeviceInfo references. Device IDs aren’t stable across sessions in every browser, so device picks happen at runtime via the device controller.

For a different storage backend (IndexedDB, server-side per user), leave savePreferences off and mirror manually:

1function setReceiveVideo(value: boolean) {
2 client.preferences.receiveVideo = value;
3 myStore.set("receiveVideo", value);
4}

ClientPreferences is a synchronous object — there is no update$ observable. Preferences are read at dial time.

userVariables

userVariables is a free-form payload attached to every outbound Verto invite. The receiving side (an AI agent, a SWML script, a backend) reads it via signalwire-address:event events.

1client.preferences.userVariables = {
2 plan: user.plan,
3 locale: navigator.language,
4};

Set on preferences for app-wide values; pass to dial() for per-call attribution.

Time units

Timeouts on the preferences surface are exposed in seconds (stored as milliseconds internally):

1client.preferences.connectionTimeout = 30; // 30 seconds
2client.preferences.iceRestartTimeout = 10; // 10 seconds

Other fields use the unit of the underlying API (kbps, integer levels, etc.).

Reference

  • ClientPreferences — the property surface
  • SignalWire.preferences — the instance
  • SignalWireOptions — savePreferences, skipDeviceMonitoring, reconnectAttachedCalls, persistSession
  • SignalWire.dial() — per-call overrides