From 9e5ffb3adc78fd6b1415f5a11c34bed461d0a185 Mon Sep 17 00:00:00 2001 From: nirav Date: Wed, 15 Oct 2025 13:37:41 +0545 Subject: [PATCH 01/12] init --- website/config/navbar.ts | 8 +- website/config/pluginsConfig/index.ts | 2 +- .../docs/signalwire-sdk/about_call_fabric.mdx | 124 +++++- .../Address/address-get-address.mdx | 152 +++++++ .../Address/address-get-addresses.mdx | 153 +++++++ .../Address/address-get-my-addresses.mdx | 179 ++++++++ .../Chat/chat-get-messages.mdx | 176 ++++++++ .../SignalWireClient/Chat/chat-join.mdx | 168 ++++++++ .../Chat/chat-send-message.mdx | 212 ++++++++++ .../SignalWireClient/Chat/chat-subscribe.mdx | 220 ++++++++++ ...conversation-get-conversation-messages.mdx | 188 +++++++++ .../conversation-get-conversations.mdx | 206 +++++++++ .../conversation-get-messages.mdx | 206 +++++++++ .../Conversation/conversation-join.mdx | 171 ++++++++ .../conversation-send-message.mdx | 260 ++++++++++++ .../Conversation/conversation-subscribe.mdx | 238 +++++++++++ .../tech-ref/SignalWireClient/dial.mdx | 143 ++++++- .../tech-ref/SignalWireClient/disconnect.mdx | 153 +++++++ .../tech-ref/SignalWireClient/events.mdx | 397 +++++++++++++++++- .../SignalWireClient/get-subscriber-info.mdx | 187 +++++++++ .../handle-push-notification.mdx | 207 +++++++++ .../tech-ref/SignalWireClient/index.mdx | 126 +++++- .../tech-ref/SignalWireClient/offline.mdx | 202 +++++++++ .../tech-ref/SignalWireClient/online.mdx | 202 +++++++++ .../tech-ref/SignalWireClient/reattach.mdx | 226 ++++++++++ .../SignalWireClient/register-device.mdx | 180 ++++++++ .../SignalWireClient/unregister-device.mdx | 181 ++++++++ .../SignalWireClient/update-token.mdx | 247 +++++++++++ .../tech-ref/authentication.mdx | 179 +++++--- .../docs/signalwire-sdk/tech-ref/index.mdx | 2 + website/src/components/APIField/index.tsx | 142 +++++++ .../src/components/APIField/styles.module.css | 152 +++++++ website/src/components/Extras/Card/Card.tsx | 8 +- website/typesense.json | 1 + 34 files changed, 5507 insertions(+), 91 deletions(-) create mode 100644 website/docs/signalwire-sdk/tech-ref/SignalWireClient/Address/address-get-address.mdx create mode 100644 website/docs/signalwire-sdk/tech-ref/SignalWireClient/Address/address-get-addresses.mdx create mode 100644 website/docs/signalwire-sdk/tech-ref/SignalWireClient/Address/address-get-my-addresses.mdx create mode 100644 website/docs/signalwire-sdk/tech-ref/SignalWireClient/Chat/chat-get-messages.mdx create mode 100644 website/docs/signalwire-sdk/tech-ref/SignalWireClient/Chat/chat-join.mdx create mode 100644 website/docs/signalwire-sdk/tech-ref/SignalWireClient/Chat/chat-send-message.mdx create mode 100644 website/docs/signalwire-sdk/tech-ref/SignalWireClient/Chat/chat-subscribe.mdx create mode 100644 website/docs/signalwire-sdk/tech-ref/SignalWireClient/Conversation/conversation-get-conversation-messages.mdx create mode 100644 website/docs/signalwire-sdk/tech-ref/SignalWireClient/Conversation/conversation-get-conversations.mdx create mode 100644 website/docs/signalwire-sdk/tech-ref/SignalWireClient/Conversation/conversation-get-messages.mdx create mode 100644 website/docs/signalwire-sdk/tech-ref/SignalWireClient/Conversation/conversation-join.mdx create mode 100644 website/docs/signalwire-sdk/tech-ref/SignalWireClient/Conversation/conversation-send-message.mdx create mode 100644 website/docs/signalwire-sdk/tech-ref/SignalWireClient/Conversation/conversation-subscribe.mdx create mode 100644 website/docs/signalwire-sdk/tech-ref/SignalWireClient/disconnect.mdx create mode 100644 website/docs/signalwire-sdk/tech-ref/SignalWireClient/get-subscriber-info.mdx create mode 100644 website/docs/signalwire-sdk/tech-ref/SignalWireClient/handle-push-notification.mdx create mode 100644 website/docs/signalwire-sdk/tech-ref/SignalWireClient/offline.mdx create mode 100644 website/docs/signalwire-sdk/tech-ref/SignalWireClient/online.mdx create mode 100644 website/docs/signalwire-sdk/tech-ref/SignalWireClient/reattach.mdx create mode 100644 website/docs/signalwire-sdk/tech-ref/SignalWireClient/register-device.mdx create mode 100644 website/docs/signalwire-sdk/tech-ref/SignalWireClient/unregister-device.mdx create mode 100644 website/docs/signalwire-sdk/tech-ref/SignalWireClient/update-token.mdx create mode 100644 website/src/components/APIField/index.tsx create mode 100644 website/src/components/APIField/styles.module.css diff --git a/website/config/navbar.ts b/website/config/navbar.ts index 21144e2b5..5f76543aa 100644 --- a/website/config/navbar.ts +++ b/website/config/navbar.ts @@ -99,10 +99,10 @@ const navbar: NavbarItem[] = [ label: "RELAY Browser SDK", to: "/sdks/browser-sdk/", }, - // { - // label: "SignalWire SDK", - // to: "/sdks/signalwire-sdk/", - // }, + { + label: "SignalWire SDK", + to: "/sdks/signalwire-sdk/", + }, { label: "RELAY Realtime Server SDK", to: "/sdks/realtime-sdk/", diff --git a/website/config/pluginsConfig/index.ts b/website/config/pluginsConfig/index.ts index 2dff86d8f..bee64d462 100644 --- a/website/config/pluginsConfig/index.ts +++ b/website/config/pluginsConfig/index.ts @@ -33,7 +33,7 @@ const plugins: PluginConfig[] = [ llmsTxtPlugin, realtimeSdkPlugin, browserSdkPlugin, - // signalwireSdkPlugin, + signalwireSdkPlugin, ogImagesPlugin, ]; diff --git a/website/docs/signalwire-sdk/about_call_fabric.mdx b/website/docs/signalwire-sdk/about_call_fabric.mdx index eb02f961d..31476dbc5 100644 --- a/website/docs/signalwire-sdk/about_call_fabric.mdx +++ b/website/docs/signalwire-sdk/about_call_fabric.mdx @@ -1,25 +1,109 @@ -# The Call Fabric architecture +# Call Fabric in the SignalWire SDK -SignalWire's Call Fabric represents a transformative evolution from traditional CPaaS, UCaaS, and CCaaS models, marking a significant shift towards more adaptable and integrated communication solutions. +Call Fabric is a great new way to build communication applications, be it a simple +chat app on your website, or a complex multi-channel multi-modal call center, or a complex set of AI agents to +manage customer interactions. + +To support this new paradigm, SignalWire has created a new SDK called the [SignalWire SDK](./index.mdx). +This new SDK is designed to run on the user's browser and allow for communication to all resources via the assigned addresses. +This new SDK replaces the older [SignalWire Browser SDK](./sdks/browser-sdk/). + +:::info Looking for more details? + +The [What is Call Fabric?](/platform/call-fabric) page has more details about the Call Fabric architecture. + +::: ## Resources -Resources are the primary entities for communication within the Call Fabric ecosystem. They are the building blocks of the system, representing the various communication tools that can be used to interact with Subscribers. For example, all of the following are Resources: - -- Subscribers -- SWML Scripts -- Compatibility XML Webhooks/Applications -- Relay apps -- SignalWire AI Agents -- Video Conferences: - Subscribers - SWML Scripts - Compatibility XML Webhooks/Applications - Relay apps - SignalWire AI Agents - Video Conferences: - Programmable API Video Conferences - Pre-built Video Conferences - SIP Endpoints - FreeSWITCH Connectors +Resources are the primary entities for communication within the Call Fabric ecosystem. You can create resources +either through the dashboard or through the REST API. + +import { TbApi } from "react-icons/tb"; +import { TbUser } from "react-icons/tb"; + + + } + href="/platform/call-fabric/resources" + /> + + } + href="/rest/signalwire-rest/endpoints/fabric/resources" + > + Each resource will have its own set of endpoints to manipulate it. + + + +To list a few important ones: + +- [AI Agents](/platform/call-fabric/resources/ai-agents) +- [Subscribers](/platform/call-fabric/subscribers) +- [SWML Scripts](/platform/call-fabric/resources/swml-scripts) +- [cXML Scripts](/platform/call-fabric/resources/cxml-scripts) +- [Video Conference Rooms](/platform/call-fabric/resources/video-rooms) +- [SIP Gateways](/platform/call-fabric/resources/sip-gateways) + +These resources are accessible via their [Addresses](/platform/call-fabric/addresses). You can more than one address +per resource. They can be: + +- Phone numbers you own +- SIP addresses +- Aliases (like `/private/support-queue` or `/public/chat-agent`) + +To call a resource using the SDK, you can use the `client.dial()` method. + +```javascript +const client = new SignalWireClient({ + project: 'YOUR_PROJECT_ID', + token: 'YOUR_TOKEN', +}); + +const callSession = await client.dial({ + to: '/private/support-queue', + rootElement: document.getElementById('call-container'), +}); +``` + +### Subscribers + +Subscribers are a special type of Resource that represent internal account-holders. +They can receive or initiate calls, messages, and other forms of interaction. + +The SignalWire Client SDK can only be used by a subscriber with a subscriber token. +For more details, see the [Authentication](./tech-ref/authentication) section. + +- each user of your communication application can be a subscriber, to manage billing and management, and allow OAuth2 sign-in +- your scripts or backend systems can be subscribers, to allow for programmatic access to the resources via a token +- a single subscriber can be an entry point to allow access to AI agents or connecting calls. + +Subscribers can be created through the dashboard or through the REST API. + + + } + href="/platform/call-fabric/resources/subscribers" + / > + + } + href="/rest/signalwire-rest/endpoints/fabric/subscribers-create" + /> + + } + href="/rest/signalwire-rest/endpoints/fabric/subscriber-tokens-create" + /> + + +:::info Looking for more details? + +The [Subscribers](/platform/call-fabric/subscribers) page has more details about the Subscribers resource. +::: \ No newline at end of file diff --git a/website/docs/signalwire-sdk/tech-ref/SignalWireClient/Address/address-get-address.mdx b/website/docs/signalwire-sdk/tech-ref/SignalWireClient/Address/address-get-address.mdx new file mode 100644 index 000000000..ac5b678f7 --- /dev/null +++ b/website/docs/signalwire-sdk/tech-ref/SignalWireClient/Address/address-get-address.mdx @@ -0,0 +1,152 @@ +--- +title: address.getAddress +slug: /signalwire-client/address-get-address +--- + +import APIField from '@site/src/components/APIField'; + +Retrieves detailed information about a specific address by its ID. + +## How it works + +The `address.getAddress` method queries the SignalWire platform for details about a single address. This provides comprehensive information about a specific phone number or endpoint. + +## Key concepts + +### Address details + +The response includes: +- Address ID +- Phone number or SIP address +- Address type +- Display name +- Capabilities +- Configuration settings + +### Use cases + +Retrieve specific address details for: +- Displaying address information +- Validating address capabilities +- Configuration management +- Call routing decisions + +## Parameters + + + The unique identifier of the address to retrieve. + + +## Signature + +```typescript +address.getAddress(addressId: string): Promise +``` + +## Returns + +**Type:** `Promise` + +Returns a Promise that resolves with detailed information about the requested address. + +## Examples + +### Get address by ID + +```typescript +const address = await client.address.getAddress('address-id-here') + +console.log('Address:', address.number) +console.log('Type:', address.type) +``` + +### Display address details + +```typescript +const address = await client.address.getAddress('address-id-here') + +console.log('Address Details:') +console.log(' Number:', address.number) +console.log(' Name:', address.name) +console.log(' Type:', address.type) +console.log(' Capabilities:', address.capabilities) +``` + +### Validate address capabilities + +```typescript +const address = await client.address.getAddress('address-id-here') + +if (address.capabilities.canReceiveCalls) { + console.log('This address can receive incoming calls') +} + +if (address.capabilities.canSendSMS) { + console.log('This address can send SMS messages') +} +``` + +### Error handling + +```typescript +try { + const address = await client.address.getAddress('address-id') + console.log('Address found:', address.number) +} catch (error) { + console.error('Address not found:', error) +} +``` + +### Get address from selection + +```typescript +const selectedId = document.getElementById('address-select').value + +if (selectedId) { + const address = await client.address.getAddress(selectedId) + + document.getElementById('address-display').textContent = address.number + document.getElementById('address-type').textContent = address.type +} +``` + +### Check if address exists + +```typescript +async function addressExists(addressId) { + try { + await client.address.getAddress(addressId) + return true + } catch (error) { + return false + } +} + +const exists = await addressExists('address-id') +console.log('Address exists:', exists) +``` + +### Compare addresses + +```typescript +const address1 = await client.address.getAddress('address-1-id') +const address2 = await client.address.getAddress('address-2-id') + +console.log('Comparing addresses:') +console.log(`Address 1: ${address1.number} (${address1.type})`) +console.log(`Address 2: ${address2.number} (${address2.type})`) +``` + +### Use address for calling + +```typescript +const address = await client.address.getAddress('my-address-id') + +const callSession = await client.dial({ + to: '+15551234567', + from: address.number +}) + +console.log('Calling from:', address.number) +``` + diff --git a/website/docs/signalwire-sdk/tech-ref/SignalWireClient/Address/address-get-addresses.mdx b/website/docs/signalwire-sdk/tech-ref/SignalWireClient/Address/address-get-addresses.mdx new file mode 100644 index 000000000..9a651b7d6 --- /dev/null +++ b/website/docs/signalwire-sdk/tech-ref/SignalWireClient/Address/address-get-addresses.mdx @@ -0,0 +1,153 @@ +--- +title: address.getAddresses +slug: /signalwire-client/address-get-addresses +--- + +import APIField from '@site/src/components/APIField'; + +Retrieves a list of all available addresses in your SignalWire space. + +## How it works + +The `address.getAddresses` method queries the SignalWire platform for all addresses configured in your space. Addresses represent phone numbers, SIP endpoints, or other communication identifiers. + +## Key concepts + +### Address types + +Addresses can include: +- Phone numbers (PSTN) +- SIP addresses +- WebRTC endpoints +- Resource names + +### Use cases + +Common uses: +- Displaying available phone numbers +- Selecting caller ID for outbound calls +- Managing address inventory +- Routing configuration + +## Parameters + +None + +## Signature + +```typescript +address.getAddresses(): Promise +``` + +## Returns + +**Type:** `Promise` + +Returns a Promise that resolves with a list of all available addresses. + +## Examples + +### Get all addresses + +```typescript +const result = await client.address.getAddresses() + +console.log('Available addresses:', result.addresses) +``` + +### Display addresses in UI + +```typescript +const result = await client.address.getAddresses() + +const select = document.getElementById('caller-id-select') + +result.addresses.forEach(address => { + const option = document.createElement('option') + option.value = address.id + option.textContent = address.number + select.appendChild(option) +}) +``` + +### Filter phone numbers + +```typescript +const result = await client.address.getAddresses() + +const phoneNumbers = result.addresses.filter( + addr => addr.type === 'phone_number' +) + +console.log('Phone numbers:', phoneNumbers) +``` + +### List addresses with details + +```typescript +const result = await client.address.getAddresses() + +result.addresses.forEach(address => { + console.log(`ID: ${address.id}`) + console.log(`Number: ${address.number}`) + console.log(`Type: ${address.type}`) + console.log(`Name: ${address.name}`) + console.log('---') +}) +``` + +### Error handling + +```typescript +try { + const result = await client.address.getAddresses() + console.log('Retrieved addresses:', result.addresses.length) +} catch (error) { + console.error('Failed to get addresses:', error) +} +``` + +### Cache addresses + +```typescript +let cachedAddresses = null + +async function getAddressesCached() { + if (!cachedAddresses) { + const result = await client.address.getAddresses() + cachedAddresses = result.addresses + } + return cachedAddresses +} + +const addresses = await getAddressesCached() +``` + +### Select default address + +```typescript +const result = await client.address.getAddresses() + +const defaultAddress = result.addresses.find( + addr => addr.isDefault +) || result.addresses[0] + +console.log('Default address:', defaultAddress.number) +``` + +### Group addresses by type + +```typescript +const result = await client.address.getAddresses() + +const grouped = result.addresses.reduce((acc, addr) => { + if (!acc[addr.type]) { + acc[addr.type] = [] + } + acc[addr.type].push(addr) + return acc +}, {}) + +console.log('Addresses by type:', grouped) +``` + diff --git a/website/docs/signalwire-sdk/tech-ref/SignalWireClient/Address/address-get-my-addresses.mdx b/website/docs/signalwire-sdk/tech-ref/SignalWireClient/Address/address-get-my-addresses.mdx new file mode 100644 index 000000000..f819f7feb --- /dev/null +++ b/website/docs/signalwire-sdk/tech-ref/SignalWireClient/Address/address-get-my-addresses.mdx @@ -0,0 +1,179 @@ +--- +title: address.getMyAddresses +slug: /signalwire-client/address-get-my-addresses +--- + +import APIField from '@site/src/components/APIField'; + +Retrieves addresses associated with the current subscriber. This returns only the addresses that the authenticated user has access to. + +## How it works + +The `address.getMyAddresses` method queries the SignalWire platform for addresses specifically assigned to or accessible by the current subscriber. This is different from `getAddresses()` which returns all addresses in the space. + +## Key concepts + +### Subscriber-specific addresses + +The response includes only addresses that: +- Are assigned to the current subscriber +- The subscriber has permissions to use +- Are configured for the subscriber's role + +### Use cases + +Retrieve subscriber addresses for: +- Displaying user-specific caller IDs +- Personal phone number selection +- User address management +- Permission-aware UI + +## Parameters + +None + +## Signature + +```typescript +address.getMyAddresses(): Promise +``` + +## Returns + +**Type:** `Promise` + +Returns a Promise that resolves with a list of addresses available to the current subscriber. + +## Examples + +### Get my addresses + +```typescript +const result = await client.address.getMyAddresses() + +console.log('My addresses:', result.addresses) +``` + +### Display user's phone numbers + +```typescript +const result = await client.address.getMyAddresses() + +const select = document.getElementById('my-numbers-select') + +result.addresses.forEach(address => { + const option = document.createElement('option') + option.value = address.number + option.textContent = `${address.name} (${address.number})` + select.appendChild(option) +}) +``` + +### Get primary address + +```typescript +const result = await client.address.getMyAddresses() + +const primaryAddress = result.addresses.find( + addr => addr.isPrimary +) || result.addresses[0] + +console.log('Primary address:', primaryAddress.number) +``` + +### List my addresses with details + +```typescript +const result = await client.address.getMyAddresses() + +console.log('Your available addresses:') +result.addresses.forEach((address, index) => { + console.log(`${index + 1}. ${address.number}`) + console.log(` Name: ${address.name}`) + console.log(` Type: ${address.type}`) +}) +``` + +### Error handling + +```typescript +try { + const result = await client.address.getMyAddresses() + console.log(`You have ${result.addresses.length} addresses`) +} catch (error) { + console.error('Failed to get your addresses:', error) +} +``` + +### Check if user has addresses + +```typescript +const result = await client.address.getMyAddresses() + +if (result.addresses.length === 0) { + console.log('You do not have any addresses configured') +} else { + console.log(`You have ${result.addresses.length} address(es)`) +} +``` + +### Filter my phone numbers + +```typescript +const result = await client.address.getMyAddresses() + +const phoneNumbers = result.addresses.filter( + addr => addr.type === 'phone_number' +) + +console.log('My phone numbers:', phoneNumbers.map(a => a.number)) +``` + +### Use my address for outbound call + +```typescript +const result = await client.address.getMyAddresses() + +if (result.addresses.length > 0) { + const myNumber = result.addresses[0].number + + const callSession = await client.dial({ + to: '+15551234567', + from: myNumber + }) + + console.log('Calling from my number:', myNumber) +} else { + console.error('No addresses available') +} +``` + +### Compare my addresses with all addresses + +```typescript +const myAddresses = await client.address.getMyAddresses() +const allAddresses = await client.address.getAddresses() + +console.log(`I have access to ${myAddresses.addresses.length} addresses`) +console.log(`Total addresses in space: ${allAddresses.addresses.length}`) +``` + +### Select preferred address + +```typescript +async function selectPreferredAddress() { + const result = await client.address.getMyAddresses() + + const preferred = localStorage.getItem('preferredAddress') + + const address = result.addresses.find( + addr => addr.id === preferred + ) || result.addresses[0] + + return address +} + +const address = await selectPreferredAddress() +console.log('Using address:', address.number) +``` + diff --git a/website/docs/signalwire-sdk/tech-ref/SignalWireClient/Chat/chat-get-messages.mdx b/website/docs/signalwire-sdk/tech-ref/SignalWireClient/Chat/chat-get-messages.mdx new file mode 100644 index 000000000..b26c63f1f --- /dev/null +++ b/website/docs/signalwire-sdk/tech-ref/SignalWireClient/Chat/chat-get-messages.mdx @@ -0,0 +1,176 @@ +--- +title: chat.getMessages +slug: /signalwire-client/chat-get-messages +--- + +import APIField from '@site/src/components/APIField'; + +Retrieves chat messages from a conversation. This method is used for in-call chat functionality. + +## How it works + +The `chat.getMessages` method fetches chat messages that were sent during a call or conversation. These are ephemeral messages tied to an active call session. + +## Key concepts + +### In-call chat + +Chat messages are: +- Associated with active calls +- Ephemeral (not permanently stored) +- Real-time communication during calls +- Visible to call participants + +### Message retrieval + +You can retrieve: +- Recent messages +- Message history +- Messages by conversation ID + +## Parameters + + + Configuration for retrieving chat messages. + + + + The unique identifier of the conversation. + + + + Maximum number of messages to retrieve. + + + + Number of messages to skip (for pagination). + + +## Signature + +```typescript +chat.getMessages(params: GetConversationChatMessageParams): Promise +``` + +## Returns + +**Type:** `Promise` + +Returns a Promise that resolves with an array of chat messages and pagination information. + +## Examples + +### Get recent messages + +```typescript +const result = await client.chat.getMessages({ + conversationId: 'conversation-id-here' +}) + +console.log('Messages:', result.messages) +``` + +### Display messages in UI + +```typescript +const result = await client.chat.getMessages({ + conversationId: 'conversation-id-here' +}) + +const chatContainer = document.getElementById('chat-messages') + +result.messages.forEach(message => { + const messageDiv = document.createElement('div') + messageDiv.className = 'message' + messageDiv.textContent = `${message.from}: ${message.content}` + chatContainer.appendChild(messageDiv) +}) +``` + +### Get messages with pagination + +```typescript +const result = await client.chat.getMessages({ + conversationId: 'conversation-id-here', + limit: 20, + offset: 0 +}) + +console.log(`Showing ${result.messages.length} of ${result.total} messages`) +``` + +### Load more messages + +```typescript +let offset = 0 +const limit = 20 + +async function loadMoreMessages() { + const result = await client.chat.getMessages({ + conversationId: 'conversation-id-here', + limit: limit, + offset: offset + }) + + displayMessages(result.messages) + offset += limit + + if (result.messages.length < limit) { + console.log('No more messages to load') + } +} +``` + +### Error handling + +```typescript +try { + const result = await client.chat.getMessages({ + conversationId: 'conversation-id-here' + }) + console.log('Retrieved messages:', result.messages.length) +} catch (error) { + console.error('Failed to get messages:', error) +} +``` + +### Filter messages by sender + +```typescript +const result = await client.chat.getMessages({ + conversationId: 'conversation-id-here' +}) + +const myMessages = result.messages.filter( + msg => msg.from === currentUserId +) + +console.log('My messages:', myMessages) +``` + +### Get messages with timestamp + +```typescript +const result = await client.chat.getMessages({ + conversationId: 'conversation-id-here' +}) + +result.messages.forEach(message => { + const timestamp = new Date(message.timestamp).toLocaleTimeString() + console.log(`[${timestamp}] ${message.from}: ${message.content}`) +}) +``` + +### Refresh messages periodically + +```typescript +setInterval(async () => { + const result = await client.chat.getMessages({ + conversationId: 'conversation-id-here', + limit: 10 + }) + + updateChatUI(result.messages) +}, 5000) +``` + diff --git a/website/docs/signalwire-sdk/tech-ref/SignalWireClient/Chat/chat-join.mdx b/website/docs/signalwire-sdk/tech-ref/SignalWireClient/Chat/chat-join.mdx new file mode 100644 index 000000000..64eb90acc --- /dev/null +++ b/website/docs/signalwire-sdk/tech-ref/SignalWireClient/Chat/chat-join.mdx @@ -0,0 +1,168 @@ +--- +title: chat.join +slug: /signalwire-client/chat-join +--- + +import APIField from '@site/src/components/APIField'; + +Joins a chat conversation, allowing you to send and receive messages in an active call or conversation. + +## How it works + +The `chat.join` method adds you as a participant to a chat conversation. Once joined, you can send messages and receive real-time updates for new messages. + +## Key concepts + +### Chat participation + +Joining a chat allows you to: +- Send messages to participants +- Receive messages in real-time +- View conversation history +- Participate in group discussions + +### Conversation context + +Chats are typically associated with: +- Active calls +- Video conferences +- Group conversations + +## Parameters + + + Configuration for joining the conversation. + + + + The unique identifier of the conversation to join. + + + + Optional member identifier for the participant. + + +## Signature + +```typescript +chat.join(params: JoinConversationParams): Promise +``` + +## Returns + +**Type:** `Promise` + +Returns a Promise that resolves with conversation details and participant information. + +## Examples + +### Join a chat + +```typescript +const response = await client.chat.join({ + conversationId: 'conversation-id-here' +}) + +console.log('Joined conversation:', response.conversationId) +``` + +### Join and start chatting + +```typescript +const response = await client.chat.join({ + conversationId: 'conversation-id-here' +}) + +await client.chat.sendMessage({ + conversationId: response.conversationId, + content: 'Hello everyone!' +}) +``` + +### Join with member ID + +```typescript +const response = await client.chat.join({ + conversationId: 'conversation-id-here', + memberId: 'my-member-id' +}) + +console.log('Joined as:', response.memberId) +``` + +### Join and subscribe to messages + +```typescript +const response = await client.chat.join({ + conversationId: 'conversation-id-here' +}) + +await client.chat.subscribe({ + conversationId: response.conversationId, + onMessage: (message) => { + console.log('New message:', message.content) + } +}) +``` + +### Error handling + +```typescript +try { + const response = await client.chat.join({ + conversationId: 'conversation-id-here' + }) + console.log('Successfully joined chat') +} catch (error) { + console.error('Failed to join chat:', error) +} +``` + +### Join during call + +```typescript +const callSession = await client.dial({ + to: '+15551234567', + from: '+15559876543' +}) + +const response = await client.chat.join({ + conversationId: callSession.conversationId +}) + +console.log('Chat enabled for call') +``` + +### Join with UI update + +```typescript +async function joinChat(conversationId) { + try { + const response = await client.chat.join({ + conversationId: conversationId + }) + + document.getElementById('chat-panel').style.display = 'block' + document.getElementById('chat-status').textContent = 'Connected' + + return response + } catch (error) { + document.getElementById('chat-status').textContent = 'Connection failed' + console.error(error) + } +} +``` + +### Auto-join on call answer + +```typescript +callSession.on('call.state', async (event) => { + if (event.call.state === 'answered') { + await client.chat.join({ + conversationId: callSession.conversationId + }) + console.log('Chat ready') + } +}) +``` + diff --git a/website/docs/signalwire-sdk/tech-ref/SignalWireClient/Chat/chat-send-message.mdx b/website/docs/signalwire-sdk/tech-ref/SignalWireClient/Chat/chat-send-message.mdx new file mode 100644 index 000000000..730607ebb --- /dev/null +++ b/website/docs/signalwire-sdk/tech-ref/SignalWireClient/Chat/chat-send-message.mdx @@ -0,0 +1,212 @@ +--- +title: chat.sendMessage +slug: /signalwire-client/chat-send-message +--- + +import APIField from '@site/src/components/APIField'; + +Sends a message in a chat conversation during an active call. + +## How it works + +The `chat.sendMessage` method delivers a text message to all participants in a chat conversation. Messages are sent in real-time to active participants. + +## Key concepts + +### Message delivery + +Messages are: +- Delivered in real-time +- Visible to all conversation participants +- Ephemeral (tied to the call session) +- Ordered chronologically + +### Message content + +You can send: +- Plain text messages +- Formatted text +- Metadata with messages + +## Parameters + + + Configuration for sending the message. + + + + The unique identifier of the conversation. + + + + The message text to send. + + + + Optional metadata to attach to the message. + + +## Signature + +```typescript +chat.sendMessage(params: SendConversationMessageParams): Promise +``` + +## Returns + +**Type:** `Promise` + +Returns a Promise that resolves with the sent message details including message ID and timestamp. + +## Examples + +### Send a message + +```typescript +const response = await client.chat.sendMessage({ + conversationId: 'conversation-id-here', + content: 'Hello everyone!' +}) + +console.log('Message sent:', response.messageId) +``` + +### Send message from input + +```typescript +const sendButton = document.getElementById('send-btn') +const messageInput = document.getElementById('message-input') + +sendButton.addEventListener('click', async () => { + const content = messageInput.value.trim() + + if (content) { + await client.chat.sendMessage({ + conversationId: 'conversation-id-here', + content: content + }) + + messageInput.value = '' + } +}) +``` + +### Send message with metadata + +```typescript +const response = await client.chat.sendMessage({ + conversationId: 'conversation-id-here', + content: 'Check this out!', + metadata: { + type: 'announcement', + priority: 'high' + } +}) +``` + +### Error handling + +```typescript +try { + await client.chat.sendMessage({ + conversationId: 'conversation-id-here', + content: 'Hello!' + }) + console.log('Message sent successfully') +} catch (error) { + console.error('Failed to send message:', error) +} +``` + +### Send message with confirmation + +```typescript +async function sendMessageWithConfirmation(content) { + try { + const response = await client.chat.sendMessage({ + conversationId: 'conversation-id-here', + content: content + }) + + showNotification('Message sent') + return response + } catch (error) { + showNotification('Failed to send message') + throw error + } +} +``` + +### Send message on Enter key + +```typescript +const messageInput = document.getElementById('message-input') + +messageInput.addEventListener('keypress', async (e) => { + if (e.key === 'Enter' && !e.shiftKey) { + e.preventDefault() + + const content = messageInput.value.trim() + + if (content) { + await client.chat.sendMessage({ + conversationId: 'conversation-id-here', + content: content + }) + + messageInput.value = '' + } + } +}) +``` + +### Display sent message immediately + +```typescript +async function sendAndDisplayMessage(content) { + const tempId = Date.now().toString() + + displayMessage({ + id: tempId, + content: content, + from: 'You', + timestamp: new Date() + }) + + try { + const response = await client.chat.sendMessage({ + conversationId: 'conversation-id-here', + content: content + }) + + updateMessageId(tempId, response.messageId) + } catch (error) { + markMessageAsFailed(tempId) + console.error('Failed to send:', error) + } +} +``` + +### Throttle message sending + +```typescript +let lastMessageTime = 0 +const throttleMs = 1000 + +async function sendThrottledMessage(content) { + const now = Date.now() + + if (now - lastMessageTime < throttleMs) { + console.log('Please wait before sending another message') + return + } + + lastMessageTime = now + + await client.chat.sendMessage({ + conversationId: 'conversation-id-here', + content: content + }) +} +``` + diff --git a/website/docs/signalwire-sdk/tech-ref/SignalWireClient/Chat/chat-subscribe.mdx b/website/docs/signalwire-sdk/tech-ref/SignalWireClient/Chat/chat-subscribe.mdx new file mode 100644 index 000000000..52d13566c --- /dev/null +++ b/website/docs/signalwire-sdk/tech-ref/SignalWireClient/Chat/chat-subscribe.mdx @@ -0,0 +1,220 @@ +--- +title: chat.subscribe +slug: /signalwire-client/chat-subscribe +--- + +import APIField from '@site/src/components/APIField'; + +Subscribes to real-time chat message events in a conversation, allowing you to receive notifications when new messages arrive. + +## How it works + +The `chat.subscribe` method establishes a real-time subscription to chat events. When new messages are sent in the conversation, your callback function is invoked with the message details. + +## Key concepts + +### Real-time updates + +Subscriptions provide: +- Instant message notifications +- Live chat updates +- Event-driven architecture +- Bi-directional communication + +### Event handling + +Your callback receives: +- New messages +- Message metadata +- Sender information +- Timestamps + +## Parameters + + + Configuration for the subscription. + + + + The unique identifier of the conversation to subscribe to. + + + + Callback function invoked when new messages arrive. + + +## Signature + +```typescript +chat.subscribe(params: ConversationChatMessagesSubscribeParams): Promise +``` + +## Returns + +**Type:** `Promise` + +Returns a Promise that resolves with subscription details including an unsubscribe method. + +## Examples + +### Subscribe to messages + +```typescript +const subscription = await client.chat.subscribe({ + conversationId: 'conversation-id-here', + onMessage: (message) => { + console.log('New message from', message.from) + console.log('Content:', message.content) + } +}) +``` + +### Display messages in UI + +```typescript +await client.chat.subscribe({ + conversationId: 'conversation-id-here', + onMessage: (message) => { + const chatContainer = document.getElementById('chat-messages') + + const messageDiv = document.createElement('div') + messageDiv.className = 'message' + messageDiv.textContent = `${message.from}: ${message.content}` + + chatContainer.appendChild(messageDiv) + chatContainer.scrollTop = chatContainer.scrollHeight + } +}) +``` + +### Subscribe with timestamp + +```typescript +await client.chat.subscribe({ + conversationId: 'conversation-id-here', + onMessage: (message) => { + const time = new Date(message.timestamp).toLocaleTimeString() + console.log(`[${time}] ${message.from}: ${message.content}`) + } +}) +``` + +### Unsubscribe when done + +```typescript +const subscription = await client.chat.subscribe({ + conversationId: 'conversation-id-here', + onMessage: (message) => { + console.log('Message:', message.content) + } +}) + +await subscription.unsubscribe() +console.log('Unsubscribed from chat') +``` + +### Error handling + +```typescript +try { + await client.chat.subscribe({ + conversationId: 'conversation-id-here', + onMessage: (message) => { + displayMessage(message) + } + }) + console.log('Subscribed to chat updates') +} catch (error) { + console.error('Failed to subscribe:', error) +} +``` + +### Filter messages by type + +```typescript +await client.chat.subscribe({ + conversationId: 'conversation-id-here', + onMessage: (message) => { + if (message.metadata?.type === 'announcement') { + displayAnnouncement(message) + } else { + displayRegularMessage(message) + } + } +}) +``` + +### Play notification sound + +```typescript +const notificationSound = new Audio('/notification.mp3') + +await client.chat.subscribe({ + conversationId: 'conversation-id-here', + onMessage: (message) => { + displayMessage(message) + + if (message.from !== currentUserId) { + notificationSound.play() + } + } +}) +``` + +### Subscribe during call + +```typescript +const callSession = await client.dial({ + to: '+15551234567', + from: '+15559876543' +}) + +await client.chat.join({ + conversationId: callSession.conversationId +}) + +await client.chat.subscribe({ + conversationId: callSession.conversationId, + onMessage: (message) => { + console.log('Chat message:', message.content) + } +}) +``` + +### Manage subscription lifecycle + +```typescript +let chatSubscription = null + +async function enableChat(conversationId) { + chatSubscription = await client.chat.subscribe({ + conversationId: conversationId, + onMessage: (message) => { + displayMessage(message) + } + }) +} + +async function disableChat() { + if (chatSubscription) { + await chatSubscription.unsubscribe() + chatSubscription = null + } +} +``` + +### Track message count + +```typescript +let messageCount = 0 + +await client.chat.subscribe({ + conversationId: 'conversation-id-here', + onMessage: (message) => { + messageCount++ + document.getElementById('message-count').textContent = messageCount + displayMessage(message) + } +}) +``` + diff --git a/website/docs/signalwire-sdk/tech-ref/SignalWireClient/Conversation/conversation-get-conversation-messages.mdx b/website/docs/signalwire-sdk/tech-ref/SignalWireClient/Conversation/conversation-get-conversation-messages.mdx new file mode 100644 index 000000000..08511ea7b --- /dev/null +++ b/website/docs/signalwire-sdk/tech-ref/SignalWireClient/Conversation/conversation-get-conversation-messages.mdx @@ -0,0 +1,188 @@ +--- +title: conversation.getConversationMessages +slug: /signalwire-client/conversation-get-conversation-messages +--- + +import APIField from '@site/src/components/APIField'; + +Retrieves messages from a specific persistent conversation. Unlike chat messages which are ephemeral, conversation messages are permanently stored. + +## How it works + +The `conversation.getConversationMessages` method fetches the message history from a persistent conversation. These messages remain available even after participants leave the conversation. + +## Key concepts + +### Persistent conversations + +Conversation messages are: +- Permanently stored +- Available across sessions +- Accessible after participants leave +- Associated with conversation IDs + +### Message history + +You can retrieve: +- Full conversation history +- Recent messages +- Paginated results +- Messages with metadata + +## Parameters + + + Configuration for retrieving conversation messages. + + + + The unique identifier of the conversation. + + + + Maximum number of messages to retrieve. + + + + Number of messages to skip (for pagination). + + +## Signature + +```typescript +conversation.getConversationMessages(params: GetConversationMessagesParams): Promise +``` + +## Returns + +**Type:** `Promise` + +Returns a Promise that resolves with an array of messages and pagination information. + +## Examples + +### Get conversation messages + +```typescript +const result = await client.conversation.getConversationMessages({ + conversationId: 'conversation-id-here' +}) + +console.log('Messages:', result.messages) +``` + +### Display message history + +```typescript +const result = await client.conversation.getConversationMessages({ + conversationId: 'conversation-id-here' +}) + +result.messages.forEach(message => { + console.log(`${message.from}: ${message.content}`) + console.log(`Sent at: ${new Date(message.timestamp).toLocaleString()}`) +}) +``` + +### Paginate through messages + +```typescript +const result = await client.conversation.getConversationMessages({ + conversationId: 'conversation-id-here', + limit: 20, + offset: 0 +}) + +console.log(`Showing ${result.messages.length} of ${result.total} messages`) + +if (result.hasMore) { + console.log('More messages available') +} +``` + +### Load older messages + +```typescript +let offset = 0 +const limit = 20 + +async function loadOlderMessages() { + const result = await client.conversation.getConversationMessages({ + conversationId: 'conversation-id-here', + limit: limit, + offset: offset + }) + + prependMessages(result.messages) + offset += limit + + return result.hasMore +} + +const hasMore = await loadOlderMessages() +``` + +### Error handling + +```typescript +try { + const result = await client.conversation.getConversationMessages({ + conversationId: 'conversation-id-here' + }) + console.log('Retrieved messages:', result.messages.length) +} catch (error) { + console.error('Failed to get messages:', error) +} +``` + +### Display in chat UI + +```typescript +const result = await client.conversation.getConversationMessages({ + conversationId: 'conversation-id-here' +}) + +const chatContainer = document.getElementById('chat-messages') +chatContainer.innerHTML = '' + +result.messages.forEach(message => { + const messageDiv = document.createElement('div') + messageDiv.className = message.from === currentUserId ? 'message-sent' : 'message-received' + messageDiv.innerHTML = ` +
${message.from}
+
${message.content}
+
${new Date(message.timestamp).toLocaleTimeString()}
+ ` + chatContainer.appendChild(messageDiv) +}) +``` + +### Filter system messages + +```typescript +const result = await client.conversation.getConversationMessages({ + conversationId: 'conversation-id-here' +}) + +const userMessages = result.messages.filter( + msg => msg.type !== 'system' +) + +console.log('User messages:', userMessages) +``` + +### Search conversation history + +```typescript +const result = await client.conversation.getConversationMessages({ + conversationId: 'conversation-id-here' +}) + +const searchTerm = 'important' +const matchingMessages = result.messages.filter( + msg => msg.content.toLowerCase().includes(searchTerm.toLowerCase()) +) + +console.log(`Found ${matchingMessages.length} messages containing "${searchTerm}"`) +``` + diff --git a/website/docs/signalwire-sdk/tech-ref/SignalWireClient/Conversation/conversation-get-conversations.mdx b/website/docs/signalwire-sdk/tech-ref/SignalWireClient/Conversation/conversation-get-conversations.mdx new file mode 100644 index 000000000..6f3886d45 --- /dev/null +++ b/website/docs/signalwire-sdk/tech-ref/SignalWireClient/Conversation/conversation-get-conversations.mdx @@ -0,0 +1,206 @@ +--- +title: conversation.getConversations +slug: /signalwire-client/conversation-get-conversations +--- + +import APIField from '@site/src/components/APIField'; + +Retrieves a list of conversations that the current subscriber has access to or is participating in. + +## How it works + +The `conversation.getConversations` method fetches all conversations associated with the authenticated subscriber. This includes active conversations, archived conversations, and group discussions. + +## Key concepts + +### Conversation types + +Conversations can include: +- One-on-one chats +- Group conversations +- Archived discussions +- Active ongoing conversations + +### Conversation metadata + +Each conversation includes: +- Conversation ID +- Participant list +- Last message preview +- Unread message count +- Timestamps + +## Parameters + + + Optional configuration for filtering conversations. + + + + Maximum number of conversations to retrieve. + + + + Number of conversations to skip (for pagination). + + + + Optional filter criteria for conversations. + + +## Signature + +```typescript +conversation.getConversations(params?: GetConversationsParams): Promise +``` + +## Returns + +**Type:** `Promise` + +Returns a Promise that resolves with an array of conversations and pagination information. + +## Examples + +### Get all conversations + +```typescript +const result = await client.conversation.getConversations() + +console.log('Conversations:', result.conversations) +``` + +### Display conversation list + +```typescript +const result = await client.conversation.getConversations() + +const listContainer = document.getElementById('conversations-list') + +result.conversations.forEach(conversation => { + const item = document.createElement('div') + item.className = 'conversation-item' + item.innerHTML = ` +

${conversation.name}

+

${conversation.lastMessage?.content || 'No messages'}

+ ${conversation.unreadCount} unread + ` + item.onclick = () => openConversation(conversation.id) + listContainer.appendChild(item) +}) +``` + +### Get conversations with pagination + +```typescript +const result = await client.conversation.getConversations({ + limit: 10, + offset: 0 +}) + +console.log(`Showing ${result.conversations.length} of ${result.total}`) +``` + +### Load more conversations + +```typescript +let offset = 0 +const limit = 10 + +async function loadMoreConversations() { + const result = await client.conversation.getConversations({ + limit: limit, + offset: offset + }) + + displayConversations(result.conversations) + offset += limit + + return result.hasMore +} +``` + +### Error handling + +```typescript +try { + const result = await client.conversation.getConversations() + console.log('Retrieved conversations:', result.conversations.length) +} catch (error) { + console.error('Failed to get conversations:', error) +} +``` + +### Sort conversations by recent activity + +```typescript +const result = await client.conversation.getConversations() + +const sorted = result.conversations.sort((a, b) => { + const timeA = new Date(a.lastMessageTimestamp).getTime() + const timeB = new Date(b.lastMessageTimestamp).getTime() + return timeB - timeA +}) + +console.log('Most recent conversations:', sorted) +``` + +### Filter unread conversations + +```typescript +const result = await client.conversation.getConversations() + +const unread = result.conversations.filter( + conv => conv.unreadCount > 0 +) + +console.log(`You have ${unread.length} conversations with unread messages`) +``` + +### Get total unread count + +```typescript +const result = await client.conversation.getConversations() + +const totalUnread = result.conversations.reduce( + (sum, conv) => sum + conv.unreadCount, + 0 +) + +console.log(`Total unread messages: ${totalUnread}`) +document.getElementById('unread-badge').textContent = totalUnread +``` + +### Find specific conversation + +```typescript +const result = await client.conversation.getConversations() + +const conversation = result.conversations.find( + conv => conv.name === 'Team Discussion' +) + +if (conversation) { + console.log('Found conversation:', conversation.id) +} +``` + +### Refresh conversations list + +```typescript +async function refreshConversations() { + const result = await client.conversation.getConversations() + + updateConversationsList(result.conversations) + + const totalUnread = result.conversations.reduce( + (sum, conv) => sum + conv.unreadCount, + 0 + ) + + updateUnreadBadge(totalUnread) +} + +setInterval(refreshConversations, 30000) +``` + diff --git a/website/docs/signalwire-sdk/tech-ref/SignalWireClient/Conversation/conversation-get-messages.mdx b/website/docs/signalwire-sdk/tech-ref/SignalWireClient/Conversation/conversation-get-messages.mdx new file mode 100644 index 000000000..1fc13aaba --- /dev/null +++ b/website/docs/signalwire-sdk/tech-ref/SignalWireClient/Conversation/conversation-get-messages.mdx @@ -0,0 +1,206 @@ +--- +title: conversation.getMessages +slug: /signalwire-client/conversation-get-messages +--- + +import APIField from '@site/src/components/APIField'; + +Retrieves messages across all conversations, providing a unified view of messages from multiple conversations. + +## How it works + +The `conversation.getMessages` method fetches messages from all conversations the subscriber has access to. This is useful for displaying a combined message feed or searching across conversations. + +## Key concepts + +### Cross-conversation retrieval + +This method: +- Aggregates messages from multiple conversations +- Provides a unified message feed +- Supports filtering and sorting +- Enables global message search + +### Use cases + +Common scenarios: +- Displaying recent messages from all conversations +- Search across all conversations +- Activity feed +- Global message notifications + +## Parameters + + + Optional configuration for retrieving messages. + + + + Maximum number of messages to retrieve. + + + + Number of messages to skip (for pagination). + + + + Optional filter criteria for messages. + + +## Signature + +```typescript +conversation.getMessages(params?: GetMessagesParams): Promise +``` + +## Returns + +**Type:** `Promise` + +Returns a Promise that resolves with an array of messages from all conversations. + +## Examples + +### Get recent messages + +```typescript +const result = await client.conversation.getMessages() + +console.log('Recent messages:', result.messages) +``` + +### Display unified message feed + +```typescript +const result = await client.conversation.getMessages({ + limit: 20 +}) + +const feedContainer = document.getElementById('message-feed') + +result.messages.forEach(message => { + const item = document.createElement('div') + item.className = 'message-item' + item.innerHTML = ` +
${message.conversationName}
+
${message.from}
+
${message.content}
+
${new Date(message.timestamp).toLocaleString()}
+ ` + feedContainer.appendChild(item) +}) +``` + +### Paginate through messages + +```typescript +const result = await client.conversation.getMessages({ + limit: 20, + offset: 0 +}) + +console.log(`Showing ${result.messages.length} of ${result.total} messages`) +``` + +### Error handling + +```typescript +try { + const result = await client.conversation.getMessages() + console.log('Retrieved messages:', result.messages.length) +} catch (error) { + console.error('Failed to get messages:', error) +} +``` + +### Search all messages + +```typescript +const result = await client.conversation.getMessages() + +const searchTerm = 'meeting' +const matches = result.messages.filter( + msg => msg.content.toLowerCase().includes(searchTerm.toLowerCase()) +) + +console.log(`Found ${matches.length} messages containing "${searchTerm}"`) +``` + +### Group messages by conversation + +```typescript +const result = await client.conversation.getMessages() + +const grouped = result.messages.reduce((acc, message) => { + if (!acc[message.conversationId]) { + acc[message.conversationId] = [] + } + acc[message.conversationId].push(message) + return acc +}, {}) + +console.log('Messages by conversation:', grouped) +``` + +### Get messages from today + +```typescript +const result = await client.conversation.getMessages() + +const today = new Date() +today.setHours(0, 0, 0, 0) + +const todayMessages = result.messages.filter( + msg => new Date(msg.timestamp) >= today +) + +console.log(`${todayMessages.length} messages today`) +``` + +### Load more messages + +```typescript +let offset = 0 +const limit = 20 + +async function loadMoreMessages() { + const result = await client.conversation.getMessages({ + limit: limit, + offset: offset + }) + + appendToFeed(result.messages) + offset += limit + + return result.hasMore +} +``` + +### Get unread messages + +```typescript +const result = await client.conversation.getMessages() + +const unread = result.messages.filter( + msg => !msg.read && msg.from !== currentUserId +) + +console.log(`${unread.length} unread messages`) +``` + +### Activity summary + +```typescript +const result = await client.conversation.getMessages({ + limit: 100 +}) + +const summary = { + total: result.messages.length, + conversations: new Set(result.messages.map(m => m.conversationId)).size, + unread: result.messages.filter(m => !m.read).length +} + +console.log('Activity summary:', summary) +``` + diff --git a/website/docs/signalwire-sdk/tech-ref/SignalWireClient/Conversation/conversation-join.mdx b/website/docs/signalwire-sdk/tech-ref/SignalWireClient/Conversation/conversation-join.mdx new file mode 100644 index 000000000..4953e17f6 --- /dev/null +++ b/website/docs/signalwire-sdk/tech-ref/SignalWireClient/Conversation/conversation-join.mdx @@ -0,0 +1,171 @@ +--- +title: conversation.join +slug: /signalwire-client/conversation-join +--- + +import APIField from '@site/src/components/APIField'; + +Joins a persistent conversation, allowing you to send and receive messages in that conversation. + +## How it works + +The `conversation.join` method adds you as a participant to a persistent conversation. Once joined, you can send messages, receive updates, and access the conversation history. + +## Key concepts + +### Conversation participation + +Joining a conversation allows you to: +- Send and receive messages +- Access conversation history +- Receive real-time updates +- View participant list + +### Persistent vs ephemeral + +Unlike chat (ephemeral), conversations are: +- Permanently stored +- Available across sessions +- Accessible after leaving and rejoining + +## Parameters + + + Configuration for joining the conversation. + + + + The unique identifier of the conversation to join. + + + + Optional member identifier for the participant. + + +## Signature + +```typescript +conversation.join(params: JoinConversationParams): Promise +``` + +## Returns + +**Type:** `Promise` + +Returns a Promise that resolves with conversation details and participant information. + +## Examples + +### Join a conversation + +```typescript +const response = await client.conversation.join({ + conversationId: 'conversation-id-here' +}) + +console.log('Joined conversation:', response.conversationId) +``` + +### Join and load history + +```typescript +const response = await client.conversation.join({ + conversationId: 'conversation-id-here' +}) + +const messages = await client.conversation.getConversationMessages({ + conversationId: response.conversationId +}) + +console.log('Loaded message history:', messages.messages.length) +``` + +### Join with member ID + +```typescript +const response = await client.conversation.join({ + conversationId: 'conversation-id-here', + memberId: 'my-member-id' +}) + +console.log('Joined as:', response.memberId) +``` + +### Error handling + +```typescript +try { + const response = await client.conversation.join({ + conversationId: 'conversation-id-here' + }) + console.log('Successfully joined conversation') +} catch (error) { + console.error('Failed to join conversation:', error) +} +``` + +### Join and subscribe + +```typescript +const response = await client.conversation.join({ + conversationId: 'conversation-id-here' +}) + +await client.conversation.subscribe((event) => { + if (event.type === 'message.created') { + console.log('New message:', event.message.content) + } +}) +``` + +### Join conversation from list + +```typescript +async function openConversation(conversationId) { + const response = await client.conversation.join({ + conversationId: conversationId + }) + + const messages = await client.conversation.getConversationMessages({ + conversationId: conversationId + }) + + displayConversation(response, messages) +} +``` + +### Auto-join on notification + +```typescript +async function handleConversationNotification(notificationData) { + const conversationId = notificationData.conversationId + + const response = await client.conversation.join({ + conversationId: conversationId + }) + + console.log('Joined conversation from notification') + openConversationUI(conversationId) +} +``` + +### Join with UI update + +```typescript +async function joinConversation(conversationId) { + try { + const response = await client.conversation.join({ + conversationId: conversationId + }) + + document.getElementById('conversation-title').textContent = response.name + document.getElementById('participant-count').textContent = response.participantCount + + return response + } catch (error) { + console.error('Failed to join:', error) + showError('Could not join conversation') + } +} +``` + diff --git a/website/docs/signalwire-sdk/tech-ref/SignalWireClient/Conversation/conversation-send-message.mdx b/website/docs/signalwire-sdk/tech-ref/SignalWireClient/Conversation/conversation-send-message.mdx new file mode 100644 index 000000000..83f1cd6c4 --- /dev/null +++ b/website/docs/signalwire-sdk/tech-ref/SignalWireClient/Conversation/conversation-send-message.mdx @@ -0,0 +1,260 @@ +--- +title: conversation.sendMessage +slug: /signalwire-client/conversation-send-message +--- + +import APIField from '@site/src/components/APIField'; + +Sends a message in a persistent conversation. Messages are stored permanently and remain accessible to all participants. + +## How it works + +The `conversation.sendMessage` method delivers a message to all participants in a persistent conversation. Unlike ephemeral chat messages, these messages are permanently stored. + +## Key concepts + +### Message persistence + +Conversation messages are: +- Permanently stored +- Accessible across sessions +- Available to all participants +- Synced across devices + +### Message delivery + +Messages are: +- Delivered in real-time to active participants +- Available for retrieval by offline participants +- Ordered chronologically +- Guaranteed delivery + +## Parameters + + + Configuration for sending the message. + + + + The unique identifier of the conversation. + + + + The message text to send. + + + + Optional metadata to attach to the message. + + +## Signature + +```typescript +conversation.sendMessage(params: SendConversationMessageParams): Promise +``` + +## Returns + +**Type:** `Promise` + +Returns a Promise that resolves with the sent message details including message ID and timestamp. + +## Examples + +### Send a message + +```typescript +const response = await client.conversation.sendMessage({ + conversationId: 'conversation-id-here', + content: 'Hello everyone!' +}) + +console.log('Message sent:', response.messageId) +``` + +### Send message from input + +```typescript +const sendButton = document.getElementById('send-btn') +const messageInput = document.getElementById('message-input') + +sendButton.addEventListener('click', async () => { + const content = messageInput.value.trim() + + if (content) { + await client.conversation.sendMessage({ + conversationId: 'conversation-id-here', + content: content + }) + + messageInput.value = '' + } +}) +``` + +### Send message with metadata + +```typescript +const response = await client.conversation.sendMessage({ + conversationId: 'conversation-id-here', + content: 'Check out this file!', + metadata: { + type: 'file_share', + fileUrl: 'https://example.com/file.pdf', + fileName: 'document.pdf' + } +}) +``` + +### Error handling + +```typescript +try { + await client.conversation.sendMessage({ + conversationId: 'conversation-id-here', + content: 'Hello!' + }) + console.log('Message sent successfully') +} catch (error) { + console.error('Failed to send message:', error) +} +``` + +### Send message on Enter key + +```typescript +const messageInput = document.getElementById('message-input') + +messageInput.addEventListener('keypress', async (e) => { + if (e.key === 'Enter' && !e.shiftKey) { + e.preventDefault() + + const content = messageInput.value.trim() + + if (content) { + await client.conversation.sendMessage({ + conversationId: 'conversation-id-here', + content: content + }) + + messageInput.value = '' + } + } +}) +``` + +### Display sent message immediately + +```typescript +async function sendAndDisplayMessage(content) { + const tempId = `temp-${Date.now()}` + + displayMessage({ + id: tempId, + content: content, + from: currentUserId, + timestamp: new Date(), + status: 'sending' + }) + + try { + const response = await client.conversation.sendMessage({ + conversationId: 'conversation-id-here', + content: content + }) + + updateMessage(tempId, { + id: response.messageId, + status: 'sent' + }) + } catch (error) { + updateMessage(tempId, { + status: 'failed' + }) + console.error('Failed to send:', error) + } +} +``` + +### Send with retry logic + +```typescript +async function sendMessageWithRetry(content, maxRetries = 3) { + for (let i = 0; i < maxRetries; i++) { + try { + const response = await client.conversation.sendMessage({ + conversationId: 'conversation-id-here', + content: content + }) + return response + } catch (error) { + console.log(`Send attempt ${i + 1} failed`) + + if (i < maxRetries - 1) { + await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1))) + } else { + throw error + } + } + } +} +``` + +### Send formatted message + +```typescript +await client.conversation.sendMessage({ + conversationId: 'conversation-id-here', + content: 'Important announcement!', + metadata: { + format: 'announcement', + priority: 'high', + timestamp: new Date().toISOString() + } +}) +``` + +### Reply to a message + +```typescript +await client.conversation.sendMessage({ + conversationId: 'conversation-id-here', + content: 'Thanks for the update!', + metadata: { + replyTo: originalMessageId, + quotedText: originalMessage.content + } +}) +``` + +### Send with typing indicator + +```typescript +let typingTimer + +messageInput.addEventListener('input', () => { + clearTimeout(typingTimer) + + client.conversation.sendTypingIndicator({ + conversationId: 'conversation-id-here' + }) + + typingTimer = setTimeout(() => { + }, 3000) +}) + +messageInput.addEventListener('keypress', async (e) => { + if (e.key === 'Enter') { + clearTimeout(typingTimer) + + const content = messageInput.value.trim() + if (content) { + await client.conversation.sendMessage({ + conversationId: 'conversation-id-here', + content: content + }) + } + } +}) +``` + diff --git a/website/docs/signalwire-sdk/tech-ref/SignalWireClient/Conversation/conversation-subscribe.mdx b/website/docs/signalwire-sdk/tech-ref/SignalWireClient/Conversation/conversation-subscribe.mdx new file mode 100644 index 000000000..d382647b3 --- /dev/null +++ b/website/docs/signalwire-sdk/tech-ref/SignalWireClient/Conversation/conversation-subscribe.mdx @@ -0,0 +1,238 @@ +--- +title: conversation.subscribe +slug: /signalwire-client/conversation-subscribe +--- + +import APIField from '@site/src/components/APIField'; + +Subscribes to real-time conversation events, allowing you to receive notifications for new messages, participant changes, and other conversation updates. + +## How it works + +The `conversation.subscribe` method establishes a real-time subscription to conversation events. When events occur (new messages, participants joining/leaving, etc.), your callback function is invoked with event details. + +## Key concepts + +### Real-time subscriptions + +Subscriptions provide: +- Instant event notifications +- Live conversation updates +- Bi-directional communication +- Event-driven architecture + +### Event types + +Common events include: +- New messages +- Message updates/deletions +- Participant joined/left +- Conversation metadata changes +- Typing indicators + +## Parameters + + + Callback function invoked when conversation events occur. + + +## Signature + +```typescript +conversation.subscribe(callback: ConversationSubscribeCallback): Promise +``` + +## Returns + +**Type:** `Promise` + +Returns a Promise that resolves with subscription details including an unsubscribe method. + +## Examples + +### Subscribe to conversation events + +```typescript +const subscription = await client.conversation.subscribe((event) => { + console.log('Conversation event:', event.type) + + if (event.type === 'message.created') { + console.log('New message:', event.message.content) + } +}) +``` + +### Handle different event types + +```typescript +await client.conversation.subscribe((event) => { + switch (event.type) { + case 'message.created': + displayNewMessage(event.message) + break + case 'message.updated': + updateMessage(event.message) + break + case 'message.deleted': + removeMessage(event.messageId) + break + case 'participant.joined': + console.log(`${event.participant.name} joined`) + break + case 'participant.left': + console.log(`${event.participant.name} left`) + break + } +}) +``` + +### Subscribe with UI updates + +```typescript +await client.conversation.subscribe((event) => { + if (event.type === 'message.created') { + const chatContainer = document.getElementById('chat-messages') + + const messageDiv = document.createElement('div') + messageDiv.className = 'message' + messageDiv.innerHTML = ` +
${event.message.from}
+
${event.message.content}
+
${new Date(event.message.timestamp).toLocaleTimeString()}
+ ` + + chatContainer.appendChild(messageDiv) + chatContainer.scrollTop = chatContainer.scrollHeight + } +}) +``` + +### Unsubscribe when done + +```typescript +const subscription = await client.conversation.subscribe((event) => { + console.log('Event:', event.type) +}) + +await subscription.unsubscribe() +console.log('Unsubscribed from conversation events') +``` + +### Error handling + +```typescript +try { + await client.conversation.subscribe((event) => { + handleEvent(event) + }) + console.log('Subscribed to conversation updates') +} catch (error) { + console.error('Failed to subscribe:', error) +} +``` + +### Filter events by conversation + +```typescript +const activeConversationId = 'conversation-id-here' + +await client.conversation.subscribe((event) => { + if (event.conversationId === activeConversationId) { + handleEvent(event) + } +}) +``` + +### Play notification sound + +```typescript +const notificationSound = new Audio('/notification.mp3') + +await client.conversation.subscribe((event) => { + if (event.type === 'message.created') { + displayMessage(event.message) + + if (event.message.from !== currentUserId) { + notificationSound.play() + } + } +}) +``` + +### Update unread count + +```typescript +let unreadCount = 0 + +await client.conversation.subscribe((event) => { + if (event.type === 'message.created' && event.message.from !== currentUserId) { + unreadCount++ + document.getElementById('unread-badge').textContent = unreadCount + } +}) +``` + +### Track typing indicators + +```typescript +const typingUsers = new Set() + +await client.conversation.subscribe((event) => { + if (event.type === 'typing.started') { + typingUsers.add(event.userId) + updateTypingIndicator(typingUsers) + } else if (event.type === 'typing.stopped') { + typingUsers.delete(event.userId) + updateTypingIndicator(typingUsers) + } +}) + +function updateTypingIndicator(users) { + const indicator = document.getElementById('typing-indicator') + + if (users.size === 0) { + indicator.textContent = '' + } else if (users.size === 1) { + indicator.textContent = `${Array.from(users)[0]} is typing...` + } else { + indicator.textContent = `${users.size} people are typing...` + } +} +``` + +### Manage subscription lifecycle + +```typescript +let conversationSubscription = null + +async function enableConversationUpdates() { + conversationSubscription = await client.conversation.subscribe((event) => { + handleConversationEvent(event) + }) +} + +async function disableConversationUpdates() { + if (conversationSubscription) { + await conversationSubscription.unsubscribe() + conversationSubscription = null + } +} +``` + +### Log all conversation activity + +```typescript +await client.conversation.subscribe((event) => { + console.log(`[${new Date().toISOString()}] ${event.type}`, event) + + const logEntry = { + timestamp: new Date(), + eventType: event.type, + conversationId: event.conversationId, + details: event + } + + saveToActivityLog(logEntry) +}) +``` + diff --git a/website/docs/signalwire-sdk/tech-ref/SignalWireClient/dial.mdx b/website/docs/signalwire-sdk/tech-ref/SignalWireClient/dial.mdx index 83a6d4115..d9b5308fb 100644 --- a/website/docs/signalwire-sdk/tech-ref/SignalWireClient/dial.mdx +++ b/website/docs/signalwire-sdk/tech-ref/SignalWireClient/dial.mdx @@ -1,13 +1,142 @@ -# dial() +--- +title: dial +slug: /signalwire-client/dial +--- -The `dial()` method allows you to dial any number or resource within the Call Fabric. +import APIField from '@site/src/components/APIField'; -```javascript +Initiates an outbound call to a destination and returns a CallSession object for managing the active call. + +## How it works + +The `dial` method establishes a new call connection to the specified destination. Once the call is initiated, you receive a `CallSession` object that you can use to control the call, manage participants, and listen to call events. + +## Key concepts + +### Destination types + +You can dial different types of destinations: +- **Phone numbers:** E.164 formatted numbers (e.g., `+15551234567`) +- **SIP addresses:** Direct SIP endpoint addresses +- **Resource names:** Named resources configured in your SignalWire space + +### Call lifecycle + +1. Call is initiated with `dial()` +2. `CallSession` is returned immediately +3. Call progresses through states: `connecting`, `ringing`, `answered` +4. Listen to events to track call state changes + +## Parameters + + + Configuration for the outbound call. + + + + The destination to call. Can be a phone number, SIP address, or resource name. + + + + Specific node ID to use for the call routing. + + + + Optional event listeners for the call session. + + + + HTML element in which to display the video stream. + + + + User and UserAgent metadata. + + + + Audio constraints to use when joining the call. + + + + Video constraints to use when joining the call. + + + + Negotiate the incoming audio from the RTC. + + + + Negotiate the incoming video from the RTC. + + + + Disable ICE UDP transport policy. + + + + Whether to apply the local-overlay on top of your video. + + + + Whether to apply an overlay on top of each member. + + + + Whether to mirror the local video overlay. + + + + Whether to stop the camera when the member is muted. + + + + Whether to stop the microphone when the member is muted. + + + + Call address ID matching one of the subscriber's addresses to attribute conversation API events in the INVITE. + + +## Signature + +```typescript +dial(params: DialParams): Promise +``` + +## Returns + +**Type:** `Promise` + +Returns a Promise that resolves to a [CallSession](../CallSession) object representing the active call. + +## Permissions + +Requires the ability to make outbound calls based on your subscriber configuration and space settings. + +## Examples + +### Basic outbound call + +```typescript const callSession = await client.dial({ - to: '1234567890', -}); + to: '+15551234567' +}) + +console.log('Call initiated:', callSession.id) ``` -## Parameters +### Dial with video and event listeners -- `to`: The number or resource to dial. \ No newline at end of file +```typescript +const callSession = await client.dial({ + to: '+15551234567', + rootElement: document.getElementById('video-container'), + audio: true, + video: true, + listen: { + onCallStateChanged: (state) => { + console.log('Call state:', state) + } + } +}) +``` diff --git a/website/docs/signalwire-sdk/tech-ref/SignalWireClient/disconnect.mdx b/website/docs/signalwire-sdk/tech-ref/SignalWireClient/disconnect.mdx new file mode 100644 index 000000000..a25e18bd6 --- /dev/null +++ b/website/docs/signalwire-sdk/tech-ref/SignalWireClient/disconnect.mdx @@ -0,0 +1,153 @@ +--- +title: disconnect +slug: /signalwire-client/disconnect +--- + +import APIField from '@site/src/components/APIField'; + +Disconnects from the SignalWire network and cleans up all active resources, including calls and subscriptions. + +## How it works + +The `disconnect` method gracefully terminates the client connection to SignalWire. It ends all active calls, removes event listeners, and frees up system resources. + +## Key concepts + +### Clean shutdown + +When disconnecting, the client: +1. Ends all active calls +2. Closes all subscriptions +3. Removes event listeners +4. Releases media devices +5. Terminates the WebSocket connection + +### Reconnection + +After disconnecting, you need to create a new client instance or call connection methods again to reconnect. + +## Parameters + +None + +## Signature + +```typescript +disconnect(): Promise +``` + +## Returns + +**Type:** `Promise` + +Returns a Promise that resolves when the disconnection is complete. + +## Examples + +### Basic disconnect + +```typescript +await client.disconnect() +console.log('Disconnected from SignalWire') +``` + +### Disconnect on page unload + +```typescript +window.addEventListener('beforeunload', async () => { + await client.disconnect() +}) +``` + +### Disconnect with cleanup + +```typescript +async function cleanup() { + console.log('Cleaning up...') + + await client.disconnect() + + console.log('Client disconnected') +} + +cleanup() +``` + +### Disconnect button + +```typescript +const disconnectButton = document.getElementById('disconnect-btn') + +disconnectButton.addEventListener('click', async () => { + try { + await client.disconnect() + disconnectButton.disabled = true + disconnectButton.textContent = 'Disconnected' + } catch (error) { + console.error('Disconnect failed:', error) + } +}) +``` + +### Reconnect after disconnect + +```typescript +await client.disconnect() +console.log('Disconnected') + +await client.online({ + incomingCallHandlers: { + onCallReceived: (call) => { + console.log('Incoming call:', call.id) + } + } +}) + +console.log('Reconnected') +``` + +### Disconnect with error handling + +```typescript +try { + await client.disconnect() + console.log('Successfully disconnected') +} catch (error) { + console.error('Error during disconnect:', error) +} +``` + +### Disconnect with timeout + +```typescript +const disconnectWithTimeout = async () => { + const timeoutPromise = new Promise((_, reject) => { + setTimeout(() => reject(new Error('Disconnect timeout')), 5000) + }) + + try { + await Promise.race([ + client.disconnect(), + timeoutPromise + ]) + console.log('Disconnected successfully') + } catch (error) { + console.error('Disconnect failed or timed out:', error) + } +} + +await disconnectWithTimeout() +``` + +### Disconnect multiple clients + +```typescript +const clients = [client1, client2, client3] + +await Promise.all( + clients.map(client => client.disconnect()) +) + +console.log('All clients disconnected') +``` + diff --git a/website/docs/signalwire-sdk/tech-ref/SignalWireClient/events.mdx b/website/docs/signalwire-sdk/tech-ref/SignalWireClient/events.mdx index cbf945847..be91f2b31 100644 --- a/website/docs/signalwire-sdk/tech-ref/SignalWireClient/events.mdx +++ b/website/docs/signalwire-sdk/tech-ref/SignalWireClient/events.mdx @@ -1 +1,396 @@ -# Events \ No newline at end of file +--- +title: Events +slug: /signalwire-client/events +--- + +import APIField from '@site/src/components/APIField'; + +The SignalWire Client emits various events that you can listen to for real-time updates about AI interactions and custom user events. + +## How it works + +The client uses an event-driven architecture where you can register listeners for specific event types. When events occur, your callback functions are invoked with relevant event data. + +## Event registration + +Use the standard `on()` method to register event listeners: + +```typescript +client.on('event_name', (params) => { +}) +``` + +## AI events + +The client emits several AI-related events for tracking AI agent interactions and responses. + +### ai.partial_result + +Emitted when the AI agent provides a partial result, similar to a typing indicator. This shows the AI is processing and generating a response. + + + The partial text result from the AI. + + + + Whether the response was interrupted (barged) by user input. + + +```typescript +client.on("ai.partial_result", (params) => { + console.log('AI is generating:', params.text) + console.log('Was barged:', params.barged) +}) +``` + +### ai.speech_detect + +Emitted when the AI detects speech from the user. This event indicates that the user is speaking. + + + The detected speech text with confidence information. + + + + The type of speech detection (e.g., 'normal', 'barged'). + + +```typescript +client.on("ai.speech_detect", (params) => { + const cleanText = params.text.replace(/\{confidence=[\d.]+\}/, "") + console.log('User said:', cleanText) + console.log('Detection type:', params.type) +}) +``` + +### ai.completion + +Emitted when the AI agent completes a response. This is the final response from the AI. + + + The complete response text from the AI. + + + + Whether the response was completed normally or was 'barged' (interrupted). + + +```typescript +client.on("ai.completion", (params) => { + console.log('AI completed:', params.text) + console.log('Was interrupted:', params.type === 'barged') +}) +``` + +### ai.response_utterance + +Emitted when the AI agent provides a spoken response utterance. This represents what the AI is actually saying. + + + The text of the AI's spoken response. + + +```typescript +client.on("ai.response_utterance", (params) => { + console.log('AI is saying:', params.utterance) +}) +``` + +## Custom user events + +### user_event + +Emitted for custom user-defined events. This allows you to send and receive custom application-specific events. + + + Custom event data defined by your application. + + +```typescript +client.on("user_event", (params) => { + console.log('User event received:', params) +}) +``` + +## Examples + +### Track AI conversation flow + +```typescript +client.on("ai.speech_detect", (params) => { + const cleanText = params.text.replace(/\{confidence=[\d.]+\}/, "") + console.log('User:', cleanText) + updateChatUI('user', cleanText) +}) + +client.on("ai.partial_result", (params) => { + console.log('AI typing...') + showTypingIndicator() +}) + +client.on("ai.completion", (params) => { + console.log('AI:', params.text) + hideTypingIndicator() + updateChatUI('ai', params.text) +}) +``` + +### Display AI responses in UI + +```typescript +const chatContainer = document.getElementById('chat-container') + +client.on("ai.response_utterance", (params) => { + const messageDiv = document.createElement('div') + messageDiv.className = 'ai-message' + messageDiv.textContent = params.utterance + chatContainer.appendChild(messageDiv) + chatContainer.scrollTop = chatContainer.scrollHeight +}) +``` + +### Handle barged interactions + +```typescript +client.on("ai.partial_result", (params) => { + if (params.barged) { + console.log('User interrupted AI') + markResponseAsInterrupted() + } +}) + +client.on("ai.completion", (params) => { + if (params.type === 'barged') { + console.log('Response was interrupted') + showInterruptionIndicator() + } +}) +``` + +### Log AI interactions + +```typescript +const conversationLog = [] + +client.on("ai.speech_detect", (params) => { + conversationLog.push({ + type: 'user', + text: params.text, + timestamp: new Date() + }) +}) + +client.on("ai.completion", (params) => { + conversationLog.push({ + type: 'ai', + text: params.text, + timestamp: new Date(), + interrupted: params.type === 'barged' + }) +}) + +console.log('Conversation history:', conversationLog) +``` + +### Real-time transcript + +```typescript +const transcriptContainer = document.getElementById('transcript') + +client.on("ai.speech_detect", (params) => { + const cleanText = params.text.replace(/\{confidence=[\d.]+\}/, "") + + const entry = document.createElement('div') + entry.className = 'transcript-entry user' + entry.innerHTML = ` + User: + ${cleanText} + ${new Date().toLocaleTimeString()} + ` + transcriptContainer.appendChild(entry) +}) + +client.on("ai.response_utterance", (params) => { + const entry = document.createElement('div') + entry.className = 'transcript-entry ai' + entry.innerHTML = ` + AI: + ${params.utterance} + ${new Date().toLocaleTimeString()} + ` + transcriptContainer.appendChild(entry) +}) +``` + +### Handle custom application events + +```typescript +client.on("user_event", (params) => { + switch (params.action) { + case 'button_clicked': + handleButtonClick(params.buttonId) + break + case 'form_submitted': + handleFormSubmission(params.formData) + break + case 'status_update': + updateStatus(params.status) + break + default: + console.log('Unknown user event:', params) + } +}) +``` + +### Typing indicator for AI + +```typescript +let typingIndicatorTimeout + +client.on("ai.partial_result", (params) => { + const indicator = document.getElementById('ai-typing') + indicator.style.display = 'block' + indicator.textContent = 'AI is thinking...' + + clearTimeout(typingIndicatorTimeout) +}) + +client.on("ai.completion", (params) => { + typingIndicatorTimeout = setTimeout(() => { + document.getElementById('ai-typing').style.display = 'none' + }, 500) +}) +``` + +### Speech confidence tracking + +```typescript +client.on("ai.speech_detect", (params) => { + const confidenceMatch = params.text.match(/\{confidence=([\d.]+)\}/) + + if (confidenceMatch) { + const confidence = parseFloat(confidenceMatch[1]) + console.log(`Speech confidence: ${(confidence * 100).toFixed(1)}%`) + + if (confidence < 0.5) { + console.warn('Low confidence detection') + } + } +}) +``` + +### Event analytics + +```typescript +const analytics = { + totalUserMessages: 0, + totalAIResponses: 0, + interruptedResponses: 0, + customEvents: 0 +} + +client.on("ai.speech_detect", () => { + analytics.totalUserMessages++ +}) + +client.on("ai.completion", (params) => { + analytics.totalAIResponses++ + if (params.type === 'barged') { + analytics.interruptedResponses++ + } +}) + +client.on("user_event", () => { + analytics.customEvents++ +}) + +console.log('Analytics:', analytics) +``` + +### Error handling in event listeners + +```typescript +client.on("ai.completion", (params) => { + try { + processAIResponse(params.text) + updateUI(params) + } catch (error) { + console.error('Error processing AI completion:', error) + showErrorMessage('Failed to process AI response') + } +}) + +client.on("user_event", (params) => { + try { + handleCustomEvent(params) + } catch (error) { + console.error('Error handling user event:', error) + } +}) +``` + +## Best practices + +### Remove event listeners + +Always remove event listeners when they're no longer needed to prevent memory leaks: + +```typescript +const handler = (params) => { + console.log('Event received:', params) +} + +client.on("ai.completion", handler) + +client.off("ai.completion", handler) +``` + +### Use event namespacing + +Group related event handlers for easier management: + +```typescript +class AIConversationManager { + constructor(client) { + this.client = client + this.setupEventListeners() + } + + setupEventListeners() { + this.client.on("ai.speech_detect", this.handleSpeech.bind(this)) + this.client.on("ai.completion", this.handleCompletion.bind(this)) + this.client.on("ai.partial_result", this.handlePartial.bind(this)) + } + + handleSpeech(params) { + } + + handleCompletion(params) { + } + + handlePartial(params) { + } + + cleanup() { + this.client.off("ai.speech_detect", this.handleSpeech) + this.client.off("ai.completion", this.handleCompletion) + this.client.off("ai.partial_result", this.handlePartial) + } +} +``` + +### Debounce rapid events + +For events that fire frequently, consider debouncing: + +```typescript +let partialResultTimeout + +client.on("ai.partial_result", (params) => { + clearTimeout(partialResultTimeout) + + partialResultTimeout = setTimeout(() => { + updatePartialResult(params.text) + }, 100) +}) +``` diff --git a/website/docs/signalwire-sdk/tech-ref/SignalWireClient/get-subscriber-info.mdx b/website/docs/signalwire-sdk/tech-ref/SignalWireClient/get-subscriber-info.mdx new file mode 100644 index 000000000..a31e2e062 --- /dev/null +++ b/website/docs/signalwire-sdk/tech-ref/SignalWireClient/get-subscriber-info.mdx @@ -0,0 +1,187 @@ +--- +title: getSubscriberInfo +slug: /signalwire-client/get-subscriber-info +--- + +import APIField from '@site/src/components/APIField'; + +Retrieves information about the current subscriber, including capabilities, permissions, and account details. + +## How it works + +The `getSubscriberInfo` method queries the SignalWire platform for detailed information about the authenticated subscriber. This includes what features the subscriber has access to, their permissions, and configuration settings. + +## Key concepts + +### Subscriber information + +The response typically includes: +- Subscriber ID +- Display name +- Capabilities and permissions +- Available features +- Account settings + +### Use cases + +Common uses for subscriber info: +- Checking available features before showing UI +- Validating permissions before actions +- Displaying user profile information +- Customizing UI based on capabilities + +## Parameters + +None + +## Signature + +```typescript +getSubscriberInfo(): Promise +``` + +## Returns + +**Type:** `Promise` + +Returns a Promise that resolves with subscriber information including capabilities and permissions. + +## Examples + +### Get basic subscriber info + +```typescript +const info = await client.getSubscriberInfo() + +console.log('Subscriber ID:', info.id) +console.log('Display name:', info.displayName) +``` + +### Check capabilities + +```typescript +const info = await client.getSubscriberInfo() + +if (info.capabilities.canMakeOutboundCalls) { + console.log('Outbound calling is enabled') +} else { + console.log('Outbound calling is disabled') +} +``` + +### Display user profile + +```typescript +async function showUserProfile() { + const info = await client.getSubscriberInfo() + + document.getElementById('user-name').textContent = info.displayName + document.getElementById('user-id').textContent = info.id + document.getElementById('user-email').textContent = info.email +} + +showUserProfile() +``` + +### Customize UI based on capabilities + +```typescript +const info = await client.getSubscriberInfo() + +const dialButton = document.getElementById('dial-btn') +dialButton.disabled = !info.capabilities.canMakeOutboundCalls + +const videoButton = document.getElementById('video-btn') +videoButton.disabled = !info.capabilities.hasVideoAccess +``` + +### Log subscriber details + +```typescript +const info = await client.getSubscriberInfo() + +console.log('Subscriber Info:', { + id: info.id, + name: info.displayName, + features: info.features, + permissions: info.permissions +}) +``` + +### Error handling + +```typescript +try { + const info = await client.getSubscriberInfo() + console.log('Retrieved subscriber info:', info) +} catch (error) { + console.error('Failed to get subscriber info:', error) +} +``` + +### Cache subscriber info + +```typescript +let cachedSubscriberInfo = null + +async function getSubscriberInfoCached() { + if (!cachedSubscriberInfo) { + cachedSubscriberInfo = await client.getSubscriberInfo() + } + return cachedSubscriberInfo +} + +const info = await getSubscriberInfoCached() +console.log('Subscriber info:', info) +``` + +### Validate permissions before action + +```typescript +async function makeVideoCall(to) { + const info = await client.getSubscriberInfo() + + if (!info.capabilities.hasVideoAccess) { + alert('Video calling is not available for your account') + return + } + + const callSession = await client.dial({ + to: to, + video: true + }) +} +``` + +### Show feature availability + +```typescript +async function updateFeatureList() { + const info = await client.getSubscriberInfo() + + const features = { + 'Outbound Calls': info.capabilities.canMakeOutboundCalls, + 'Video Calls': info.capabilities.hasVideoAccess, + 'Screen Sharing': info.capabilities.canShareScreen, + 'Recording': info.capabilities.canRecord + } + + for (const [feature, available] of Object.entries(features)) { + console.log(`${feature}: ${available ? 'Available' : 'Not available'}`) + } +} +``` + +### Refresh info on token update + +```typescript +async function refreshToken(newToken) { + await client.updateToken(newToken) + + const info = await client.getSubscriberInfo() + console.log('Updated subscriber info:', info) + + updateUIWithNewCapabilities(info) +} +``` + diff --git a/website/docs/signalwire-sdk/tech-ref/SignalWireClient/handle-push-notification.mdx b/website/docs/signalwire-sdk/tech-ref/SignalWireClient/handle-push-notification.mdx new file mode 100644 index 000000000..a9c1a4c3b --- /dev/null +++ b/website/docs/signalwire-sdk/tech-ref/SignalWireClient/handle-push-notification.mdx @@ -0,0 +1,207 @@ +--- +title: handlePushNotification +slug: /signalwire-client/handle-push-notification +--- + +import APIField from '@site/src/components/APIField'; + +Processes incoming push notifications for call or message events, allowing the app to respond appropriately when a notification is received. + +## How it works + +The `handlePushNotification` method processes push notification payloads received from the platform's notification system. It extracts call or message information and prepares the client to handle the incoming event. + +## Key concepts + +### Notification flow + +1. SignalWire sends push notification to device +2. Platform delivers notification to app +3. App calls `handlePushNotification` with payload +4. Client processes and triggers appropriate handlers + +### Platform integration + +This method integrates with: +- **iOS:** APNs notifications +- **Android:** FCM notifications +- **Web:** Service Worker notifications + +## Parameters + + + The push notification payload to process. + + + + The platform-specific notification data. + + + + Custom data payload from the notification. + + +## Signature + +```typescript +handlePushNotification(params: HandlePushNotificationParams): Promise +``` + +## Returns + +**Type:** `Promise` + +Returns a Promise that resolves with information about the processed notification. + +## Examples + +### Handle iOS push notification + +```typescript +async function onNotificationReceived(notification) { + const result = await client.handlePushNotification({ + notification: notification + }) + + console.log('Notification processed:', result) +} +``` + +### Handle Android FCM notification + +```typescript +messaging.onMessage(async (payload) => { + const result = await client.handlePushNotification({ + notification: payload + }) + + console.log('FCM notification handled:', result) +}) +``` + +### Handle notification when app is closed + +```typescript +async function handleBackgroundNotification(notificationData) { + await client.online({ + incomingCallHandlers: { + onCallReceived: (call) => { + console.log('Incoming call from notification') + showCallUI(call) + } + } + }) + + await client.handlePushNotification({ + notification: notificationData + }) +} +``` + +### Extract call information + +```typescript +async function processCallNotification(notification) { + const result = await client.handlePushNotification({ + notification: notification + }) + + if (result.type === 'call') { + console.log('Incoming call from:', result.from) + console.log('Call ID:', result.callId) + } +} +``` + +### Show notification UI + +```typescript +async function handleNotification(notification) { + const result = await client.handlePushNotification({ + notification: notification + }) + + if (result.type === 'call') { + showIncomingCallScreen({ + caller: result.from, + callId: result.callId + }) + } else if (result.type === 'message') { + showMessageNotification({ + message: result.content, + sender: result.from + }) + } +} +``` + +### Error handling + +```typescript +try { + const result = await client.handlePushNotification({ + notification: notificationPayload + }) + console.log('Notification handled successfully') +} catch (error) { + console.error('Failed to handle notification:', error) +} +``` + +### Handle notification with deep linking + +```typescript +async function handleNotificationTap(notification) { + const result = await client.handlePushNotification({ + notification: notification + }) + + if (result.type === 'call' && result.callId) { + window.location.href = `/call/${result.callId}` + } else if (result.type === 'message' && result.conversationId) { + window.location.href = `/conversation/${result.conversationId}` + } +} +``` + +### Log notification handling + +```typescript +async function logAndHandleNotification(notification) { + console.log('Received notification:', notification) + + const result = await client.handlePushNotification({ + notification: notification + }) + + console.log('Notification processing result:', { + type: result.type, + timestamp: new Date().toISOString() + }) +} +``` + +### Handle multiple notification types + +```typescript +async function processNotification(notification) { + const result = await client.handlePushNotification({ + notification: notification + }) + + switch (result.type) { + case 'call': + handleIncomingCall(result) + break + case 'message': + handleIncomingMessage(result) + break + case 'voicemail': + handleVoicemail(result) + break + default: + console.log('Unknown notification type:', result.type) + } +} +``` + diff --git a/website/docs/signalwire-sdk/tech-ref/SignalWireClient/index.mdx b/website/docs/signalwire-sdk/tech-ref/SignalWireClient/index.mdx index 304aad427..dd45e6829 100644 --- a/website/docs/signalwire-sdk/tech-ref/SignalWireClient/index.mdx +++ b/website/docs/signalwire-sdk/tech-ref/SignalWireClient/index.mdx @@ -1,2 +1,126 @@ -# SignalWireClient +--- +title: SignalWire Client +slug: /signalwire-client +--- +import APIField from '@site/src/components/APIField'; + +The SignalWire Client ([`SignalWireContract`](../Types#signalwirecontract)) is the main entry point for the SignalWire SDK. It provides methods for managing calls, conversations, device registration, and real-time communication. + +## Core methods + + + Initiates an outbound call to a destination. Returns a CallSession object for managing the call. + + + + Disconnects from the SignalWire network and cleans up all active resources. + + + + Brings the client online to receive incoming calls and messages. Requires callback handlers for incoming calls. + + + + Takes the client offline, preventing reception of new incoming calls and messages. + + + + Reattaches to an existing call session using a call ID. Useful for reconnecting after network interruptions. + + +## Device management + + + Registers a device for push notifications. Required for receiving calls when the app is in the background. + + + + Unregisters a device from push notifications. + + + + Processes incoming push notifications for call or message events. + + +## Token management + + + Retrieves information about the current subscriber, including capabilities and permissions. + + + + Updates the authentication token for the client session. Useful for token refresh scenarios. + + +## Address namespace + +The `address` namespace provides methods for managing and retrieving address information. + + + Retrieves a list of all available addresses. + + + + Retrieves information about a specific address by ID. + + + + Retrieves addresses associated with the current subscriber. + + +## Chat namespace + +The `chat` namespace provides methods for real-time chat functionality within calls. + + + Retrieves chat messages from a conversation. + + + + Joins a chat conversation. + + + + Sends a message in a chat conversation. + + + + Subscribes to real-time chat message events. + + +## Conversation namespace + +The `conversation` namespace provides methods for managing persistent conversations and messaging. + + + Retrieves messages from a specific conversation. + + + + Retrieves a list of conversations. + + + + Retrieves messages across conversations. + + + + Joins a conversation. + + + + Sends a message in a conversation. + + + + Subscribes to real-time conversation events. + + +## Methods + + + +## See also + +- [Events](/signalwire-client/events) - Available events for the SignalWire Client \ No newline at end of file diff --git a/website/docs/signalwire-sdk/tech-ref/SignalWireClient/offline.mdx b/website/docs/signalwire-sdk/tech-ref/SignalWireClient/offline.mdx new file mode 100644 index 000000000..7507213ea --- /dev/null +++ b/website/docs/signalwire-sdk/tech-ref/SignalWireClient/offline.mdx @@ -0,0 +1,202 @@ +--- +title: offline +slug: /signalwire-client/offline +--- + +import APIField from '@site/src/components/APIField'; + +Takes the client offline, preventing reception of new incoming calls and messages while maintaining the connection. + +## How it works + +The `offline` method changes the client's availability state to offline. Unlike `disconnect`, which terminates the connection entirely, `offline` keeps the connection active but stops receiving incoming calls and messages. + +## Key concepts + +### Offline vs disconnect + +- **offline():** Maintains connection but doesn't receive calls +- **disconnect():** Completely terminates the connection + +### Use cases + +Going offline is useful when: +- User is temporarily unavailable +- App moves to background +- Do Not Disturb mode is enabled +- Temporarily pausing call reception without full disconnect + +## Parameters + +None + +## Signature + +```typescript +offline(): Promise +``` + +## Returns + +**Type:** `Promise` + +Returns a Promise that resolves when the client is successfully offline. + +## Examples + +### Basic offline + +```typescript +await client.offline() +console.log('Client is now offline') +``` + +### Toggle availability + +```typescript +const toggleButton = document.getElementById('toggle-availability') +let isOnline = true + +toggleButton.addEventListener('click', async () => { + if (isOnline) { + await client.offline() + toggleButton.textContent = 'Go Online' + console.log('Now offline') + } else { + await client.online({ + incomingCallHandlers: { + onCallReceived: (call) => { + console.log('Incoming call:', call.id) + } + } + }) + toggleButton.textContent = 'Go Offline' + console.log('Now online') + } + + isOnline = !isOnline +}) +``` + +### Go offline during busy periods + +```typescript +async function startBusyMode() { + await client.offline() + console.log('Do Not Disturb enabled') +} + +async function endBusyMode() { + await client.online({ + incomingCallHandlers: { + onCallReceived: (call) => { + handleIncomingCall(call) + } + } + }) + console.log('Do Not Disturb disabled') +} +``` + +### Auto-offline on visibility change + +```typescript +document.addEventListener('visibilitychange', async () => { + if (document.hidden) { + await client.offline() + console.log('Page hidden, going offline') + } else { + await client.online({ + incomingCallHandlers: { + onCallReceived: (call) => { + console.log('Incoming call:', call.id) + } + } + }) + console.log('Page visible, going online') + } +}) +``` + +### Offline with status indicator + +```typescript +const statusIndicator = document.getElementById('status') + +async function goOffline() { + await client.offline() + statusIndicator.textContent = 'Offline' + statusIndicator.className = 'status-offline' +} + +async function goOnline() { + await client.online({ + incomingCallHandlers: { + onCallReceived: (call) => { + console.log('Incoming call:', call.id) + } + } + }) + statusIndicator.textContent = 'Online' + statusIndicator.className = 'status-online' +} +``` + +### Error handling + +```typescript +try { + await client.offline() + console.log('Successfully went offline') +} catch (error) { + console.error('Failed to go offline:', error) +} +``` + +### Scheduled offline periods + +```typescript +function scheduleOfflineHours() { + const now = new Date() + const hour = now.getHours() + + if (hour >= 22 || hour < 8) { + client.offline() + console.log('Outside business hours, going offline') + } else { + client.online({ + incomingCallHandlers: { + onCallReceived: (call) => { + console.log('Incoming call:', call.id) + } + } + }) + console.log('Business hours, going online') + } +} + +setInterval(scheduleOfflineHours, 60000) +``` + +### Temporary offline for maintenance + +```typescript +async function performMaintenance() { + console.log('Starting maintenance...') + + await client.offline() + + await updateClientSettings() + + await client.online({ + incomingCallHandlers: { + onCallReceived: (call) => { + console.log('Incoming call:', call.id) + } + } + }) + + console.log('Maintenance complete, back online') +} +``` + diff --git a/website/docs/signalwire-sdk/tech-ref/SignalWireClient/online.mdx b/website/docs/signalwire-sdk/tech-ref/SignalWireClient/online.mdx new file mode 100644 index 000000000..ee1f29281 --- /dev/null +++ b/website/docs/signalwire-sdk/tech-ref/SignalWireClient/online.mdx @@ -0,0 +1,202 @@ +--- +title: online +slug: /signalwire-client/online +--- + +import APIField from '@site/src/components/APIField'; + +Brings the client online to receive incoming calls and messages. This method registers callback handlers for incoming call events. + +## How it works + +The `online` method establishes the client's availability on the SignalWire network. Once online, the client can receive incoming calls and other real-time events through the provided callback handlers. + +## Key concepts + +### Availability state + +- **Offline:** Client cannot receive incoming calls or messages +- **Online:** Client is registered and can receive incoming calls and messages + +### Callback handlers + +You must provide handlers for incoming calls. These callbacks are invoked when events occur, allowing you to manage incoming calls appropriately. + +## Parameters + + + Configuration object containing callback handlers for incoming call events. + + + + Called when an incoming call is received. Provides a CallSession object for the incoming call. + + + + Called when an incoming call ends before being answered. + + +## Signature + +```typescript +online(incomingCallHandlers: OnlineParams): Promise +``` + +## Returns + +**Type:** `Promise` + +Returns a Promise that resolves when the client is successfully online. + +## Examples + +### Basic online setup + +```typescript +await client.online({ + incomingCallHandlers: { + onCallReceived: (call) => { + console.log('Incoming call from:', call.from) + call.answer() + } + } +}) + +console.log('Client is now online') +``` + +### Handle incoming calls with UI + +```typescript +await client.online({ + incomingCallHandlers: { + onCallReceived: (call) => { + const notification = document.getElementById('call-notification') + notification.textContent = `Incoming call from ${call.from}` + notification.style.display = 'block' + + const answerBtn = document.getElementById('answer-btn') + answerBtn.onclick = () => { + call.answer() + notification.style.display = 'none' + } + + const rejectBtn = document.getElementById('reject-btn') + rejectBtn.onclick = () => { + call.hangup() + notification.style.display = 'none' + } + } + } +}) +``` + +### Handle call ended events + +```typescript +await client.online({ + incomingCallHandlers: { + onCallReceived: (call) => { + console.log('Incoming call:', call.id) + }, + onCallEnded: (call) => { + console.log('Call ended:', call.id) + } + } +}) +``` + +### Auto-answer incoming calls + +```typescript +await client.online({ + incomingCallHandlers: { + onCallReceived: async (call) => { + console.log('Auto-answering call from:', call.from) + await call.answer() + } + } +}) +``` + +### Log incoming call details + +```typescript +await client.online({ + incomingCallHandlers: { + onCallReceived: (call) => { + console.log('Incoming call details:', { + id: call.id, + from: call.from, + to: call.to, + timestamp: new Date().toISOString() + }) + + call.answer() + } + } +}) +``` + +### Go online after authentication + +```typescript +async function initialize() { + const token = await getAuthToken() + const client = await SignalWire.Client({ token }) + + await client.online({ + incomingCallHandlers: { + onCallReceived: (call) => { + handleIncomingCall(call) + } + } + }) + + console.log('Client initialized and online') +} + +initialize() +``` + +### Toggle online/offline state + +```typescript +let isOnline = false + +async function toggleOnlineState() { + if (isOnline) { + await client.offline() + console.log('Now offline') + } else { + await client.online({ + incomingCallHandlers: { + onCallReceived: (call) => { + console.log('Incoming call:', call.id) + } + } + }) + console.log('Now online') + } + + isOnline = !isOnline +} +``` + +### Error handling + +```typescript +try { + await client.online({ + incomingCallHandlers: { + onCallReceived: (call) => { + console.log('Incoming call:', call.id) + } + } + }) + console.log('Successfully online') +} catch (error) { + console.error('Failed to go online:', error) +} +``` + diff --git a/website/docs/signalwire-sdk/tech-ref/SignalWireClient/reattach.mdx b/website/docs/signalwire-sdk/tech-ref/SignalWireClient/reattach.mdx new file mode 100644 index 000000000..24b8651eb --- /dev/null +++ b/website/docs/signalwire-sdk/tech-ref/SignalWireClient/reattach.mdx @@ -0,0 +1,226 @@ +--- +title: reattach +slug: /signalwire-client/reattach +--- + +import APIField from '@site/src/components/APIField'; + +Reattaches to an existing call session using a call ID. This is useful for reconnecting to a call after network interruptions or page refreshes. + +## How it works + +The `reattach` method allows you to reconnect to an active call that you were previously part of. By providing the call ID, you can restore the CallSession object and resume control of the call. + +## Key concepts + +### Call persistence + +Calls remain active on the SignalWire platform even if your client loses connection. Using `reattach` allows you to: +- Resume a call after network interruption +- Reconnect after page refresh +- Resume a call on a different device + +### Call ID storage + +To reattach to a call, you need to store the call ID. Common storage methods: +- Browser localStorage +- Session storage +- Server-side database +- URL parameters + +## Parameters + + + Configuration for reattaching to the call. + + + + The unique identifier of the call to reattach to. + + +## Signature + +```typescript +reattach(params: ReattachParams): Promise +``` + +## Returns + +**Type:** `Promise` + +Returns a Promise that resolves to a [CallSession](/call-session) object representing the reattached call. + +## Examples + +### Basic reattach + +```typescript +const callSession = await client.reattach({ + callId: 'call-id-here' +}) + +console.log('Reattached to call:', callSession.id) +``` + +### Reattach with localStorage + +```typescript +const storedCallId = localStorage.getItem('activeCallId') + +if (storedCallId) { + try { + const callSession = await client.reattach({ + callId: storedCallId + }) + console.log('Reconnected to call') + } catch (error) { + console.error('Failed to reattach:', error) + localStorage.removeItem('activeCallId') + } +} +``` + +### Store call ID on dial + +```typescript +const callSession = await client.dial({ + to: '+15551234567', + from: '+15559876543' +}) + +localStorage.setItem('activeCallId', callSession.id) + +callSession.on('call.ended', () => { + localStorage.removeItem('activeCallId') +}) +``` + +### Reattach on page load + +```typescript +window.addEventListener('load', async () => { + const activeCallId = localStorage.getItem('activeCallId') + + if (activeCallId) { + try { + const callSession = await client.reattach({ + callId: activeCallId + }) + + console.log('Reattached to active call') + setupCallUI(callSession) + } catch (error) { + console.log('No active call to reattach') + localStorage.removeItem('activeCallId') + } + } +}) +``` + +### Reattach with network recovery + +```typescript +let currentCallId = null + +window.addEventListener('online', async () => { + if (currentCallId) { + try { + const callSession = await client.reattach({ + callId: currentCallId + }) + console.log('Reconnected to call after network recovery') + } catch (error) { + console.error('Could not reattach to call:', error) + currentCallId = null + } + } +}) + +window.addEventListener('offline', () => { + console.log('Network connection lost') +}) +``` + +### Reattach with retry logic + +```typescript +async function reattachWithRetry(callId, maxRetries = 3) { + for (let i = 0; i < maxRetries; i++) { + try { + const callSession = await client.reattach({ callId }) + console.log('Successfully reattached') + return callSession + } catch (error) { + console.log(`Reattach attempt ${i + 1} failed`) + + if (i < maxRetries - 1) { + await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1))) + } + } + } + + throw new Error('Failed to reattach after multiple attempts') +} + +const callSession = await reattachWithRetry('call-id') +``` + +### Reattach button in UI + +```typescript +const reattachButton = document.getElementById('reattach-btn') +const callIdInput = document.getElementById('call-id-input') + +reattachButton.addEventListener('click', async () => { + const callId = callIdInput.value + + if (!callId) { + alert('Please enter a call ID') + return + } + + try { + const callSession = await client.reattach({ callId }) + console.log('Reattached to call:', callSession.id) + setupCallControls(callSession) + } catch (error) { + alert('Failed to reattach to call') + console.error(error) + } +}) +``` + +### Track call state after reattach + +```typescript +const callSession = await client.reattach({ + callId: storedCallId +}) + +console.log('Current call state:', callSession.state) + +callSession.on('call.state', (event) => { + console.log('Call state changed:', event.call.state) +}) +``` + +### Multiple device scenario + +```typescript +async function transferCallToDevice(callId) { + localStorage.setItem('transferredCallId', callId) + + window.location.href = '/call-page' +} + +async function receiveTransferredCall() { + const callId = localStorage.getItem('transferredCallId') + + if (callId) { + const callSession = await client.reattach({ callId }) + localStorage.removeItem('transferredCallId') + return callSession + } +} +``` + diff --git a/website/docs/signalwire-sdk/tech-ref/SignalWireClient/register-device.mdx b/website/docs/signalwire-sdk/tech-ref/SignalWireClient/register-device.mdx new file mode 100644 index 000000000..5896b3eb1 --- /dev/null +++ b/website/docs/signalwire-sdk/tech-ref/SignalWireClient/register-device.mdx @@ -0,0 +1,180 @@ +--- +title: registerDevice +slug: /signalwire-client/register-device +--- + +import APIField from '@site/src/components/APIField'; + +Registers a device for push notifications, enabling the client to receive calls when the app is in the background or closed. + +## How it works + +The `registerDevice` method registers your device with SignalWire's push notification system. Once registered, your device can receive notifications for incoming calls and messages even when the app is not actively running. + +## Key concepts + +### Platform-specific tokens + +Different platforms use different token formats: +- **iOS:** APNs device token +- **Android:** FCM registration token +- **Web:** Service Worker registration + +### Token lifecycle + +Device tokens can change and should be re-registered when: +- App is reinstalled +- Token expires or is refreshed +- User logs in on a new device + +## Parameters + + + Configuration for device registration. + + + + The platform-specific push notification token. + + + + The platform type for the device. + + + + Optional unique identifier for the device. + + +## Signature + +```typescript +registerDevice(params: RegisterDeviceParams): Promise +``` + +## Returns + +**Type:** `Promise` + +Returns a Promise that resolves when the device is successfully registered. + +## Examples + +### Register iOS device + +```typescript +const response = await client.registerDevice({ + deviceToken: 'apns-token-here', + platform: 'ios' +}) + +console.log('Device registered:', response) +``` + +### Register Android device + +```typescript +const response = await client.registerDevice({ + deviceToken: 'fcm-token-here', + platform: 'android' +}) + +console.log('Device registered:', response) +``` + +### Register with device ID + +```typescript +const deviceId = localStorage.getItem('deviceId') || crypto.randomUUID() +localStorage.setItem('deviceId', deviceId) + +await client.registerDevice({ + deviceToken: 'push-token-here', + platform: 'ios', + deviceId: deviceId +}) +``` + +### Register on app launch + +```typescript +async function initializeApp() { + const pushToken = await getPushNotificationToken() + + await client.registerDevice({ + deviceToken: pushToken, + platform: 'ios' + }) + + console.log('Device registered for push notifications') +} + +initializeApp() +``` + +### Handle token refresh + +```typescript +async function onTokenRefresh(newToken) { + try { + await client.registerDevice({ + deviceToken: newToken, + platform: 'android' + }) + console.log('Updated device token') + } catch (error) { + console.error('Failed to update device token:', error) + } +} +``` + +### Error handling + +```typescript +try { + await client.registerDevice({ + deviceToken: 'device-token', + platform: 'ios' + }) + console.log('Device registration successful') +} catch (error) { + console.error('Device registration failed:', error) +} +``` + +### Register with user preferences + +```typescript +async function registerWithPreferences(enablePush) { + if (!enablePush) { + console.log('Push notifications disabled by user') + return + } + + const token = await requestPushPermission() + + if (token) { + await client.registerDevice({ + deviceToken: token, + platform: 'ios' + }) + console.log('Push notifications enabled') + } +} +``` + +### Re-register after login + +```typescript +async function onUserLogin(userId) { + const deviceToken = await getDeviceToken() + + await client.registerDevice({ + deviceToken: deviceToken, + platform: 'android', + deviceId: `${userId}-${deviceToken.slice(0, 8)}` + }) + + console.log('Device registered for user:', userId) +} +``` + diff --git a/website/docs/signalwire-sdk/tech-ref/SignalWireClient/unregister-device.mdx b/website/docs/signalwire-sdk/tech-ref/SignalWireClient/unregister-device.mdx new file mode 100644 index 000000000..963ed1b7b --- /dev/null +++ b/website/docs/signalwire-sdk/tech-ref/SignalWireClient/unregister-device.mdx @@ -0,0 +1,181 @@ +--- +title: unregisterDevice +slug: /signalwire-client/unregister-device +--- + +import APIField from '@site/src/components/APIField'; + +Unregisters a device from push notifications, stopping the delivery of push notifications for calls and messages. + +## How it works + +The `unregisterDevice` method removes your device from SignalWire's push notification system. After unregistering, your device will no longer receive push notifications for incoming calls or messages. + +## Key concepts + +### When to unregister + +Unregister devices when: +- User logs out +- User disables push notifications in settings +- App is being uninstalled +- Device token is no longer valid + +### Re-registration + +If the user wants to receive notifications again, you'll need to call `registerDevice` with a new token. + +## Parameters + + + Configuration for device unregistration. + + + + The device token that was previously registered. + + + + Optional device identifier used during registration. + + +## Signature + +```typescript +unregisterDevice(params: UnregisterDeviceParams): Promise +``` + +## Returns + +**Type:** `Promise` + +Returns a Promise that resolves when the device is successfully unregistered. + +## Examples + +### Basic unregister + +```typescript +await client.unregisterDevice({ + deviceToken: 'device-token-here' +}) + +console.log('Device unregistered') +``` + +### Unregister on logout + +```typescript +async function logout() { + const deviceToken = localStorage.getItem('deviceToken') + + if (deviceToken) { + await client.unregisterDevice({ + deviceToken: deviceToken + }) + } + + await client.disconnect() + localStorage.clear() + + console.log('Logged out and device unregistered') +} +``` + +### Unregister with device ID + +```typescript +const deviceId = localStorage.getItem('deviceId') +const deviceToken = localStorage.getItem('deviceToken') + +await client.unregisterDevice({ + deviceToken: deviceToken, + deviceId: deviceId +}) +``` + +### Unregister when disabling notifications + +```typescript +async function togglePushNotifications(enabled) { + const deviceToken = localStorage.getItem('deviceToken') + + if (enabled) { + await client.registerDevice({ + deviceToken: deviceToken, + platform: 'ios' + }) + console.log('Push notifications enabled') + } else { + await client.unregisterDevice({ + deviceToken: deviceToken + }) + console.log('Push notifications disabled') + } +} +``` + +### Error handling + +```typescript +try { + await client.unregisterDevice({ + deviceToken: 'device-token' + }) + console.log('Successfully unregistered device') +} catch (error) { + console.error('Failed to unregister device:', error) +} +``` + +### Unregister on app uninstall + +```typescript +window.addEventListener('beforeunload', async () => { + const isAppUninstalling = checkIfUninstalling() + + if (isAppUninstalling) { + const deviceToken = localStorage.getItem('deviceToken') + + await client.unregisterDevice({ + deviceToken: deviceToken + }) + } +}) +``` + +### Cleanup multiple devices + +```typescript +async function cleanupOldDevices(deviceTokens) { + await Promise.all( + deviceTokens.map(token => + client.unregisterDevice({ deviceToken: token }) + ) + ) + + console.log('Cleaned up old device registrations') +} +``` + +### Unregister with UI toggle + +```typescript +const notificationToggle = document.getElementById('notification-toggle') + +notificationToggle.addEventListener('change', async (e) => { + const deviceToken = localStorage.getItem('deviceToken') + + if (e.target.checked) { + await client.registerDevice({ + deviceToken: deviceToken, + platform: 'android' + }) + } else { + await client.unregisterDevice({ + deviceToken: deviceToken + }) + } +}) +``` + diff --git a/website/docs/signalwire-sdk/tech-ref/SignalWireClient/update-token.mdx b/website/docs/signalwire-sdk/tech-ref/SignalWireClient/update-token.mdx new file mode 100644 index 000000000..7aa31294f --- /dev/null +++ b/website/docs/signalwire-sdk/tech-ref/SignalWireClient/update-token.mdx @@ -0,0 +1,247 @@ +--- +title: updateToken +slug: /signalwire-client/update-token +--- + +import APIField from '@site/src/components/APIField'; + +Updates the authentication token for the client session. This is useful for token refresh scenarios to maintain an active connection. + +## How it works + +The `updateToken` method replaces the current authentication token with a new one. This allows you to refresh expired tokens without disconnecting and reconnecting the client. + +## Key concepts + +### Token expiration + +JWT tokens have expiration times. Using `updateToken` allows: +- Seamless token refresh +- No interruption to active calls +- Continuous authentication + +### Token refresh strategy + +Common approaches: +- **Proactive refresh:** Refresh before expiration +- **Reactive refresh:** Refresh on authentication error +- **Scheduled refresh:** Refresh at regular intervals + +## Parameters + + + The new JWT authentication token to use. + + +## Signature + +```typescript +updateToken(token: string): Promise +``` + +## Returns + +**Type:** `Promise` + +Returns a Promise that resolves when the token is successfully updated. + +## Examples + +### Basic token update + +```typescript +const newToken = await fetchNewToken() + +await client.updateToken(newToken) +console.log('Token updated successfully') +``` + +### Proactive token refresh + +```typescript +async function refreshTokenBeforeExpiry() { + const tokenExpiryTime = getTokenExpiry() + const timeUntilExpiry = tokenExpiryTime - Date.now() + const refreshTime = timeUntilExpiry - (5 * 60 * 1000) + + setTimeout(async () => { + const newToken = await fetchNewToken() + await client.updateToken(newToken) + console.log('Token refreshed proactively') + + refreshTokenBeforeExpiry() + }, refreshTime) +} + +refreshTokenBeforeExpiry() +``` + +### Handle token expiration error + +```typescript +client.on('error', async (error) => { + if (error.code === 'TOKEN_EXPIRED') { + console.log('Token expired, refreshing...') + + const newToken = await fetchNewToken() + await client.updateToken(newToken) + + console.log('Token refreshed successfully') + } +}) +``` + +### Refresh on interval + +```typescript +setInterval(async () => { + try { + const newToken = await fetchNewToken() + await client.updateToken(newToken) + console.log('Token refreshed') + } catch (error) { + console.error('Token refresh failed:', error) + } +}, 30 * 60 * 1000) +``` + +### Update token with retry logic + +```typescript +async function updateTokenWithRetry(newToken, maxRetries = 3) { + for (let i = 0; i < maxRetries; i++) { + try { + await client.updateToken(newToken) + console.log('Token updated successfully') + return + } catch (error) { + console.log(`Token update attempt ${i + 1} failed`) + + if (i < maxRetries - 1) { + await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1))) + } + } + } + + throw new Error('Failed to update token after multiple attempts') +} +``` + +### Store and refresh token + +```typescript +async function refreshAndStoreToken() { + const newToken = await fetchNewToken() + + await client.updateToken(newToken) + + localStorage.setItem('authToken', newToken) + localStorage.setItem('tokenRefreshTime', Date.now().toString()) + + console.log('Token refreshed and stored') +} +``` + +### Error handling + +```typescript +try { + await client.updateToken(newToken) + console.log('Token updated') +} catch (error) { + console.error('Failed to update token:', error) + + await handleTokenUpdateFailure() +} +``` + +### Decode and validate token before update + +```typescript +function decodeJWT(token) { + const base64Url = token.split('.')[1] + const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/') + const jsonPayload = decodeURIComponent( + atob(base64).split('').map(c => + '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2) + ).join('') + ) + + return JSON.parse(jsonPayload) +} + +async function updateTokenSafely(newToken) { + const decoded = decodeJWT(newToken) + + if (decoded.exp * 1000 < Date.now()) { + console.error('Token is already expired') + return + } + + await client.updateToken(newToken) + console.log('Token updated, expires at:', new Date(decoded.exp * 1000)) +} +``` + +### Update token on user action + +```typescript +const refreshButton = document.getElementById('refresh-token-btn') + +refreshButton.addEventListener('click', async () => { + refreshButton.disabled = true + refreshButton.textContent = 'Refreshing...' + + try { + const newToken = await fetchNewToken() + await client.updateToken(newToken) + + refreshButton.textContent = 'Token Refreshed' + setTimeout(() => { + refreshButton.textContent = 'Refresh Token' + refreshButton.disabled = false + }, 2000) + } catch (error) { + refreshButton.textContent = 'Refresh Failed' + console.error(error) + } +}) +``` + +### Automatic background refresh + +```typescript +class TokenRefreshManager { + constructor(client, tokenFetcher) { + this.client = client + this.tokenFetcher = tokenFetcher + this.refreshInterval = null + } + + start() { + this.refreshInterval = setInterval(async () => { + await this.refresh() + }, 25 * 60 * 1000) + } + + stop() { + if (this.refreshInterval) { + clearInterval(this.refreshInterval) + } + } + + async refresh() { + try { + const newToken = await this.tokenFetcher() + await this.client.updateToken(newToken) + console.log('Token auto-refreshed') + } catch (error) { + console.error('Auto-refresh failed:', error) + } + } +} + +const refreshManager = new TokenRefreshManager(client, fetchNewToken) +refreshManager.start() +``` + diff --git a/website/docs/signalwire-sdk/tech-ref/authentication.mdx b/website/docs/signalwire-sdk/tech-ref/authentication.mdx index 1d59c4e70..652e129c0 100644 --- a/website/docs/signalwire-sdk/tech-ref/authentication.mdx +++ b/website/docs/signalwire-sdk/tech-ref/authentication.mdx @@ -5,59 +5,17 @@ sidebar_position: 1 # Authentication -The SignalWire SDK uses the same authentication methods as the REST API. +The SignalWire Client SDK is a browser-side library. The source code for all browser-side code is publicly available, so +we cannot use the same token authentication method as the REST API. +Authentication is scoped to [subscribers](./about_call_fabric#subscribers). +You can create subscribers either through the dashboard or through the REST API. +For temporary usage, you can create a guest token which creates a temporary subscriber +with limited permissions to access only the specified `allowed_address`. -### REST API Token Authentication +Depending on your use-case, several methods for authentication are available, which ensure security and scoped access. -You can obtain authentication tokens directly through the REST API. The following endpoints are available for token generation: - -import { TbApi } from "react-icons/tb"; - - -} - href="/rest/signalwire-rest/endpoints/fabric/guest-tokens-create" -> - Generate a limited-access token for guest access to specific Fabric addresses. - -} - href="/rest/signalwire-rest/endpoints/fabric/invite-tokens-create" -> - Generate a token to access resources associated with a specific subscriber on behalf of the subscriber. - -} - href="/rest/signalwire-rest/endpoints/fabric/subscriber-tokens-create" -> - Create a new subscriber and get their token in a single request. - - - -:::info -For browser-based applications, we recommend using the OAuth2 flow to -authenticate subscribers and obtain tokens. See -[Authenticate subscribers using OAuth2](#authenticate-subscribers-using-oauth2) below for details. -::: - -#### Using the Token - -The endpoints return a JSON object containing a `token` property. Use this token to initialize the [SignalWire Client][SignalWire Client]: - -```js -import { SignalWire } from "@signalwire/js"; - -const client = await SignalWire({ - token: "eyJhbGciOiJIUzI1NiIs..." -}); -``` - - -### Authenticate subscribers using OAuth2 +## 1. OAuth2 Subscriber Log-In When you create a Subscriber, you assign them a username (email) and a password. These credentials can be used authenticate the subscriber using the standard OAuth2 flow with PKCE. For OAuth2, you @@ -123,6 +81,11 @@ A complete example is presented below. Assuming that this page is [`npx serve`d](https://www.npmjs.com/package/serve) at the address `http://localhost:3000`, this script takes the subscriber through the OAuth2 login flow, and uses the access token received to fetch the subscriber's registration details from SignalWire. + + + + + {/* prettier-ignore */} ```html title="index.html" @@ -187,4 +150,118 @@ through the OAuth2 login flow, and uses the access token received to fetch the s -``` \ No newline at end of file +``` + + + + + +### When to use? + +Use this method if you're creating a new subscriber for each end-user of your application. With OAuth2, +they'll be able to log into your application and use your application's features without the need for a backend or +authentication logic on your part. + +import { TbApi } from "react-icons/tb"; + +{/* ## REST API Token Authentication + +You can obtain authentication tokens directly through the REST API. The following endpoints are available for token generation: + +:::info +For browser-based applications, we recommend using the OAuth2 flow to +authenticate subscribers and obtain tokens. See +[Authenticate subscribers using OAuth2](#authenticate-subscribers-using-oauth2) below for details. +::: */} + +## 2. Guest Token Authentication + +This method creates a temporary subscriber with limited permissions to access only the specified `allowed_addresses`. + + +} + href="/rest/signalwire-rest/endpoints/fabric/guest-tokens-create" +> + + + +### When to use? + +If you have a backend, and would like to generate a token for a specific resource without creating a new +permanent subscriber, this is the method to use. + +## 3. Subscriber Invite Token Authentication + +Use this method if you're creating a subscriber invite token for a specific subscriber. This is useful if you're creating a +temporary link for a user to access a specific resource. + +This method generates a token to access resources associated with a specific subscriber on behalf of the subscriber. + + +} + href="/rest/signalwire-rest/endpoints/fabric/invite-tokens-create" +/> + + +### When to use? + +Use this method if you already have a Subscriber, and would like to allow them to access resources; or if you would like to +access a resource on behalf of a Subscriber. + +## 4. Subscriber Token Authentication + +This method creates a new subscriber and returns their token. + + +} + href="/rest/signalwire-rest/endpoints/fabric/subscriber-tokens-create" +> + Create a new subscriber and get their token in a single request. + + + +### When to use? + +Use this method if you're creating a new subscriber and need to get their token in a single request. + +## 5. Exchange a C2C token for a Guest Token + +The [C2C widget](/tools/c2c) is a great tool to quickly embed resources into your website. When you +create a new C2C widget from the dashboard, you can assign a specific resource that can be accessed by it. +That C2C token can then be copied, and exchanged for a Guest Token to access the resource. This particular +method is great if you don't have a backend, and you need to access a particular resource. + +This particular REST API call can be performed from the browser. + + +} + href="/rest/signalwire-rest/endpoints/fabric/embeds-tokens-create" +> + Create a new subscriber and get their token in a single request. + + + +### When to use? + +Use this method if you don't have a backend, and you need to access a particular resource that is protected by a C2C token. + +## Using the Token + +The endpoints return a JSON object containing a `token` property. Use this token to initialize the [SignalWire Client][SignalWire Client]: + +```js +import { SignalWire } from "@signalwire/js"; + +const client = await SignalWire({ + token: "eyJhbGciOiJIUzI1NiIs..." +}); +``` + diff --git a/website/docs/signalwire-sdk/tech-ref/index.mdx b/website/docs/signalwire-sdk/tech-ref/index.mdx index 191c60dd7..d365f50be 100644 --- a/website/docs/signalwire-sdk/tech-ref/index.mdx +++ b/website/docs/signalwire-sdk/tech-ref/index.mdx @@ -4,3 +4,5 @@ sidebar_position: 0 --- # Overview + + diff --git a/website/src/components/APIField/index.tsx b/website/src/components/APIField/index.tsx new file mode 100644 index 000000000..2fc346905 --- /dev/null +++ b/website/src/components/APIField/index.tsx @@ -0,0 +1,142 @@ +import React, { ReactNode } from "react"; +import clsx from "clsx"; +import Link from "@docusaurus/Link"; +import styles from "./styles.module.css"; + +export interface APIFieldProps { + /** + * The name of the parameter/field + */ + name: string; + /** + * The type of the parameter (e.g., 'string', 'number', 'boolean', 'Promise') + * Supports markdown-style links: [TypeName](/path/to/type#anchor) + */ + type: string; + /** + * Whether the parameter is required + */ + required?: boolean; + /** + * Default value for the parameter + */ + default?: string; + /** + * Whether the parameter is deprecated + */ + deprecated?: boolean; + /** + * Description of the parameter (can include markdown/JSX) + */ + children?: ReactNode; +} + +export const APIField: React.FC = ({ + name, + type, + required = false, + default: defaultValue, + deprecated = false, + children, +}: APIFieldProps) => { + // Create a URL-friendly ID from the field name + const fieldId = `field-${name.toLowerCase().replace(/[^a-z0-9]+/g, "-")}`; + + const handleAnchorClick = (e: React.MouseEvent) => { + e.preventDefault(); + + // Update URL and jump to location (like header anchors) + window.location.hash = fieldId; + + // Copy to clipboard + navigator.clipboard + .writeText(window.location.href) + .then(() => { + // Optional: Show a toast/notification that link was copied + console.log("Link copied to clipboard"); + }) + .catch((err) => { + console.error("Failed to copy link:", err); + }); + }; + + // Parse markdown-style links in type string: [text](url) + const parseTypeLinks = (typeString: string) => { + const parts: (string | React.ReactElement)[] = []; + let lastIndex = 0; + const linkRegex = /\[([^\]]+)\]\(([^)]+)\)/g; + let match; + + while ((match = linkRegex.exec(typeString)) !== null) { + // Add text before the link + if (match.index > lastIndex) { + parts.push(typeString.substring(lastIndex, match.index)); + } + + // Add the link + parts.push( + + {match[1]} + , + ); + + lastIndex = match.index + match[0].length; + } + + // Add remaining text + if (lastIndex < typeString.length) { + parts.push(typeString.substring(lastIndex)); + } + + return parts.length > 0 ? parts : typeString; + }; + + return ( +
+
+
+ + + + + + + {name} + +
+ {parseTypeLinks(type)} + {required && required} + {deprecated && ( + + deprecated + + )} +
+ {defaultValue && ( +
+ Default:{" "} + {defaultValue} +
+ )} + {children &&
{children}
} +
+ ); +}; + +export default APIField; diff --git a/website/src/components/APIField/styles.module.css b/website/src/components/APIField/styles.module.css new file mode 100644 index 000000000..eeb68f47c --- /dev/null +++ b/website/src/components/APIField/styles.module.css @@ -0,0 +1,152 @@ +/** + * APIField component styles + * Inspired by Mintlify's ResponseField component + */ + +.apiField { + padding: 1rem 0; + border-bottom: 1px solid var(--ifm-color-emphasis-200); +} + +.apiField:last-child { + border-bottom: none; +} + +.deprecatedField { + opacity: 0.7; +} + +/* Field Header - contains name, type, and badges */ +.fieldHeader { + display: flex; + align-items: center; + gap: 0.75rem; + margin-bottom: 0.5rem; + flex-wrap: wrap; + position: relative; +} + +/* Field Name Container with anchor */ +.fieldNameContainer { + display: flex; + align-items: center; + gap: 0.5rem; + position: relative; +} + +/* Anchor Link */ +.fieldAnchor { + position: absolute; + left: -1.75rem; + display: flex; + align-items: center; + justify-content: center; + width: 1.25rem; + height: 1.25rem; + opacity: 0; + color: var(--ifm-color-primary); + transition: opacity 0.2s ease; + text-decoration: none; +} + +.fieldNameContainer:hover .fieldAnchor, +.fieldAnchor:focus { + opacity: 1; +} + +/* Field Name */ +.fieldName { + font-weight: 600; + font-size: 1rem; + color: var(--ifm-color-success); + font-family: var(--ifm-font-family-monospace); + cursor: pointer; +} + +/* Deprecated name with strikethrough */ +.deprecatedName { + text-decoration: line-through; + color: var(--ifm-color-emphasis-600); +} + +/* Field Type */ +.fieldType { + font-family: var(--ifm-font-family-monospace); + font-size: 0.875rem; + color: var(--ifm-color-emphasis-700); + background-color: var(--ifm-color-emphasis-100); + padding: 0.125rem 0.5rem; + border-radius: 4px; +} + +/* Badges (required, deprecated) */ +.fieldBadge { + font-size: 0.75rem; + font-weight: 600; + padding: 0.125rem 0.5rem; + border-radius: 4px; + text-transform: lowercase; + background-color: var(--ifm-color-danger-contrast-background); + color: var(--ifm-color-danger-contrast-foreground); +} + +.deprecatedBadge { + background-color: var(--ifm-color-warning-contrast-background); + color: var(--ifm-color-warning-contrast-foreground); +} + +/* Default Value */ +.fieldDefault { + margin-bottom: 0.5rem; + font-size: 0.875rem; + color: var(--ifm-color-emphasis-700); +} + +.defaultLabel { + font-weight: 600; + margin-right: 0.25rem; +} + +.fieldDefault code { + background-color: var(--ifm-color-emphasis-100); + padding: 0.125rem 0.375rem; + border-radius: 3px; + font-size: 0.875rem; +} + +/* Field Description */ +.fieldDescription { + color: var(--ifm-color-emphasis-800); + font-size: 0.9375rem; + line-height: 1.6; +} + +.fieldDescription p:first-child { + margin-top: 0; +} + +.fieldDescription p:last-child { + margin-bottom: 0; +} + +/* Dark mode adjustments */ +[data-theme="dark"] .fieldName { + color: var(--ifm-color-success-light); +} + +[data-theme="dark"] .fieldAnchor { + color: var(--ifm-color-primary); +} + +[data-theme="dark"] .fieldType { + background-color: var(--ifm-color-emphasis-200); + color: var(--ifm-color-emphasis-900); +} + +[data-theme="dark"] .fieldDefault code { + background-color: var(--ifm-color-emphasis-200); +} + +[data-theme="dark"] .deprecatedName { + color: var(--ifm-color-emphasis-500); +} diff --git a/website/src/components/Extras/Card/Card.tsx b/website/src/components/Extras/Card/Card.tsx index 4a5d03a45..661bd95d0 100644 --- a/website/src/components/Extras/Card/Card.tsx +++ b/website/src/components/Extras/Card/Card.tsx @@ -66,7 +66,7 @@ export function Card({ const Component = as || props.href != undefined ? Link : "div"; const isImageSrc: boolean = typeof icon === "string"; - const renderIcon: JSX.Element = ( + const renderIcon: ReactNode = ( <> {icon ? ( isImageSrc ? ( @@ -98,11 +98,7 @@ export function Card({ {title} {titleIcon ? titleIcon : null} )} - {description && ( -

- {description} -

- )} + {description &&

{description}

} {children} diff --git a/website/typesense.json b/website/typesense.json index d4b93293f..86f428402 100644 --- a/website/typesense.json +++ b/website/typesense.json @@ -542,6 +542,7 @@ } ], "separatorsToIndex": "_", + "symbols_to_index": ["<", ">"], "attributesForFaceting": ["language", "version", "type", "docusaurus_tag", "tags"], "attributesToRetrieve": [ "hierarchy", From 5253636d107e01e5fd89fbdadb6e2b073b1b5197 Mon Sep 17 00:00:00 2001 From: nirav Date: Wed, 15 Oct 2025 13:49:38 +0545 Subject: [PATCH 02/12] rename --- website/config/navbar.ts | 4 ++-- website/config/pluginsConfig/index.ts | 2 +- ...sdk-docs.ts => signalwire-client-sdk-docs.ts} | 8 ++++---- .../index.ts | 0 .../_category_.yaml | 2 +- .../about_call_fabric.mdx | 0 .../guides/_category_.yaml | 0 .../guides/calling.mdx | 0 .../guides/getting_started.mdx | 0 .../guides/index.mdx | 0 .../guides/migrating.mdx | 0 .../index.mdx | 16 ++++++++-------- .../tags.yml | 0 .../tech-ref/ClientFactory/_index.mdx} | 0 .../Address/address-get-address.mdx | 0 .../Address/address-get-addresses.mdx | 0 .../Address/address-get-my-addresses.mdx | 0 .../SignalWireClient/Chat/chat-get-messages.mdx | 0 .../tech-ref/SignalWireClient/Chat/chat-join.mdx | 0 .../SignalWireClient/Chat/chat-send-message.mdx | 0 .../SignalWireClient/Chat/chat-subscribe.mdx | 0 .../conversation-get-conversation-messages.mdx | 0 .../conversation-get-conversations.mdx | 0 .../Conversation/conversation-get-messages.mdx | 0 .../Conversation/conversation-join.mdx | 0 .../Conversation/conversation-send-message.mdx | 0 .../Conversation/conversation-subscribe.mdx | 0 .../tech-ref/SignalWireClient/dial.mdx | 0 .../tech-ref/SignalWireClient/disconnect.mdx | 0 .../tech-ref/SignalWireClient/events.mdx | 0 .../SignalWireClient/get-subscriber-info.mdx | 0 .../handle-push-notification.mdx | 0 .../tech-ref/SignalWireClient/index.mdx | 0 .../tech-ref/SignalWireClient/offline.mdx | 0 .../tech-ref/SignalWireClient/online.mdx | 0 .../tech-ref/SignalWireClient/reattach.mdx | 0 .../SignalWireClient/register-device.mdx | 0 .../SignalWireClient/unregister-device.mdx | 0 .../tech-ref/SignalWireClient/update-token.mdx | 0 .../tech-ref/Types/.gitignore | 0 .../tech-ref/Types/index.mdx | 0 .../tech-ref/Utilities/_index.mdx} | 0 .../tech-ref/authentication.mdx | 0 .../tech-ref/call-session/events.mdx | 8 ++++---- .../tech-ref/call-session/index.mdx | 8 ++++---- .../tech-ref/call-session/methods/answer.mdx | 0 .../tech-ref/call-session/methods/audio-mute.mdx | 0 .../call-session/methods/audio-unmute.mdx | 0 .../tech-ref/call-session/methods/deaf.mdx | 0 .../tech-ref/call-session/methods/destroy.mdx | 0 .../tech-ref/call-session/methods/end.mdx | 0 .../call-session/methods/get-layouts.mdx | 0 .../call-session/methods/get-member-overlay.mdx | 0 .../call-session/methods/get-members.mdx | 0 .../tech-ref/call-session/methods/hangup.mdx | 0 .../tech-ref/call-session/methods/hold.mdx | 0 .../tech-ref/call-session/methods/leave.mdx | 0 .../tech-ref/call-session/methods/lock.mdx | 0 .../tech-ref/call-session/methods/off.mdx | 0 .../tech-ref/call-session/methods/on.mdx | 0 .../tech-ref/call-session/methods/once.mdx | 0 .../methods/remove-all-listeners.mdx | 0 .../call-session/methods/remove-member.mdx | 0 .../call-session/methods/send-digits.mdx | 0 .../call-session/methods/set-audio-direction.mdx | 0 .../call-session/methods/set-audio-flags.mdx | 2 +- .../methods/set-input-sensitivity.mdx | 0 .../call-session/methods/set-input-volume.mdx | 0 .../tech-ref/call-session/methods/set-layout.mdx | 2 +- .../call-session/methods/set-local-stream.mdx | 0 .../call-session/methods/set-output-volume.mdx | 0 .../call-session/methods/set-positions.mdx | 2 +- .../call-session/methods/set-raised-hand.mdx | 0 .../call-session/methods/set-video-direction.mdx | 0 .../call-session/methods/start-screen-share.mdx | 2 +- .../tech-ref/call-session/methods/start.mdx | 0 .../tech-ref/call-session/methods/undeaf.mdx | 0 .../tech-ref/call-session/methods/unhold.mdx | 0 .../tech-ref/call-session/methods/unlock.mdx | 0 .../call-session/methods/update-camera.mdx | 0 .../call-session/methods/update-media.mdx | 0 .../call-session/methods/update-microphone.mdx | 0 .../call-session/methods/update-speaker.mdx | 0 .../tech-ref/call-session/methods/video-mute.mdx | 0 .../call-session/methods/video-unmute.mdx | 0 .../tech-ref/index.mdx | 0 .../tech-ref/notifications.mdx | 6 +++--- 87 files changed, 31 insertions(+), 31 deletions(-) rename website/config/pluginsConfig/{signalwire-sdk-docs.ts => signalwire-client-sdk-docs.ts} (84%) rename website/config/sidebarsConfig/{signalwire-sdk => signalwire-client-sdk}/index.ts (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/_category_.yaml (61%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/about_call_fabric.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/guides/_category_.yaml (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/guides/calling.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/guides/getting_started.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/guides/index.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/guides/migrating.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/index.mdx (90%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tags.yml (100%) rename website/docs/{signalwire-sdk/tech-ref/ClientFactory/index.mdx => signalwire-client-sdk/tech-ref/ClientFactory/_index.mdx} (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/SignalWireClient/Address/address-get-address.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/SignalWireClient/Address/address-get-addresses.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/SignalWireClient/Address/address-get-my-addresses.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/SignalWireClient/Chat/chat-get-messages.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/SignalWireClient/Chat/chat-join.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/SignalWireClient/Chat/chat-send-message.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/SignalWireClient/Chat/chat-subscribe.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/SignalWireClient/Conversation/conversation-get-conversation-messages.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/SignalWireClient/Conversation/conversation-get-conversations.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/SignalWireClient/Conversation/conversation-get-messages.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/SignalWireClient/Conversation/conversation-join.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/SignalWireClient/Conversation/conversation-send-message.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/SignalWireClient/Conversation/conversation-subscribe.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/SignalWireClient/dial.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/SignalWireClient/disconnect.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/SignalWireClient/events.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/SignalWireClient/get-subscriber-info.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/SignalWireClient/handle-push-notification.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/SignalWireClient/index.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/SignalWireClient/offline.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/SignalWireClient/online.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/SignalWireClient/reattach.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/SignalWireClient/register-device.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/SignalWireClient/unregister-device.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/SignalWireClient/update-token.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/Types/.gitignore (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/Types/index.mdx (100%) rename website/docs/{signalwire-sdk/tech-ref/Utilities/index.mdx => signalwire-client-sdk/tech-ref/Utilities/_index.mdx} (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/authentication.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/call-session/events.mdx (97%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/call-session/index.mdx (96%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/call-session/methods/answer.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/call-session/methods/audio-mute.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/call-session/methods/audio-unmute.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/call-session/methods/deaf.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/call-session/methods/destroy.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/call-session/methods/end.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/call-session/methods/get-layouts.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/call-session/methods/get-member-overlay.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/call-session/methods/get-members.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/call-session/methods/hangup.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/call-session/methods/hold.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/call-session/methods/leave.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/call-session/methods/lock.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/call-session/methods/off.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/call-session/methods/on.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/call-session/methods/once.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/call-session/methods/remove-all-listeners.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/call-session/methods/remove-member.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/call-session/methods/send-digits.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/call-session/methods/set-audio-direction.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/call-session/methods/set-audio-flags.mdx (97%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/call-session/methods/set-input-sensitivity.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/call-session/methods/set-input-volume.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/call-session/methods/set-layout.mdx (98%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/call-session/methods/set-local-stream.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/call-session/methods/set-output-volume.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/call-session/methods/set-positions.mdx (98%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/call-session/methods/set-raised-hand.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/call-session/methods/set-video-direction.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/call-session/methods/start-screen-share.mdx (97%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/call-session/methods/start.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/call-session/methods/undeaf.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/call-session/methods/unhold.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/call-session/methods/unlock.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/call-session/methods/update-camera.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/call-session/methods/update-media.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/call-session/methods/update-microphone.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/call-session/methods/update-speaker.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/call-session/methods/video-mute.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/call-session/methods/video-unmute.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/index.mdx (100%) rename website/docs/{signalwire-sdk => signalwire-client-sdk}/tech-ref/notifications.mdx (95%) diff --git a/website/config/navbar.ts b/website/config/navbar.ts index 5f76543aa..3029f2f7f 100644 --- a/website/config/navbar.ts +++ b/website/config/navbar.ts @@ -100,8 +100,8 @@ const navbar: NavbarItem[] = [ to: "/sdks/browser-sdk/", }, { - label: "SignalWire SDK", - to: "/sdks/signalwire-sdk/", + label: "SignalWire Client SDK", + to: "/sdks/signalwire-client-sdk/", }, { label: "RELAY Realtime Server SDK", diff --git a/website/config/pluginsConfig/index.ts b/website/config/pluginsConfig/index.ts index bee64d462..515d83a57 100644 --- a/website/config/pluginsConfig/index.ts +++ b/website/config/pluginsConfig/index.ts @@ -20,7 +20,7 @@ import { showcasePlugin } from "./guide-showcase"; import { llmsTxtPlugin } from "./docusaurus-plugin-llms-txt"; import { realtimeSdkPlugin } from "./realtime-sdk-docs"; import { browserSdkPlugin } from "./browser-sdk-docs"; -import { signalwireSdkPlugin } from "./signalwire-sdk-docs"; +import { signalwireSdkPlugin } from "./signalwire-client-sdk-docs"; import { ogImagesPlugin } from "../ogImages/index"; const plugins: PluginConfig[] = [ diff --git a/website/config/pluginsConfig/signalwire-sdk-docs.ts b/website/config/pluginsConfig/signalwire-client-sdk-docs.ts similarity index 84% rename from website/config/pluginsConfig/signalwire-sdk-docs.ts rename to website/config/pluginsConfig/signalwire-client-sdk-docs.ts index 4ab4775ee..72f6714b3 100644 --- a/website/config/pluginsConfig/signalwire-sdk-docs.ts +++ b/website/config/pluginsConfig/signalwire-client-sdk-docs.ts @@ -4,10 +4,10 @@ import sidebarGenerator from "../../src/plugins/SidebarGenerator"; export const signalwireSdkPlugin: PluginConfig = [ "@docusaurus/plugin-content-docs", { - id: "signalwire-sdk", - path: "docs/signalwire-sdk", - routeBasePath: "sdks/signalwire-sdk", - sidebarPath: require.resolve("../sidebarsConfig/signalwire-sdk/index.ts"), + id: "signalwire-client-sdk", + path: "docs/signalwire-client-sdk", + routeBasePath: "sdks/signalwire-client-sdk", + sidebarPath: require.resolve("../sidebarsConfig/signalwire-client-sdk/index.ts"), editUrl: "https://github.com/signalwire/docs/edit/main/website", editCurrentVersion: true, docItemComponent: "@theme/ApiItem", diff --git a/website/config/sidebarsConfig/signalwire-sdk/index.ts b/website/config/sidebarsConfig/signalwire-client-sdk/index.ts similarity index 100% rename from website/config/sidebarsConfig/signalwire-sdk/index.ts rename to website/config/sidebarsConfig/signalwire-client-sdk/index.ts diff --git a/website/docs/signalwire-sdk/_category_.yaml b/website/docs/signalwire-client-sdk/_category_.yaml similarity index 61% rename from website/docs/signalwire-sdk/_category_.yaml rename to website/docs/signalwire-client-sdk/_category_.yaml index 341b52727..605fc1370 100644 --- a/website/docs/signalwire-sdk/_category_.yaml +++ b/website/docs/signalwire-client-sdk/_category_.yaml @@ -1,4 +1,4 @@ -label: SignalWire SDK +label: SignalWire Client SDK position: 0 collapsed: true collapsible: false diff --git a/website/docs/signalwire-sdk/about_call_fabric.mdx b/website/docs/signalwire-client-sdk/about_call_fabric.mdx similarity index 100% rename from website/docs/signalwire-sdk/about_call_fabric.mdx rename to website/docs/signalwire-client-sdk/about_call_fabric.mdx diff --git a/website/docs/signalwire-sdk/guides/_category_.yaml b/website/docs/signalwire-client-sdk/guides/_category_.yaml similarity index 100% rename from website/docs/signalwire-sdk/guides/_category_.yaml rename to website/docs/signalwire-client-sdk/guides/_category_.yaml diff --git a/website/docs/signalwire-sdk/guides/calling.mdx b/website/docs/signalwire-client-sdk/guides/calling.mdx similarity index 100% rename from website/docs/signalwire-sdk/guides/calling.mdx rename to website/docs/signalwire-client-sdk/guides/calling.mdx diff --git a/website/docs/signalwire-sdk/guides/getting_started.mdx b/website/docs/signalwire-client-sdk/guides/getting_started.mdx similarity index 100% rename from website/docs/signalwire-sdk/guides/getting_started.mdx rename to website/docs/signalwire-client-sdk/guides/getting_started.mdx diff --git a/website/docs/signalwire-sdk/guides/index.mdx b/website/docs/signalwire-client-sdk/guides/index.mdx similarity index 100% rename from website/docs/signalwire-sdk/guides/index.mdx rename to website/docs/signalwire-client-sdk/guides/index.mdx diff --git a/website/docs/signalwire-sdk/guides/migrating.mdx b/website/docs/signalwire-client-sdk/guides/migrating.mdx similarity index 100% rename from website/docs/signalwire-sdk/guides/migrating.mdx rename to website/docs/signalwire-client-sdk/guides/migrating.mdx diff --git a/website/docs/signalwire-sdk/index.mdx b/website/docs/signalwire-client-sdk/index.mdx similarity index 90% rename from website/docs/signalwire-sdk/index.mdx rename to website/docs/signalwire-client-sdk/index.mdx index bb103058d..f6e6417aa 100644 --- a/website/docs/signalwire-sdk/index.mdx +++ b/website/docs/signalwire-client-sdk/index.mdx @@ -1,5 +1,5 @@ --- -title: "SignalWire SDK" +title: "SignalWire Client SDK" sidebar_position: 0 --- @@ -7,14 +7,14 @@ import { SiJavascript } from "react-icons/si"; import { MdCode, MdLibraryBooks } from "react-icons/md"; } installCommand="npm install @signalwire/client" - docsUrl="/sdks/signalwire-sdk/technical-reference" + docsUrl="/sdks/signalwire-client-sdk/technical-reference" status="beta" packages={[ { - githubUrl: "https://github.com/signalwire/signalwire-sdk", + githubUrl: "https://github.com/signalwire/signalwire-client-sdk", type: "npm", packageName: "@signalwire/client", } @@ -23,11 +23,11 @@ import { MdCode, MdLibraryBooks } from "react-icons/md"; # Overview -The SignalWire SDK is a JavaScript library that enables WebRTC-based voice, video, and chat applications directly in web browsers. Built on WebSocket architecture, it provides real-time communication capabilities without plugins or downloads. +The SignalWire Client SDK is a JavaScript library that enables WebRTC-based voice, video, and chat applications directly in web browsers. Built on WebSocket architecture, it provides real-time communication capabilities without plugins or downloads. :::info This SDK is meant to replace the [Browser SDK](/sdks/browser-sdk) -The SignalWire SDK should be used in place of the [Browser SDK](/sdks/browser-sdk) for all new projects. The new SDK maintains the API where possible while making architectural changes to support a unified way of interacting with SignalWire's services. +The SignalWire Client SDK should be used in place of the [Browser SDK](/sdks/browser-sdk) for all new projects. The new SDK maintains the API where possible while making architectural changes to support a unified way of interacting with SignalWire's services. ::: @@ -365,13 +365,13 @@ deviceWatcher.on("changed", (event) => { } /> } /> \ No newline at end of file diff --git a/website/docs/signalwire-sdk/tags.yml b/website/docs/signalwire-client-sdk/tags.yml similarity index 100% rename from website/docs/signalwire-sdk/tags.yml rename to website/docs/signalwire-client-sdk/tags.yml diff --git a/website/docs/signalwire-sdk/tech-ref/ClientFactory/index.mdx b/website/docs/signalwire-client-sdk/tech-ref/ClientFactory/_index.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/ClientFactory/index.mdx rename to website/docs/signalwire-client-sdk/tech-ref/ClientFactory/_index.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/SignalWireClient/Address/address-get-address.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Address/address-get-address.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/SignalWireClient/Address/address-get-address.mdx rename to website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Address/address-get-address.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/SignalWireClient/Address/address-get-addresses.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Address/address-get-addresses.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/SignalWireClient/Address/address-get-addresses.mdx rename to website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Address/address-get-addresses.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/SignalWireClient/Address/address-get-my-addresses.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Address/address-get-my-addresses.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/SignalWireClient/Address/address-get-my-addresses.mdx rename to website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Address/address-get-my-addresses.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/SignalWireClient/Chat/chat-get-messages.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Chat/chat-get-messages.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/SignalWireClient/Chat/chat-get-messages.mdx rename to website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Chat/chat-get-messages.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/SignalWireClient/Chat/chat-join.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Chat/chat-join.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/SignalWireClient/Chat/chat-join.mdx rename to website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Chat/chat-join.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/SignalWireClient/Chat/chat-send-message.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Chat/chat-send-message.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/SignalWireClient/Chat/chat-send-message.mdx rename to website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Chat/chat-send-message.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/SignalWireClient/Chat/chat-subscribe.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Chat/chat-subscribe.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/SignalWireClient/Chat/chat-subscribe.mdx rename to website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Chat/chat-subscribe.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/SignalWireClient/Conversation/conversation-get-conversation-messages.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Conversation/conversation-get-conversation-messages.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/SignalWireClient/Conversation/conversation-get-conversation-messages.mdx rename to website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Conversation/conversation-get-conversation-messages.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/SignalWireClient/Conversation/conversation-get-conversations.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Conversation/conversation-get-conversations.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/SignalWireClient/Conversation/conversation-get-conversations.mdx rename to website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Conversation/conversation-get-conversations.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/SignalWireClient/Conversation/conversation-get-messages.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Conversation/conversation-get-messages.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/SignalWireClient/Conversation/conversation-get-messages.mdx rename to website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Conversation/conversation-get-messages.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/SignalWireClient/Conversation/conversation-join.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Conversation/conversation-join.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/SignalWireClient/Conversation/conversation-join.mdx rename to website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Conversation/conversation-join.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/SignalWireClient/Conversation/conversation-send-message.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Conversation/conversation-send-message.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/SignalWireClient/Conversation/conversation-send-message.mdx rename to website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Conversation/conversation-send-message.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/SignalWireClient/Conversation/conversation-subscribe.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Conversation/conversation-subscribe.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/SignalWireClient/Conversation/conversation-subscribe.mdx rename to website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Conversation/conversation-subscribe.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/SignalWireClient/dial.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/dial.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/SignalWireClient/dial.mdx rename to website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/dial.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/SignalWireClient/disconnect.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/disconnect.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/SignalWireClient/disconnect.mdx rename to website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/disconnect.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/SignalWireClient/events.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/events.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/SignalWireClient/events.mdx rename to website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/events.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/SignalWireClient/get-subscriber-info.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/get-subscriber-info.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/SignalWireClient/get-subscriber-info.mdx rename to website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/get-subscriber-info.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/SignalWireClient/handle-push-notification.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/handle-push-notification.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/SignalWireClient/handle-push-notification.mdx rename to website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/handle-push-notification.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/SignalWireClient/index.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/index.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/SignalWireClient/index.mdx rename to website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/index.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/SignalWireClient/offline.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/offline.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/SignalWireClient/offline.mdx rename to website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/offline.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/SignalWireClient/online.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/online.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/SignalWireClient/online.mdx rename to website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/online.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/SignalWireClient/reattach.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/reattach.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/SignalWireClient/reattach.mdx rename to website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/reattach.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/SignalWireClient/register-device.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/register-device.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/SignalWireClient/register-device.mdx rename to website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/register-device.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/SignalWireClient/unregister-device.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/unregister-device.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/SignalWireClient/unregister-device.mdx rename to website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/unregister-device.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/SignalWireClient/update-token.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/update-token.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/SignalWireClient/update-token.mdx rename to website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/update-token.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/Types/.gitignore b/website/docs/signalwire-client-sdk/tech-ref/Types/.gitignore similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/Types/.gitignore rename to website/docs/signalwire-client-sdk/tech-ref/Types/.gitignore diff --git a/website/docs/signalwire-sdk/tech-ref/Types/index.mdx b/website/docs/signalwire-client-sdk/tech-ref/Types/index.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/Types/index.mdx rename to website/docs/signalwire-client-sdk/tech-ref/Types/index.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/Utilities/index.mdx b/website/docs/signalwire-client-sdk/tech-ref/Utilities/_index.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/Utilities/index.mdx rename to website/docs/signalwire-client-sdk/tech-ref/Utilities/_index.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/authentication.mdx b/website/docs/signalwire-client-sdk/tech-ref/authentication.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/authentication.mdx rename to website/docs/signalwire-client-sdk/tech-ref/authentication.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/call-session/events.mdx b/website/docs/signalwire-client-sdk/tech-ref/call-session/events.mdx similarity index 97% rename from website/docs/signalwire-sdk/tech-ref/call-session/events.mdx rename to website/docs/signalwire-client-sdk/tech-ref/call-session/events.mdx index b11884836..749195b6c 100644 --- a/website/docs/signalwire-sdk/tech-ref/call-session/events.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/call-session/events.mdx @@ -33,7 +33,7 @@ Fired when you successfully join a call. Your member ID. - + Your permissions and capabilities for this call session. @@ -404,7 +404,7 @@ call.on('room.left', (event) => { Fired when a new member joins the call. - + The member object with all properties. @@ -448,7 +448,7 @@ call.on('member.updated', (event) => { Fired when a member leaves the call. - + The member who left. @@ -661,7 +661,7 @@ call.on('member.updated.noiseSuppression', (event) => { Fired when the video layout changes. - + Layout object with name and layers. diff --git a/website/docs/signalwire-sdk/tech-ref/call-session/index.mdx b/website/docs/signalwire-client-sdk/tech-ref/call-session/index.mdx similarity index 96% rename from website/docs/signalwire-sdk/tech-ref/call-session/index.mdx rename to website/docs/signalwire-client-sdk/tech-ref/call-session/index.mdx index 1c1833612..f16822988 100644 --- a/website/docs/signalwire-sdk/tech-ref/call-session/index.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/call-session/index.mdx @@ -81,7 +81,7 @@ call.on('destroy', () => { ``` - + The full layout changed event object containing the current layout and all member positions. Updated automatically when the room layout changes. ```typescript @@ -100,7 +100,7 @@ call.on('destroy', () => { ``` - + Your current position within the video layout, or `undefined` if not found in any layer. ```typescript @@ -111,7 +111,7 @@ call.on('destroy', () => { ``` - + Defines what actions are allowed for this call session based on your role and permissions. ```typescript @@ -126,7 +126,7 @@ call.on('destroy', () => { ``` - + Array of active screen sharing sessions in this call. ```typescript diff --git a/website/docs/signalwire-sdk/tech-ref/call-session/methods/answer.mdx b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/answer.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/call-session/methods/answer.mdx rename to website/docs/signalwire-client-sdk/tech-ref/call-session/methods/answer.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/call-session/methods/audio-mute.mdx b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/audio-mute.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/call-session/methods/audio-mute.mdx rename to website/docs/signalwire-client-sdk/tech-ref/call-session/methods/audio-mute.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/call-session/methods/audio-unmute.mdx b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/audio-unmute.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/call-session/methods/audio-unmute.mdx rename to website/docs/signalwire-client-sdk/tech-ref/call-session/methods/audio-unmute.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/call-session/methods/deaf.mdx b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/deaf.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/call-session/methods/deaf.mdx rename to website/docs/signalwire-client-sdk/tech-ref/call-session/methods/deaf.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/call-session/methods/destroy.mdx b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/destroy.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/call-session/methods/destroy.mdx rename to website/docs/signalwire-client-sdk/tech-ref/call-session/methods/destroy.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/call-session/methods/end.mdx b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/end.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/call-session/methods/end.mdx rename to website/docs/signalwire-client-sdk/tech-ref/call-session/methods/end.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/call-session/methods/get-layouts.mdx b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/get-layouts.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/call-session/methods/get-layouts.mdx rename to website/docs/signalwire-client-sdk/tech-ref/call-session/methods/get-layouts.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/call-session/methods/get-member-overlay.mdx b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/get-member-overlay.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/call-session/methods/get-member-overlay.mdx rename to website/docs/signalwire-client-sdk/tech-ref/call-session/methods/get-member-overlay.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/call-session/methods/get-members.mdx b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/get-members.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/call-session/methods/get-members.mdx rename to website/docs/signalwire-client-sdk/tech-ref/call-session/methods/get-members.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/call-session/methods/hangup.mdx b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/hangup.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/call-session/methods/hangup.mdx rename to website/docs/signalwire-client-sdk/tech-ref/call-session/methods/hangup.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/call-session/methods/hold.mdx b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/hold.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/call-session/methods/hold.mdx rename to website/docs/signalwire-client-sdk/tech-ref/call-session/methods/hold.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/call-session/methods/leave.mdx b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/leave.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/call-session/methods/leave.mdx rename to website/docs/signalwire-client-sdk/tech-ref/call-session/methods/leave.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/call-session/methods/lock.mdx b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/lock.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/call-session/methods/lock.mdx rename to website/docs/signalwire-client-sdk/tech-ref/call-session/methods/lock.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/call-session/methods/off.mdx b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/off.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/call-session/methods/off.mdx rename to website/docs/signalwire-client-sdk/tech-ref/call-session/methods/off.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/call-session/methods/on.mdx b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/on.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/call-session/methods/on.mdx rename to website/docs/signalwire-client-sdk/tech-ref/call-session/methods/on.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/call-session/methods/once.mdx b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/once.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/call-session/methods/once.mdx rename to website/docs/signalwire-client-sdk/tech-ref/call-session/methods/once.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/call-session/methods/remove-all-listeners.mdx b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/remove-all-listeners.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/call-session/methods/remove-all-listeners.mdx rename to website/docs/signalwire-client-sdk/tech-ref/call-session/methods/remove-all-listeners.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/call-session/methods/remove-member.mdx b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/remove-member.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/call-session/methods/remove-member.mdx rename to website/docs/signalwire-client-sdk/tech-ref/call-session/methods/remove-member.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/call-session/methods/send-digits.mdx b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/send-digits.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/call-session/methods/send-digits.mdx rename to website/docs/signalwire-client-sdk/tech-ref/call-session/methods/send-digits.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/call-session/methods/set-audio-direction.mdx b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/set-audio-direction.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/call-session/methods/set-audio-direction.mdx rename to website/docs/signalwire-client-sdk/tech-ref/call-session/methods/set-audio-direction.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/call-session/methods/set-audio-flags.mdx b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/set-audio-flags.mdx similarity index 97% rename from website/docs/signalwire-sdk/tech-ref/call-session/methods/set-audio-flags.mdx rename to website/docs/signalwire-client-sdk/tech-ref/call-session/methods/set-audio-flags.mdx index 0c80b28dd..841292bf4 100644 --- a/website/docs/signalwire-sdk/tech-ref/call-session/methods/set-audio-flags.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/set-audio-flags.mdx @@ -15,7 +15,7 @@ setAudioFlags(params: SetAudioFlagsParams): Promise ## Parameters - + Audio processing configuration. diff --git a/website/docs/signalwire-sdk/tech-ref/call-session/methods/set-input-sensitivity.mdx b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/set-input-sensitivity.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/call-session/methods/set-input-sensitivity.mdx rename to website/docs/signalwire-client-sdk/tech-ref/call-session/methods/set-input-sensitivity.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/call-session/methods/set-input-volume.mdx b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/set-input-volume.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/call-session/methods/set-input-volume.mdx rename to website/docs/signalwire-client-sdk/tech-ref/call-session/methods/set-input-volume.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/call-session/methods/set-layout.mdx b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/set-layout.mdx similarity index 98% rename from website/docs/signalwire-sdk/tech-ref/call-session/methods/set-layout.mdx rename to website/docs/signalwire-client-sdk/tech-ref/call-session/methods/set-layout.mdx index eab45413c..27ee16b81 100644 --- a/website/docs/signalwire-sdk/tech-ref/call-session/methods/set-layout.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/set-layout.mdx @@ -23,7 +23,7 @@ setLayout(params: SetLayoutParams): Promise Name of the layout to apply (e.g., "grid-responsive", "2x2", "6x6"). - + Map of member IDs to specific positions in the layout. diff --git a/website/docs/signalwire-sdk/tech-ref/call-session/methods/set-local-stream.mdx b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/set-local-stream.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/call-session/methods/set-local-stream.mdx rename to website/docs/signalwire-client-sdk/tech-ref/call-session/methods/set-local-stream.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/call-session/methods/set-output-volume.mdx b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/set-output-volume.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/call-session/methods/set-output-volume.mdx rename to website/docs/signalwire-client-sdk/tech-ref/call-session/methods/set-output-volume.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/call-session/methods/set-positions.mdx b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/set-positions.mdx similarity index 98% rename from website/docs/signalwire-sdk/tech-ref/call-session/methods/set-positions.mdx rename to website/docs/signalwire-client-sdk/tech-ref/call-session/methods/set-positions.mdx index a13385ad0..9736c8eda 100644 --- a/website/docs/signalwire-sdk/tech-ref/call-session/methods/set-positions.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/set-positions.mdx @@ -19,7 +19,7 @@ setPositions(params: SetPositionsParams): Promise Positioning configuration object. - + Map of member IDs to their desired positions in the layout. diff --git a/website/docs/signalwire-sdk/tech-ref/call-session/methods/set-raised-hand.mdx b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/set-raised-hand.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/call-session/methods/set-raised-hand.mdx rename to website/docs/signalwire-client-sdk/tech-ref/call-session/methods/set-raised-hand.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/call-session/methods/set-video-direction.mdx b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/set-video-direction.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/call-session/methods/set-video-direction.mdx rename to website/docs/signalwire-client-sdk/tech-ref/call-session/methods/set-video-direction.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/call-session/methods/start-screen-share.mdx b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/start-screen-share.mdx similarity index 97% rename from website/docs/signalwire-sdk/tech-ref/call-session/methods/start-screen-share.mdx rename to website/docs/signalwire-client-sdk/tech-ref/call-session/methods/start-screen-share.mdx index 7aed58c78..3960a1e9d 100644 --- a/website/docs/signalwire-sdk/tech-ref/call-session/methods/start-screen-share.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/start-screen-share.mdx @@ -9,7 +9,7 @@ Starts screen sharing within the call, allowing you to share your screen, applic ## Parameters - + Screen share configuration options. diff --git a/website/docs/signalwire-sdk/tech-ref/call-session/methods/start.mdx b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/start.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/call-session/methods/start.mdx rename to website/docs/signalwire-client-sdk/tech-ref/call-session/methods/start.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/call-session/methods/undeaf.mdx b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/undeaf.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/call-session/methods/undeaf.mdx rename to website/docs/signalwire-client-sdk/tech-ref/call-session/methods/undeaf.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/call-session/methods/unhold.mdx b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/unhold.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/call-session/methods/unhold.mdx rename to website/docs/signalwire-client-sdk/tech-ref/call-session/methods/unhold.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/call-session/methods/unlock.mdx b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/unlock.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/call-session/methods/unlock.mdx rename to website/docs/signalwire-client-sdk/tech-ref/call-session/methods/unlock.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/call-session/methods/update-camera.mdx b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/update-camera.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/call-session/methods/update-camera.mdx rename to website/docs/signalwire-client-sdk/tech-ref/call-session/methods/update-camera.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/call-session/methods/update-media.mdx b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/update-media.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/call-session/methods/update-media.mdx rename to website/docs/signalwire-client-sdk/tech-ref/call-session/methods/update-media.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/call-session/methods/update-microphone.mdx b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/update-microphone.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/call-session/methods/update-microphone.mdx rename to website/docs/signalwire-client-sdk/tech-ref/call-session/methods/update-microphone.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/call-session/methods/update-speaker.mdx b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/update-speaker.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/call-session/methods/update-speaker.mdx rename to website/docs/signalwire-client-sdk/tech-ref/call-session/methods/update-speaker.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/call-session/methods/video-mute.mdx b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/video-mute.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/call-session/methods/video-mute.mdx rename to website/docs/signalwire-client-sdk/tech-ref/call-session/methods/video-mute.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/call-session/methods/video-unmute.mdx b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/video-unmute.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/call-session/methods/video-unmute.mdx rename to website/docs/signalwire-client-sdk/tech-ref/call-session/methods/video-unmute.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/index.mdx b/website/docs/signalwire-client-sdk/tech-ref/index.mdx similarity index 100% rename from website/docs/signalwire-sdk/tech-ref/index.mdx rename to website/docs/signalwire-client-sdk/tech-ref/index.mdx diff --git a/website/docs/signalwire-sdk/tech-ref/notifications.mdx b/website/docs/signalwire-client-sdk/tech-ref/notifications.mdx similarity index 95% rename from website/docs/signalwire-sdk/tech-ref/notifications.mdx rename to website/docs/signalwire-client-sdk/tech-ref/notifications.mdx index 71361c358..5f4ae781c 100644 --- a/website/docs/signalwire-sdk/tech-ref/notifications.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/notifications.mdx @@ -29,10 +29,10 @@ client.online({ When an incoming call arrives, the `websocket` handler receives a `callInvite` object containing: - `callInvite.invite.details` - caller information (name, number) -- `callInvite.invite.accept()` - accepts the call and returns a [`CallSession`](/sdks/signalwire-sdk/call-session) +- `callInvite.invite.accept()` - accepts the call and returns a [`CallSession`](/sdks/signalwire-client-sdk/call-session) - `callInvite.invite.reject()` - rejects the call -[`incomingCallHandlers`]: /sdks/signalwire-sdk/types#incomingcallhandlers +[`incomingCallHandlers`]: /sdks/signalwire-client-sdk/types#incomingcallhandlers ## Push Notifications @@ -42,7 +42,7 @@ The SignalWire platform can be configured to send push notifications to a subscr When the subscriber's device receives a push notification, it will make the device ring and forward the notification to your application. Your application should set up an audio/video link if the user accepts the call using the -[`handlePushNotification`](/sdks/signalwire-sdk/types#handlepushnotificationresult) method. +[`handlePushNotification`](/sdks/signalwire-client-sdk/types#handlepushnotificationresult) method. The push notification is only sent if there is no active WebSocket connection to the subscriber at that moment. ## Setup From f580d2bca1bf6584af8045691c0a7a90f9379fa8 Mon Sep 17 00:00:00 2001 From: nirav Date: Thu, 16 Oct 2025 00:10:58 +0545 Subject: [PATCH 03/12] edits --- .../about_call_fabric.mdx | 5 +- website/docs/signalwire-client-sdk/index.mdx | 411 +++++++----------- .../tech-ref/SignalWireClient/dial.mdx | 29 +- .../tech-ref/SignalWireClient/index.mdx | 4 +- .../tech-ref/Types/index.mdx | 1 + .../tech-ref/authentication.mdx | 96 ++-- .../signalwire-client-sdk/tech-ref/index.mdx | 2 + .../tech-ref/notifications.mdx | 20 +- 8 files changed, 243 insertions(+), 325 deletions(-) diff --git a/website/docs/signalwire-client-sdk/about_call_fabric.mdx b/website/docs/signalwire-client-sdk/about_call_fabric.mdx index 31476dbc5..c5ded82f3 100644 --- a/website/docs/signalwire-client-sdk/about_call_fabric.mdx +++ b/website/docs/signalwire-client-sdk/about_call_fabric.mdx @@ -57,8 +57,7 @@ per resource. They can be: To call a resource using the SDK, you can use the `client.dial()` method. ```javascript -const client = new SignalWireClient({ - project: 'YOUR_PROJECT_ID', +const client = await SignalWire({ token: 'YOUR_TOKEN', }); @@ -102,6 +101,8 @@ Subscribers can be created through the dashboard or through the REST API. /> +The [Authentication](/sdks/signalwire-client-sdk/tech-ref/authentication) section has more details about the authentication process. + :::info Looking for more details? The [Subscribers](/platform/call-fabric/subscribers) page has more details about the Subscribers resource. diff --git a/website/docs/signalwire-client-sdk/index.mdx b/website/docs/signalwire-client-sdk/index.mdx index f6e6417aa..2f5bc82a8 100644 --- a/website/docs/signalwire-client-sdk/index.mdx +++ b/website/docs/signalwire-client-sdk/index.mdx @@ -1,6 +1,8 @@ --- title: "SignalWire Client SDK" sidebar_position: 0 +sidebar_custom_props: + hideFromIndex: true --- import { SiJavascript } from "react-icons/si"; @@ -10,11 +12,11 @@ import { MdCode, MdLibraryBooks } from "react-icons/md"; title="SignalWire Client SDK" titleIcon={} installCommand="npm install @signalwire/client" - docsUrl="/sdks/signalwire-client-sdk/technical-reference" + docsUrl="/sdks/signalwire-client-sdk/" status="beta" packages={[ { - githubUrl: "https://github.com/signalwire/signalwire-client-sdk", + githubUrl: "https://github.com/signalwire/signalwire-sdk", type: "npm", packageName: "@signalwire/client", } @@ -31,12 +33,6 @@ The SignalWire Client SDK should be used in place of the [Browser SDK](/sdks/bro ::: -## How It Works - -The SDK operates through WebSocket connections that handle both method calls and real-time events. -When you call methods like `join()` or `publish()`, the SDK sends requests and returns promises. -Simultaneously, you can listen for real-time events like new members joining or messages arriving using the `.on()` method. - ## Getting Started @@ -57,307 +53,218 @@ Or include it via CDN: ### Set up a SWML resource -Create a SWML resource from the Dashboard to get started: +Create a [SWML Resource](/platform/call-fabric/resources/swml-scripts) from the Dashboard. ```yaml andJson version: 1.0.0 sections: main: - - answer: {} - - execute: - dest: play_music - params: - to_play: 'https://cdn.signalwire.com/swml/April_Kisses.mp3' - play_music: - - play: - url: "%{params.to_play}" + - play: "https://cdn.signalwire.com/swml/April_Kisses.mp3" ``` +Navigate to the newly created SWML Resource's `Addresses and Phone Numbers` tab, and note the Address UUID. + +### Create a Guest Token for that address + +Guest tokens are a simple way to get access to a specific address. + +```bash +curl -L -g 'https://{Your_Space_Name}.signalwire.com/api/fabric/guests/tokens' \ + -u ':' \ + -H 'Content-Type: application/json' \ + -H 'Accept: application/json' \ + -d '{"allowed_addresses":["
"]}' +``` + +The API credentials can be found in your dashboard. To learn how to find it, +see [Your Credentials](/platform/dashboard/getting-started/your-signalwire-api-space) page. + ### Test your setup Create a simple video room to test your setup: - + ```javascript -import { Video } from "@signalwire/js"; +import { SignalWire } from "@signalwire/client"; -// Join a video room -const roomSession = new Video.RoomSession({ - token: "your-room-token", // From your server - rootElement: document.getElementById("video-container") -}); +const $ = (x: string) => document.querySelector(x); -// Listen for events -roomSession.on("member.joined", (e) => { - console.log(`${e.member.name} joined the room`); -}); +$("#app")!.textContent = "Connecting ..."; -roomSession.on("room.joined", () => { - console.log("Successfully joined the room!"); +const client = await SignalWire({ + token: import.meta.env.VITE_TOKEN, }); -// Join the room -await roomSession.join(); +$("#app")!.innerHTML = ` +
+ + +
+
+`; + +const startButton = $("#startCall")!; +const hangupButton = $("#hangupCall")!; +const callContainer = $("#callContainer")!; + +startButton.addEventListener("click", async () => { + startButton.disabled = true; + startButton.textContent = "Connecting..."; + + const callSession = await client.dial({ + to: "/private/aprilkisses", + rootElement: callContainer, + }); + + callSession.on("call.joined", () => { + startButton.textContent = "Call Joined"; + hangupButton.disabled = false; + }); + + callSession.start(); + + hangupButton.addEventListener("click", () => { + callSession.hangup(); + hangupButton.disabled = true; + startButton.disabled = false; + startButton.textContent = "Start Call"; + }); +}); ```
- + ```html - - + + + + + SignalWire Call Example + + +
+ + +
+
+ + + + + ```
-Add this HTML element to your page: -```html -
-``` - - +### Walkthrough -## Usage Examples + + - - +After you get the token from the CURL request, you can initialize the client. ```javascript -import { Video } from "@signalwire/js"; - -const roomSession = new Video.RoomSession({ - token: "your-room-token", - rootElement: document.getElementById("video-container"), - video: true, - audio: true -}); - -// Handle room events -roomSession.on("room.joined", () => { - console.log("Joined the video room"); - - // Set up UI controls after joining - setupControls(); -}); - -roomSession.on("member.joined", (e) => { - console.log(`${e.member.name} joined`); -}); - -roomSession.on("member.left", (e) => { - console.log(`${e.member.name} left`); -}); - -// Detect when members are talking -roomSession.on("member.talking", (e) => { - if (e.member.id === roomSession.memberId) { - console.log("You are talking"); - } else { - console.log(`${e.member.name} is talking`); - } +const client = await SignalWire({ + token: "", }); - -// Join the room -await roomSession.join(); - -// Example: Set up media controls for your UI -function setupControls() { - // Toggle camera on button click - document.getElementById("cameraBtn").onclick = async () => { - if (roomSession.localVideo.active) { - await roomSession.videoMute(); - console.log("Camera muted"); - } else { - await roomSession.videoUnmute(); - console.log("Camera unmuted"); - } - }; - - // Toggle microphone on button click - document.getElementById("micBtn").onclick = async () => { - if (roomSession.localAudio.active) { - await roomSession.audioMute(); - console.log("Microphone muted"); - } else { - await roomSession.audioUnmute(); - console.log("Microphone unmuted"); - } - }; -} ``` - - - -```javascript -import { Chat } from "@signalwire/js"; - -const chatClient = new Chat.Client({ - token: "your-chat-token" -}); +It is recommended to keep a persistent client instance for the lifetime of the application. -// Subscribe to channels -await chatClient.subscribe(["general", "support"]); + + -// Listen for messages -chatClient.on("message", (message) => { - console.log(`${message.member.name}: ${message.content}`); - // Add your custom logic to display messages in your UI -}); +When the user clicks the `Start Call` button, you can use the `dial` method to dial the call. -// Listen for member events -chatClient.on("member.joined", (member) => { - console.log(`${member.name} joined the channel`); +```javascript +const callSession = await client.dial({ + to: "
", + rootElement: $("#callContainer")!, }); +``` -chatClient.on("member.left", (member) => { - console.log(`${member.name} left the channel`); -}); +The `callSession` object is a [CallSession](/sdks/signalwire-client-sdk/call-session) object +that you can use to manage the call. -// Send messages -await chatClient.publish({ - channel: "general", - content: "Hello everyone!" -}); +After the call session is created, you can use the `start` method to start the call. -// Send with metadata -await chatClient.publish({ - channel: "general", - content: "Check out this image!", - meta: { - image_url: "https://example.com/image.jpg", - message_type: "image" - } -}); +```javascript +callSession.start(); ``` - - + -```javascript -import { PubSub } from "@signalwire/js"; + -const pubSubClient = new PubSub.Client({ - token: "your-pubsub-token" -}); +After the call session is created, you can use the `on` method to listen for events. -// Subscribe to channels -await pubSubClient.subscribe(["notifications", "alerts"]); - -// Listen for messages -pubSubClient.on("message", (message) => { - console.log(`Channel: ${message.channel}`); - console.log(`Content:`, message.content); - - // Handle different message types - if (message.channel === "alerts") { - console.log("Alert received:", message.content); - // Add your custom logic to show alerts in your UI - } +```javascript +callSession.on("call.joined", () => { + console.log("Call joined"); + // UI Updates }); +``` -// Publish messages -await pubSubClient.publish({ - channel: "notifications", - content: { - type: "user_action", - user_id: "123", - action: "button_click", - timestamp: Date.now() - } -}); + -// Publish with metadata -await pubSubClient.publish({ - channel: "alerts", - content: "System maintenance in 30 minutes", - meta: { - priority: "high", - category: "maintenance" - } -}); -``` + - - +You can use the `hangup` method to hangup the call. ```javascript -import { WebRTC, Video } from "@signalwire/js"; - -// Check browser support -if (WebRTC.supportsGetUserMedia()) { - console.log("Browser supports getUserMedia"); -} - -if (WebRTC.supportsGetDisplayMedia()) { - console.log("Browser supports screen sharing"); -} - -// Get available devices -const cameras = await WebRTC.getCameraDevices(); -const microphones = await WebRTC.getMicrophoneDevices(); -const speakers = await WebRTC.getSpeakerDevices(); - -console.log("Cameras:", cameras); -console.log("Microphones:", microphones); -console.log("Speakers:", speakers); - -// Get user media with SignalWire WebRTC helper -const stream = await WebRTC.getUserMedia({ - video: { - width: { ideal: 1280 }, - height: { ideal: 720 }, - frameRate: { ideal: 30 } - }, - audio: { - echoCancellation: true, - noiseSuppression: true - } -}); +callSession.hangup(); +``` -// Use custom stream in video room -const roomSession = new Video.RoomSession({ - token: "your-room-token", - rootElement: document.getElementById("video"), - localStream: stream -}); + -// Device monitoring -const deviceWatcher = await WebRTC.createDeviceWatcher(); -deviceWatcher.on("changed", (event) => { - console.log("Devices changed:", event.changes); - // Add your custom logic to handle device changes -}); -``` + - - + ## Explore the SDK diff --git a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/dial.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/dial.mdx index d9b5308fb..54f3b82c7 100644 --- a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/dial.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/dial.mdx @@ -5,27 +5,13 @@ slug: /signalwire-client/dial import APIField from '@site/src/components/APIField'; -Initiates an outbound call to a destination and returns a CallSession object for managing the active call. +Initiates an outbound call to a destination and returns a [CallSession](../call-session) object for managing the active call. -## How it works - -The `dial` method establishes a new call connection to the specified destination. Once the call is initiated, you receive a `CallSession` object that you can use to control the call, manage participants, and listen to call events. - -## Key concepts - -### Destination types - -You can dial different types of destinations: -- **Phone numbers:** E.164 formatted numbers (e.g., `+15551234567`) -- **SIP addresses:** Direct SIP endpoint addresses -- **Resource names:** Named resources configured in your SignalWire space - -### Call lifecycle +## Signature -1. Call is initiated with `dial()` -2. `CallSession` is returned immediately -3. Call progresses through states: `connecting`, `ringing`, `answered` -4. Listen to events to track call state changes +```typescript +dial(params: DialParams): Promise +``` ## Parameters @@ -97,11 +83,6 @@ You can dial different types of destinations: Call address ID matching one of the subscriber's addresses to attribute conversation API events in the INVITE. -## Signature - -```typescript -dial(params: DialParams): Promise -``` ## Returns diff --git a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/index.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/index.mdx index dd45e6829..1c11b8264 100644 --- a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/index.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/index.mdx @@ -9,8 +9,8 @@ The SignalWire Client ([`SignalWireContract`](../Types#signalwirecontract)) is t ## Core methods - - Initiates an outbound call to a destination. Returns a CallSession object for managing the call. + + Initiates an outbound call to a destination. Returns a [CallSession](call-session) object for managing the call. diff --git a/website/docs/signalwire-client-sdk/tech-ref/Types/index.mdx b/website/docs/signalwire-client-sdk/tech-ref/Types/index.mdx index d1967388d..dc149b668 100644 --- a/website/docs/signalwire-client-sdk/tech-ref/Types/index.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/Types/index.mdx @@ -1,6 +1,7 @@ --- title: API Types slug: /types +sidebar_position: 10 --- diff --git a/website/docs/signalwire-client-sdk/tech-ref/authentication.mdx b/website/docs/signalwire-client-sdk/tech-ref/authentication.mdx index 652e129c0..7217c6825 100644 --- a/website/docs/signalwire-client-sdk/tech-ref/authentication.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/authentication.mdx @@ -6,25 +6,23 @@ sidebar_position: 1 # Authentication The SignalWire Client SDK is a browser-side library. The source code for all browser-side code is publicly available, so -we cannot use the same token authentication method as the REST API. +we cannot use the same token authentication method as the REST API. -Authentication is scoped to [subscribers](./about_call_fabric#subscribers). +Authentication is scoped to [subscribers](./about_call_fabric#subscribers). You can create subscribers either through the dashboard or through the REST API. -For temporary usage, you can create a guest token which creates a temporary subscriber +For temporary usage, you can create a guest token which creates a temporary subscriber with limited permissions to access only the specified `allowed_address`. Depending on your use-case, several methods for authentication are available, which ensure security and scoped access. -## 1. OAuth2 Subscriber Log-In +## OAuth2 Subscriber Log-In -When you create a Subscriber, you assign them a username (email) and a password. These credentials +When you create a Subscriber, either through the REST API or the Dashboard, +you assign them a username (email) and a password. These credentials can be used authenticate the subscriber using the standard OAuth2 flow with PKCE. For OAuth2, you can use tools like [odic-client-ts](https://github.com/authts/oidc-client-ts) or [react-native-app-auth](https://github.com/FormidableLabs/react-native-app-auth). -You can also use this [node.js script](https://github.com/signalwire-community/react/tree/main/scripts/refresh-fabric-tokens) -from [SignalWire Community](https://github.com/signalwire-community) to get a token for a subscriber. - :::info Currently, the only way to get a client ID for the OAuth2 flow is through the SignalWire Support team. ::: @@ -81,18 +79,22 @@ A complete example is presented below. Assuming that this page is [`npx serve`d](https://www.npmjs.com/package/serve) at the address `http://localhost:3000`, this script takes the subscriber through the OAuth2 login flow, and uses the access token received to fetch the subscriber's registration details from SignalWire. - {/* prettier-ignore */} + ```html title="index.html" @@ -110,7 +112,8 @@ through the OAuth2 login flow, and uses the access token received to fetch the s authority: "x", // dummy authority metadata: { issuer: "https://id.fabric.signalwire.com/", - authorization_endpoint: "https://id.fabric.signalwire.com/login/oauth/authorize", + authorization_endpoint: + "https://id.fabric.signalwire.com/login/oauth/authorize", token_endpoint: "https://id.fabric.signalwire.com/oauth/token", }, client_id: "", @@ -143,7 +146,7 @@ through the OAuth2 login flow, and uses the access token received to fetch the s } // We want to check if the user was redirected here from the subscriber login flow, - // or if the came here directly from the browser. If the user came directly from the + // or if the came here directly from the browser. If the user came directly from the // browser, we show a Login button. If they were redirected here, we allow oidc-client-ts // to finish the flow and get the access token. checkForRedirect(); @@ -156,25 +159,25 @@ through the OAuth2 login flow, and uses the access token received to fetch the s -### When to use? +#### When to use? -Use this method if you're creating a new subscriber for each end-user of your application. With OAuth2, +Use this method if you're creating a new subscriber for each end-user of your application. With OAuth2, they'll be able to log into your application and use your application's features without the need for a backend or authentication logic on your part. import { TbApi } from "react-icons/tb"; -{/* ## REST API Token Authentication +## REST API Token Authentication You can obtain authentication tokens directly through the REST API. The following endpoints are available for token generation: :::info -For browser-based applications, we recommend using the OAuth2 flow to -authenticate subscribers and obtain tokens. See +For browser-based applications, we recommend using the OAuth2 flow to +authenticate subscribers and obtain tokens. See [Authenticate subscribers using OAuth2](#authenticate-subscribers-using-oauth2) below for details. -::: */} +::: -## 2. Guest Token Authentication +### Guest Token Authentication This method creates a temporary subscriber with limited permissions to access only the specified `allowed_addresses`. @@ -183,16 +186,15 @@ This method creates a temporary subscriber with limited permissions to access on title="Create a Guest Token" icon={} href="/rest/signalwire-rest/endpoints/fabric/guest-tokens-create" -> - +/> -### When to use? +#### When to use? -If you have a backend, and would like to generate a token for a specific resource without creating a new -permanent subscriber, this is the method to use. +If you have a backend, and would like to generate a token for a specific resource without creating a new +permanent subscriber, this is the method to use. -## 3. Subscriber Invite Token Authentication +### Subscriber Invite Token Authentication Use this method if you're creating a subscriber invite token for a specific subscriber. This is useful if you're creating a temporary link for a user to access a specific resource. @@ -207,12 +209,12 @@ This method generates a token to access resources associated with a specific sub /> -### When to use? +#### When to use? -Use this method if you already have a Subscriber, and would like to allow them to access resources; or if you would like to -access a resource on behalf of a Subscriber. +Use this method if you already have a Subscriber, and would like to allow them to access resources; or if you would like to +access a resource on behalf of a Subscriber. -## 4. Subscriber Token Authentication +### Subscriber Token Authentication This method creates a new subscriber and returns their token. @@ -226,16 +228,16 @@ This method creates a new subscriber and returns their token. -### When to use? +#### When to use? Use this method if you're creating a new subscriber and need to get their token in a single request. -## 5. Exchange a C2C token for a Guest Token +### Exchange a C2C token for a Guest Token -The [C2C widget](/tools/c2c) is a great tool to quickly embed resources into your website. When you -create a new C2C widget from the dashboard, you can assign a specific resource that can be accessed by it. +The [C2C widget](/tools/c2c) is a great tool to quickly embed resources into your website. When you +create a new C2C widget from the dashboard, you can assign a specific resource that can be accessed by it. That C2C token can then be copied, and exchanged for a Guest Token to access the resource. This particular -method is great if you don't have a backend, and you need to access a particular resource. +method is great if you don't have a backend, and you need to access a particular resource. This particular REST API call can be performed from the browser. @@ -249,19 +251,31 @@ This particular REST API call can be performed from the browser. -### When to use? +#### When to use? + +Use this method if you don't have a backend, and you need to access a particular resource that is protected by a C2C token. The C2C +token is assumed to be public, so it is not necessary to authenticate it. -Use this method if you don't have a backend, and you need to access a particular resource that is protected by a C2C token. +## Choosing the right authentication method + +Use this comparison table to select the authentication method that best fits your use case: + +| Authentication Method | Needs Backend | Handles User Auth | Access Scope | Duration | Best For | +| ---------------------------- | ------------- | -------------------------- | --------------------------------- | ------------- | --------------------------------------------------------------------------- | +| **OAuth2 Subscriber Log-In** | No | Yes | Multiple resources per subscriber | Persistent | Production apps where each end-user needs their own subscriber account | +| **Guest Token** | Yes | No | Selected resources | Temporary | Quick access to a specific resource without creating a permanent subscriber | +| **Subscriber Invite Token** | Yes | No | Multiple resources per subscriber | Session-based | Accessing resources on behalf of an existing subscriber | +| **Subscriber Token** | Yes | No | Multiple resources per subscriber | Session-based | Creating new subscribers and getting tokens in a single request | +| **C2C Token Exchange** | No |C2C tokens are assumed public|Single resource | Temporary | Simple static websites needing access to a specific resource | ## Using the Token -The endpoints return a JSON object containing a `token` property. Use this token to initialize the [SignalWire Client][SignalWire Client]: +After you have received the access token by an authentication method, you can use that token to initialize the [SignalWire Client](./signalwire-client): ```js -import { SignalWire } from "@signalwire/js"; +import { SignalWire } from "@signalwire/client"; const client = await SignalWire({ - token: "eyJhbGciOiJIUzI1NiIs..." + token: "eyJhbGciOiJIUzI1NiIs...", }); ``` - diff --git a/website/docs/signalwire-client-sdk/tech-ref/index.mdx b/website/docs/signalwire-client-sdk/tech-ref/index.mdx index d365f50be..1da52df3e 100644 --- a/website/docs/signalwire-client-sdk/tech-ref/index.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/index.mdx @@ -1,6 +1,8 @@ --- slug: /technical-reference sidebar_position: 0 +sidebar_custom_props: + hideFromIndex: true --- # Overview diff --git a/website/docs/signalwire-client-sdk/tech-ref/notifications.mdx b/website/docs/signalwire-client-sdk/tech-ref/notifications.mdx index 5f4ae781c..6624c99f4 100644 --- a/website/docs/signalwire-client-sdk/tech-ref/notifications.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/notifications.mdx @@ -6,7 +6,17 @@ sidebar_position: 2 # Notifications If you've initialized the SignalWire Client with a subscriber token, you can opt into receiving notifications -whenever that subscriber gets a call or a message. +whenever that subscriber address is called. There are two ways to push the notifications to your application: + +- WebSocket Notifications +- Push Notifications + +The WebSocket notifications are delivered over the WebSocket connection while your application is active, and you have +called the [`online()`](/sdks/signalwire-client-sdk/signalwire-client/online) method to opt into receiving them. + +Push Notifications are delivered to your application regardless of whether it's active or not. It can be +used to push VoIP calls to your application when it's in the background. + ## WebSocket Notifications @@ -19,8 +29,10 @@ client.online({ const callerName = callInvite.invite.details?.caller_id_name; const callerNumber = callInvite.invite.details?.caller_id_number; + // to accept: const roomSession = await callInvite.invite.accept(params); + // to reject: callInvite.invite.reject(); }, }, @@ -28,7 +40,7 @@ client.online({ ``` When an incoming call arrives, the `websocket` handler receives a `callInvite` object containing: -- `callInvite.invite.details` - caller information (name, number) +- `callInvite.invite.details` - call and caller information [IncomingInvite](/sdks/signalwire-client-sdk/types#incominginvite) - `callInvite.invite.accept()` - accepts the call and returns a [`CallSession`](/sdks/signalwire-client-sdk/call-session) - `callInvite.invite.reject()` - rejects the call @@ -45,7 +57,7 @@ Your application should set up an audio/video link if the user accepts the call [`handlePushNotification`](/sdks/signalwire-client-sdk/types#handlepushnotificationresult) method. The push notification is only sent if there is no active WebSocket connection to the subscriber at that moment. -## Setup +### Setup To be able to receive push notifications to your applications, device-specific configurations are required. @@ -64,7 +76,7 @@ with the certificates you want. ::: -## Handling Push Notifications +### Handling Push Notifications The push notification is a compressed and encrypted JSON payload which contains the caller details and the invitation that needs to be passed into the SDK to join the call. From 9345034393ba61b063313d3beca6d683888e0a44 Mon Sep 17 00:00:00 2001 From: nirav Date: Thu, 16 Oct 2025 01:27:53 +0545 Subject: [PATCH 04/12] push notification details --- .../about_call_fabric.mdx | 25 +- .../Address/address-get-address.mdx | 121 +------- .../Address/address-get-addresses.mdx | 154 +++------ .../Address/address-get-my-addresses.mdx | 155 +-------- .../Chat/chat-get-messages.mdx | 122 -------- .../SignalWireClient/Chat/chat-join.mdx | 118 ------- .../Chat/chat-send-message.mdx | 157 ---------- .../SignalWireClient/Chat/chat-subscribe.mdx | 170 +--------- ...conversation-get-conversation-messages.mdx | 133 -------- .../conversation-get-conversations.mdx | 154 --------- .../conversation-get-messages.mdx | 154 --------- .../Conversation/conversation-join.mdx | 121 -------- .../conversation-send-message.mdx | 207 +------------ .../Conversation/conversation-subscribe.mdx | 194 ------------ .../tech-ref/SignalWireClient/dial.mdx | 5 - .../tech-ref/SignalWireClient/disconnect.mdx | 121 +------- .../tech-ref/SignalWireClient/events.mdx | 293 ++---------------- .../SignalWireClient/get-subscriber-info.mdx | 160 +--------- .../handle-push-notification.mdx | 241 ++++++-------- .../tech-ref/SignalWireClient/offline.mdx | 22 +- .../tech-ref/SignalWireClient/online.mdx | 143 --------- .../tech-ref/SignalWireClient/reattach.mdx | 179 ----------- .../SignalWireClient/register-device.mdx | 178 ++++------- .../SignalWireClient/unregister-device.mdx | 156 ++-------- 24 files changed, 296 insertions(+), 3187 deletions(-) diff --git a/website/docs/signalwire-client-sdk/about_call_fabric.mdx b/website/docs/signalwire-client-sdk/about_call_fabric.mdx index c5ded82f3..7a7d0f089 100644 --- a/website/docs/signalwire-client-sdk/about_call_fabric.mdx +++ b/website/docs/signalwire-client-sdk/about_call_fabric.mdx @@ -107,4 +107,27 @@ The [Authentication](/sdks/signalwire-client-sdk/tech-ref/authentication) sectio The [Subscribers](/platform/call-fabric/subscribers) page has more details about the Subscribers resource. -::: \ No newline at end of file +::: + +## The Conversation API + +In the context of the Call Fabric, a conversation is a record of a Subscriber's interaction with another resource. + +The Conversation API, then, is the history of the interactions of a Subscriber with other addresses, +It blends logs, events, and chats into a single personalized history. +A Subscriber's interaction with an address, even an address shared between many, +can be specific to only them. + +From the Subscriber's perspective, the chronological list of conversations will completely capture their +history of interactions with all other addresses. This makes making Subscriber-centric applications extremely simple. + +{/* ref: https://github.com/signalwire/cloud-product/issues/8857 */} + +The Conversation API allows you to interact with those conversations in two very important ways: + +1. a real-time inbound stream of conversations which can be subscribed to +2. a Chat API which allows you to send, receive, and subscribe to messages + +Based on your program requirements, you can use one or both of these APIs. + + diff --git a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Address/address-get-address.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Address/address-get-address.mdx index ac5b678f7..77be9a12d 100644 --- a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Address/address-get-address.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Address/address-get-address.mdx @@ -5,31 +5,10 @@ slug: /signalwire-client/address-get-address import APIField from '@site/src/components/APIField'; -Retrieves detailed information about a specific address by its ID. +Retrieves detailed information about a specific address by its ID or by its name. -## How it works - -The `address.getAddress` method queries the SignalWire platform for details about a single address. This provides comprehensive information about a specific phone number or endpoint. - -## Key concepts - -### Address details - -The response includes: -- Address ID -- Phone number or SIP address -- Address type -- Display name -- Capabilities -- Configuration settings - -### Use cases - -Retrieve specific address details for: -- Displaying address information -- Validating address capabilities -- Configuration management -- Call routing decisions +The response includes the preview URL, display name, resource type, available channels, lock status, and timestamps. +For full type information, see the [`GetAddressResult`](../Types#getaddressresult) type. ## Parameters @@ -45,7 +24,7 @@ address.getAddress(addressId: string): Promise ## Returns -**Type:** `Promise` +**Type:** `Promise<`[`GetAddressResult`](../Types#getaddressresult)`>` Returns a Promise that resolves with detailed information about the requested address. @@ -54,99 +33,17 @@ Returns a Promise that resolves with detailed information about the requested ad ### Get address by ID ```typescript -const address = await client.address.getAddress('address-id-here') +const address = await client.address.getAddress({id: 'address-id-here'}) console.log('Address:', address.number) console.log('Type:', address.type) ``` -### Display address details - -```typescript -const address = await client.address.getAddress('address-id-here') - -console.log('Address Details:') -console.log(' Number:', address.number) -console.log(' Name:', address.name) -console.log(' Type:', address.type) -console.log(' Capabilities:', address.capabilities) -``` - -### Validate address capabilities - -```typescript -const address = await client.address.getAddress('address-id-here') - -if (address.capabilities.canReceiveCalls) { - console.log('This address can receive incoming calls') -} - -if (address.capabilities.canSendSMS) { - console.log('This address can send SMS messages') -} -``` - -### Error handling - -```typescript -try { - const address = await client.address.getAddress('address-id') - console.log('Address found:', address.number) -} catch (error) { - console.error('Address not found:', error) -} -``` - -### Get address from selection - -```typescript -const selectedId = document.getElementById('address-select').value - -if (selectedId) { - const address = await client.address.getAddress(selectedId) - - document.getElementById('address-display').textContent = address.number - document.getElementById('address-type').textContent = address.type -} -``` - -### Check if address exists - -```typescript -async function addressExists(addressId) { - try { - await client.address.getAddress(addressId) - return true - } catch (error) { - return false - } -} - -const exists = await addressExists('address-id') -console.log('Address exists:', exists) -``` - -### Compare addresses +### Get address by name ```typescript -const address1 = await client.address.getAddress('address-1-id') -const address2 = await client.address.getAddress('address-2-id') +const address = await client.address.getAddress({name: 'address-name-here'}) -console.log('Comparing addresses:') -console.log(`Address 1: ${address1.number} (${address1.type})`) -console.log(`Address 2: ${address2.number} (${address2.type})`) -``` - -### Use address for calling - -```typescript -const address = await client.address.getAddress('my-address-id') - -const callSession = await client.dial({ - to: '+15551234567', - from: address.number -}) - -console.log('Calling from:', address.number) +console.log('Address:', address.number) +console.log('Type:', address.type) ``` - diff --git a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Address/address-get-addresses.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Address/address-get-addresses.mdx index 9a651b7d6..9c5309cc3 100644 --- a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Address/address-get-addresses.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Address/address-get-addresses.mdx @@ -1,49 +1,52 @@ --- title: address.getAddresses slug: /signalwire-client/address-get-addresses +description: Retrieve and filter addresses available in your SignalWire space with pagination and sorting options. --- import APIField from '@site/src/components/APIField'; -Retrieves a list of all available addresses in your SignalWire space. +Retrieves addresses available to the current subscriber with filtering, sorting, and pagination. -## How it works - -The `address.getAddresses` method queries the SignalWire platform for all addresses configured in your space. Addresses represent phone numbers, SIP endpoints, or other communication identifiers. - -## Key concepts +## Signature -### Address types +```typescript +address.getAddresses(params?: GetAddressesParams): Promise +``` -Addresses can include: -- Phone numbers (PSTN) -- SIP addresses -- WebRTC endpoints -- Resource names +## Parameters -### Use cases + + Optional configuration for filtering and sorting addresses. + -Common uses: -- Displaying available phone numbers -- Selecting caller ID for outbound calls -- Managing address inventory -- Routing configuration + + Filter addresses by type (e.g., phone number, SIP endpoint). + -## Parameters + + Filter addresses by their display name. + -None + + Number of results to return per page. + -## Signature + + Field to sort results by. Can be either `'name'` or `'created_at'`. + -```typescript -address.getAddresses(): Promise -``` + + Sort order. Can be either `'asc'` (ascending) or `'desc'` (descending). + ## Returns -**Type:** `Promise` +**Type:** `Promise>` + +Returns a Promise that resolves with a paginated list of address details. -Returns a Promise that resolves with a list of all available addresses. +For full type information, see the [`GetAddressesResult`](../Types#getaddressesresult) type. ## Examples @@ -52,102 +55,33 @@ Returns a Promise that resolves with a list of all available addresses. ```typescript const result = await client.address.getAddresses() -console.log('Available addresses:', result.addresses) +console.log('Available addresses:', result.data) ``` -### Display addresses in UI +### Filter and sort addresses ```typescript -const result = await client.address.getAddresses() - -const select = document.getElementById('caller-id-select') - -result.addresses.forEach(address => { - const option = document.createElement('option') - option.value = address.id - option.textContent = address.number - select.appendChild(option) +const result = await client.address.getAddresses({ + displayName: 'Support', + sortBy: 'created_at', + sortOrder: 'desc', + pageSize: 10 }) -``` -### Filter phone numbers - -```typescript -const result = await client.address.getAddresses() - -const phoneNumbers = result.addresses.filter( - addr => addr.type === 'phone_number' -) - -console.log('Phone numbers:', phoneNumbers) +console.log('Recent support addresses:', result.data) ``` -### List addresses with details +### Navigate paginated results ```typescript -const result = await client.address.getAddresses() - -result.addresses.forEach(address => { - console.log(`ID: ${address.id}`) - console.log(`Number: ${address.number}`) - console.log(`Type: ${address.type}`) - console.log(`Name: ${address.name}`) - console.log('---') +const result = await client.address.getAddresses({ + pageSize: 10 }) -``` -### Error handling +console.log('First page:', result.data) -```typescript -try { - const result = await client.address.getAddresses() - console.log('Retrieved addresses:', result.addresses.length) -} catch (error) { - console.error('Failed to get addresses:', error) -} -``` - -### Cache addresses - -```typescript -let cachedAddresses = null - -async function getAddressesCached() { - if (!cachedAddresses) { - const result = await client.address.getAddresses() - cachedAddresses = result.addresses - } - return cachedAddresses +if (result.hasNext) { + const nextPage = await result.nextPage() + console.log('Second page:', nextPage.data) } - -const addresses = await getAddressesCached() -``` - -### Select default address - -```typescript -const result = await client.address.getAddresses() - -const defaultAddress = result.addresses.find( - addr => addr.isDefault -) || result.addresses[0] - -console.log('Default address:', defaultAddress.number) ``` - -### Group addresses by type - -```typescript -const result = await client.address.getAddresses() - -const grouped = result.addresses.reduce((acc, addr) => { - if (!acc[addr.type]) { - acc[addr.type] = [] - } - acc[addr.type].push(addr) - return acc -}, {}) - -console.log('Addresses by type:', grouped) -``` - diff --git a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Address/address-get-my-addresses.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Address/address-get-my-addresses.mdx index f819f7feb..4f0be6dbf 100644 --- a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Address/address-get-my-addresses.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Address/address-get-my-addresses.mdx @@ -5,28 +5,8 @@ slug: /signalwire-client/address-get-my-addresses import APIField from '@site/src/components/APIField'; -Retrieves addresses associated with the current subscriber. This returns only the addresses that the authenticated user has access to. - -## How it works - -The `address.getMyAddresses` method queries the SignalWire platform for addresses specifically assigned to or accessible by the current subscriber. This is different from `getAddresses()` which returns all addresses in the space. - -## Key concepts - -### Subscriber-specific addresses - -The response includes only addresses that: -- Are assigned to the current subscriber -- The subscriber has permissions to use -- Are configured for the subscriber's role - -### Use cases - -Retrieve subscriber addresses for: -- Displaying user-specific caller IDs -- Personal phone number selection -- User address management -- Permission-aware UI +Retrieves only the addresses that the current subscriber can be called with. +This is different from `getAddresses()` which returns all addresses visible to the subscriber. ## Parameters @@ -35,145 +15,36 @@ None ## Signature ```typescript -address.getMyAddresses(): Promise +address.getMyAddresses(): Promise ``` ## Returns -**Type:** `Promise` +**Type:** `Promise` -Returns a Promise that resolves with a list of addresses available to the current subscriber. +Returns a Promise that resolves with an array of addresses that the current subscriber can be called with. ## Examples ### Get my addresses ```typescript -const result = await client.address.getMyAddresses() +const addresses = await client.address.getMyAddresses() -console.log('My addresses:', result.addresses) +console.log('My addresses:', addresses) ``` -### Display user's phone numbers +### Display user's addresses ```typescript -const result = await client.address.getMyAddresses() +const addresses = await client.address.getMyAddresses() -const select = document.getElementById('my-numbers-select') +const select = document.getElementById('my-addresses-select') -result.addresses.forEach(address => { +addresses.forEach(address => { const option = document.createElement('option') - option.value = address.number - option.textContent = `${address.name} (${address.number})` + option.value = address.id + option.textContent = `${address.display_name} (${address.name})` select.appendChild(option) }) ``` - -### Get primary address - -```typescript -const result = await client.address.getMyAddresses() - -const primaryAddress = result.addresses.find( - addr => addr.isPrimary -) || result.addresses[0] - -console.log('Primary address:', primaryAddress.number) -``` - -### List my addresses with details - -```typescript -const result = await client.address.getMyAddresses() - -console.log('Your available addresses:') -result.addresses.forEach((address, index) => { - console.log(`${index + 1}. ${address.number}`) - console.log(` Name: ${address.name}`) - console.log(` Type: ${address.type}`) -}) -``` - -### Error handling - -```typescript -try { - const result = await client.address.getMyAddresses() - console.log(`You have ${result.addresses.length} addresses`) -} catch (error) { - console.error('Failed to get your addresses:', error) -} -``` - -### Check if user has addresses - -```typescript -const result = await client.address.getMyAddresses() - -if (result.addresses.length === 0) { - console.log('You do not have any addresses configured') -} else { - console.log(`You have ${result.addresses.length} address(es)`) -} -``` - -### Filter my phone numbers - -```typescript -const result = await client.address.getMyAddresses() - -const phoneNumbers = result.addresses.filter( - addr => addr.type === 'phone_number' -) - -console.log('My phone numbers:', phoneNumbers.map(a => a.number)) -``` - -### Use my address for outbound call - -```typescript -const result = await client.address.getMyAddresses() - -if (result.addresses.length > 0) { - const myNumber = result.addresses[0].number - - const callSession = await client.dial({ - to: '+15551234567', - from: myNumber - }) - - console.log('Calling from my number:', myNumber) -} else { - console.error('No addresses available') -} -``` - -### Compare my addresses with all addresses - -```typescript -const myAddresses = await client.address.getMyAddresses() -const allAddresses = await client.address.getAddresses() - -console.log(`I have access to ${myAddresses.addresses.length} addresses`) -console.log(`Total addresses in space: ${allAddresses.addresses.length}`) -``` - -### Select preferred address - -```typescript -async function selectPreferredAddress() { - const result = await client.address.getMyAddresses() - - const preferred = localStorage.getItem('preferredAddress') - - const address = result.addresses.find( - addr => addr.id === preferred - ) || result.addresses[0] - - return address -} - -const address = await selectPreferredAddress() -console.log('Using address:', address.number) -``` - diff --git a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Chat/chat-get-messages.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Chat/chat-get-messages.mdx index b26c63f1f..290f205da 100644 --- a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Chat/chat-get-messages.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Chat/chat-get-messages.mdx @@ -11,23 +11,6 @@ Retrieves chat messages from a conversation. This method is used for in-call cha The `chat.getMessages` method fetches chat messages that were sent during a call or conversation. These are ephemeral messages tied to an active call session. -## Key concepts - -### In-call chat - -Chat messages are: -- Associated with active calls -- Ephemeral (not permanently stored) -- Real-time communication during calls -- Visible to call participants - -### Message retrieval - -You can retrieve: -- Recent messages -- Message history -- Messages by conversation ID - ## Parameters @@ -69,108 +52,3 @@ const result = await client.chat.getMessages({ console.log('Messages:', result.messages) ``` - -### Display messages in UI - -```typescript -const result = await client.chat.getMessages({ - conversationId: 'conversation-id-here' -}) - -const chatContainer = document.getElementById('chat-messages') - -result.messages.forEach(message => { - const messageDiv = document.createElement('div') - messageDiv.className = 'message' - messageDiv.textContent = `${message.from}: ${message.content}` - chatContainer.appendChild(messageDiv) -}) -``` - -### Get messages with pagination - -```typescript -const result = await client.chat.getMessages({ - conversationId: 'conversation-id-here', - limit: 20, - offset: 0 -}) - -console.log(`Showing ${result.messages.length} of ${result.total} messages`) -``` - -### Load more messages - -```typescript -let offset = 0 -const limit = 20 - -async function loadMoreMessages() { - const result = await client.chat.getMessages({ - conversationId: 'conversation-id-here', - limit: limit, - offset: offset - }) - - displayMessages(result.messages) - offset += limit - - if (result.messages.length < limit) { - console.log('No more messages to load') - } -} -``` - -### Error handling - -```typescript -try { - const result = await client.chat.getMessages({ - conversationId: 'conversation-id-here' - }) - console.log('Retrieved messages:', result.messages.length) -} catch (error) { - console.error('Failed to get messages:', error) -} -``` - -### Filter messages by sender - -```typescript -const result = await client.chat.getMessages({ - conversationId: 'conversation-id-here' -}) - -const myMessages = result.messages.filter( - msg => msg.from === currentUserId -) - -console.log('My messages:', myMessages) -``` - -### Get messages with timestamp - -```typescript -const result = await client.chat.getMessages({ - conversationId: 'conversation-id-here' -}) - -result.messages.forEach(message => { - const timestamp = new Date(message.timestamp).toLocaleTimeString() - console.log(`[${timestamp}] ${message.from}: ${message.content}`) -}) -``` - -### Refresh messages periodically - -```typescript -setInterval(async () => { - const result = await client.chat.getMessages({ - conversationId: 'conversation-id-here', - limit: 10 - }) - - updateChatUI(result.messages) -}, 5000) -``` - diff --git a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Chat/chat-join.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Chat/chat-join.mdx index 64eb90acc..c8f30c767 100644 --- a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Chat/chat-join.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Chat/chat-join.mdx @@ -11,23 +11,6 @@ Joins a chat conversation, allowing you to send and receive messages in an activ The `chat.join` method adds you as a participant to a chat conversation. Once joined, you can send messages and receive real-time updates for new messages. -## Key concepts - -### Chat participation - -Joining a chat allows you to: -- Send messages to participants -- Receive messages in real-time -- View conversation history -- Participate in group discussions - -### Conversation context - -Chats are typically associated with: -- Active calls -- Video conferences -- Group conversations - ## Parameters @@ -65,104 +48,3 @@ const response = await client.chat.join({ console.log('Joined conversation:', response.conversationId) ``` - -### Join and start chatting - -```typescript -const response = await client.chat.join({ - conversationId: 'conversation-id-here' -}) - -await client.chat.sendMessage({ - conversationId: response.conversationId, - content: 'Hello everyone!' -}) -``` - -### Join with member ID - -```typescript -const response = await client.chat.join({ - conversationId: 'conversation-id-here', - memberId: 'my-member-id' -}) - -console.log('Joined as:', response.memberId) -``` - -### Join and subscribe to messages - -```typescript -const response = await client.chat.join({ - conversationId: 'conversation-id-here' -}) - -await client.chat.subscribe({ - conversationId: response.conversationId, - onMessage: (message) => { - console.log('New message:', message.content) - } -}) -``` - -### Error handling - -```typescript -try { - const response = await client.chat.join({ - conversationId: 'conversation-id-here' - }) - console.log('Successfully joined chat') -} catch (error) { - console.error('Failed to join chat:', error) -} -``` - -### Join during call - -```typescript -const callSession = await client.dial({ - to: '+15551234567', - from: '+15559876543' -}) - -const response = await client.chat.join({ - conversationId: callSession.conversationId -}) - -console.log('Chat enabled for call') -``` - -### Join with UI update - -```typescript -async function joinChat(conversationId) { - try { - const response = await client.chat.join({ - conversationId: conversationId - }) - - document.getElementById('chat-panel').style.display = 'block' - document.getElementById('chat-status').textContent = 'Connected' - - return response - } catch (error) { - document.getElementById('chat-status').textContent = 'Connection failed' - console.error(error) - } -} -``` - -### Auto-join on call answer - -```typescript -callSession.on('call.state', async (event) => { - if (event.call.state === 'answered') { - await client.chat.join({ - conversationId: callSession.conversationId - }) - console.log('Chat ready') - } -}) -``` - diff --git a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Chat/chat-send-message.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Chat/chat-send-message.mdx index 730607ebb..753de9c62 100644 --- a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Chat/chat-send-message.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Chat/chat-send-message.mdx @@ -11,23 +11,6 @@ Sends a message in a chat conversation during an active call. The `chat.sendMessage` method delivers a text message to all participants in a chat conversation. Messages are sent in real-time to active participants. -## Key concepts - -### Message delivery - -Messages are: -- Delivered in real-time -- Visible to all conversation participants -- Ephemeral (tied to the call session) -- Ordered chronologically - -### Message content - -You can send: -- Plain text messages -- Formatted text -- Metadata with messages - ## Parameters @@ -70,143 +53,3 @@ const response = await client.chat.sendMessage({ console.log('Message sent:', response.messageId) ``` - -### Send message from input - -```typescript -const sendButton = document.getElementById('send-btn') -const messageInput = document.getElementById('message-input') - -sendButton.addEventListener('click', async () => { - const content = messageInput.value.trim() - - if (content) { - await client.chat.sendMessage({ - conversationId: 'conversation-id-here', - content: content - }) - - messageInput.value = '' - } -}) -``` - -### Send message with metadata - -```typescript -const response = await client.chat.sendMessage({ - conversationId: 'conversation-id-here', - content: 'Check this out!', - metadata: { - type: 'announcement', - priority: 'high' - } -}) -``` - -### Error handling - -```typescript -try { - await client.chat.sendMessage({ - conversationId: 'conversation-id-here', - content: 'Hello!' - }) - console.log('Message sent successfully') -} catch (error) { - console.error('Failed to send message:', error) -} -``` - -### Send message with confirmation - -```typescript -async function sendMessageWithConfirmation(content) { - try { - const response = await client.chat.sendMessage({ - conversationId: 'conversation-id-here', - content: content - }) - - showNotification('Message sent') - return response - } catch (error) { - showNotification('Failed to send message') - throw error - } -} -``` - -### Send message on Enter key - -```typescript -const messageInput = document.getElementById('message-input') - -messageInput.addEventListener('keypress', async (e) => { - if (e.key === 'Enter' && !e.shiftKey) { - e.preventDefault() - - const content = messageInput.value.trim() - - if (content) { - await client.chat.sendMessage({ - conversationId: 'conversation-id-here', - content: content - }) - - messageInput.value = '' - } - } -}) -``` - -### Display sent message immediately - -```typescript -async function sendAndDisplayMessage(content) { - const tempId = Date.now().toString() - - displayMessage({ - id: tempId, - content: content, - from: 'You', - timestamp: new Date() - }) - - try { - const response = await client.chat.sendMessage({ - conversationId: 'conversation-id-here', - content: content - }) - - updateMessageId(tempId, response.messageId) - } catch (error) { - markMessageAsFailed(tempId) - console.error('Failed to send:', error) - } -} -``` - -### Throttle message sending - -```typescript -let lastMessageTime = 0 -const throttleMs = 1000 - -async function sendThrottledMessage(content) { - const now = Date.now() - - if (now - lastMessageTime < throttleMs) { - console.log('Please wait before sending another message') - return - } - - lastMessageTime = now - - await client.chat.sendMessage({ - conversationId: 'conversation-id-here', - content: content - }) -} -``` - diff --git a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Chat/chat-subscribe.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Chat/chat-subscribe.mdx index 52d13566c..93c0ed69e 100644 --- a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Chat/chat-subscribe.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Chat/chat-subscribe.mdx @@ -11,24 +11,6 @@ Subscribes to real-time chat message events in a conversation, allowing you to r The `chat.subscribe` method establishes a real-time subscription to chat events. When new messages are sent in the conversation, your callback function is invoked with the message details. -## Key concepts - -### Real-time updates - -Subscriptions provide: -- Instant message notifications -- Live chat updates -- Event-driven architecture -- Bi-directional communication - -### Event handling - -Your callback receives: -- New messages -- Message metadata -- Sender information -- Timestamps - ## Parameters @@ -67,154 +49,4 @@ const subscription = await client.chat.subscribe({ console.log('Content:', message.content) } }) -``` - -### Display messages in UI - -```typescript -await client.chat.subscribe({ - conversationId: 'conversation-id-here', - onMessage: (message) => { - const chatContainer = document.getElementById('chat-messages') - - const messageDiv = document.createElement('div') - messageDiv.className = 'message' - messageDiv.textContent = `${message.from}: ${message.content}` - - chatContainer.appendChild(messageDiv) - chatContainer.scrollTop = chatContainer.scrollHeight - } -}) -``` - -### Subscribe with timestamp - -```typescript -await client.chat.subscribe({ - conversationId: 'conversation-id-here', - onMessage: (message) => { - const time = new Date(message.timestamp).toLocaleTimeString() - console.log(`[${time}] ${message.from}: ${message.content}`) - } -}) -``` - -### Unsubscribe when done - -```typescript -const subscription = await client.chat.subscribe({ - conversationId: 'conversation-id-here', - onMessage: (message) => { - console.log('Message:', message.content) - } -}) - -await subscription.unsubscribe() -console.log('Unsubscribed from chat') -``` - -### Error handling - -```typescript -try { - await client.chat.subscribe({ - conversationId: 'conversation-id-here', - onMessage: (message) => { - displayMessage(message) - } - }) - console.log('Subscribed to chat updates') -} catch (error) { - console.error('Failed to subscribe:', error) -} -``` - -### Filter messages by type - -```typescript -await client.chat.subscribe({ - conversationId: 'conversation-id-here', - onMessage: (message) => { - if (message.metadata?.type === 'announcement') { - displayAnnouncement(message) - } else { - displayRegularMessage(message) - } - } -}) -``` - -### Play notification sound - -```typescript -const notificationSound = new Audio('/notification.mp3') - -await client.chat.subscribe({ - conversationId: 'conversation-id-here', - onMessage: (message) => { - displayMessage(message) - - if (message.from !== currentUserId) { - notificationSound.play() - } - } -}) -``` - -### Subscribe during call - -```typescript -const callSession = await client.dial({ - to: '+15551234567', - from: '+15559876543' -}) - -await client.chat.join({ - conversationId: callSession.conversationId -}) - -await client.chat.subscribe({ - conversationId: callSession.conversationId, - onMessage: (message) => { - console.log('Chat message:', message.content) - } -}) -``` - -### Manage subscription lifecycle - -```typescript -let chatSubscription = null - -async function enableChat(conversationId) { - chatSubscription = await client.chat.subscribe({ - conversationId: conversationId, - onMessage: (message) => { - displayMessage(message) - } - }) -} - -async function disableChat() { - if (chatSubscription) { - await chatSubscription.unsubscribe() - chatSubscription = null - } -} -``` - -### Track message count - -```typescript -let messageCount = 0 - -await client.chat.subscribe({ - conversationId: 'conversation-id-here', - onMessage: (message) => { - messageCount++ - document.getElementById('message-count').textContent = messageCount - displayMessage(message) - } -}) -``` - +``` \ No newline at end of file diff --git a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Conversation/conversation-get-conversation-messages.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Conversation/conversation-get-conversation-messages.mdx index 08511ea7b..e069dcf74 100644 --- a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Conversation/conversation-get-conversation-messages.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Conversation/conversation-get-conversation-messages.mdx @@ -11,23 +11,6 @@ Retrieves messages from a specific persistent conversation. Unlike chat messages The `conversation.getConversationMessages` method fetches the message history from a persistent conversation. These messages remain available even after participants leave the conversation. -## Key concepts - -### Persistent conversations - -Conversation messages are: -- Permanently stored -- Available across sessions -- Accessible after participants leave -- Associated with conversation IDs - -### Message history - -You can retrieve: -- Full conversation history -- Recent messages -- Paginated results -- Messages with metadata ## Parameters @@ -70,119 +53,3 @@ const result = await client.conversation.getConversationMessages({ console.log('Messages:', result.messages) ``` - -### Display message history - -```typescript -const result = await client.conversation.getConversationMessages({ - conversationId: 'conversation-id-here' -}) - -result.messages.forEach(message => { - console.log(`${message.from}: ${message.content}`) - console.log(`Sent at: ${new Date(message.timestamp).toLocaleString()}`) -}) -``` - -### Paginate through messages - -```typescript -const result = await client.conversation.getConversationMessages({ - conversationId: 'conversation-id-here', - limit: 20, - offset: 0 -}) - -console.log(`Showing ${result.messages.length} of ${result.total} messages`) - -if (result.hasMore) { - console.log('More messages available') -} -``` - -### Load older messages - -```typescript -let offset = 0 -const limit = 20 - -async function loadOlderMessages() { - const result = await client.conversation.getConversationMessages({ - conversationId: 'conversation-id-here', - limit: limit, - offset: offset - }) - - prependMessages(result.messages) - offset += limit - - return result.hasMore -} - -const hasMore = await loadOlderMessages() -``` - -### Error handling - -```typescript -try { - const result = await client.conversation.getConversationMessages({ - conversationId: 'conversation-id-here' - }) - console.log('Retrieved messages:', result.messages.length) -} catch (error) { - console.error('Failed to get messages:', error) -} -``` - -### Display in chat UI - -```typescript -const result = await client.conversation.getConversationMessages({ - conversationId: 'conversation-id-here' -}) - -const chatContainer = document.getElementById('chat-messages') -chatContainer.innerHTML = '' - -result.messages.forEach(message => { - const messageDiv = document.createElement('div') - messageDiv.className = message.from === currentUserId ? 'message-sent' : 'message-received' - messageDiv.innerHTML = ` -
${message.from}
-
${message.content}
-
${new Date(message.timestamp).toLocaleTimeString()}
- ` - chatContainer.appendChild(messageDiv) -}) -``` - -### Filter system messages - -```typescript -const result = await client.conversation.getConversationMessages({ - conversationId: 'conversation-id-here' -}) - -const userMessages = result.messages.filter( - msg => msg.type !== 'system' -) - -console.log('User messages:', userMessages) -``` - -### Search conversation history - -```typescript -const result = await client.conversation.getConversationMessages({ - conversationId: 'conversation-id-here' -}) - -const searchTerm = 'important' -const matchingMessages = result.messages.filter( - msg => msg.content.toLowerCase().includes(searchTerm.toLowerCase()) -) - -console.log(`Found ${matchingMessages.length} messages containing "${searchTerm}"`) -``` - diff --git a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Conversation/conversation-get-conversations.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Conversation/conversation-get-conversations.mdx index 6f3886d45..9582dbcd4 100644 --- a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Conversation/conversation-get-conversations.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Conversation/conversation-get-conversations.mdx @@ -11,25 +11,6 @@ Retrieves a list of conversations that the current subscriber has access to or i The `conversation.getConversations` method fetches all conversations associated with the authenticated subscriber. This includes active conversations, archived conversations, and group discussions. -## Key concepts - -### Conversation types - -Conversations can include: -- One-on-one chats -- Group conversations -- Archived discussions -- Active ongoing conversations - -### Conversation metadata - -Each conversation includes: -- Conversation ID -- Participant list -- Last message preview -- Unread message count -- Timestamps - ## Parameters @@ -69,138 +50,3 @@ const result = await client.conversation.getConversations() console.log('Conversations:', result.conversations) ``` - -### Display conversation list - -```typescript -const result = await client.conversation.getConversations() - -const listContainer = document.getElementById('conversations-list') - -result.conversations.forEach(conversation => { - const item = document.createElement('div') - item.className = 'conversation-item' - item.innerHTML = ` -

${conversation.name}

-

${conversation.lastMessage?.content || 'No messages'}

- ${conversation.unreadCount} unread - ` - item.onclick = () => openConversation(conversation.id) - listContainer.appendChild(item) -}) -``` - -### Get conversations with pagination - -```typescript -const result = await client.conversation.getConversations({ - limit: 10, - offset: 0 -}) - -console.log(`Showing ${result.conversations.length} of ${result.total}`) -``` - -### Load more conversations - -```typescript -let offset = 0 -const limit = 10 - -async function loadMoreConversations() { - const result = await client.conversation.getConversations({ - limit: limit, - offset: offset - }) - - displayConversations(result.conversations) - offset += limit - - return result.hasMore -} -``` - -### Error handling - -```typescript -try { - const result = await client.conversation.getConversations() - console.log('Retrieved conversations:', result.conversations.length) -} catch (error) { - console.error('Failed to get conversations:', error) -} -``` - -### Sort conversations by recent activity - -```typescript -const result = await client.conversation.getConversations() - -const sorted = result.conversations.sort((a, b) => { - const timeA = new Date(a.lastMessageTimestamp).getTime() - const timeB = new Date(b.lastMessageTimestamp).getTime() - return timeB - timeA -}) - -console.log('Most recent conversations:', sorted) -``` - -### Filter unread conversations - -```typescript -const result = await client.conversation.getConversations() - -const unread = result.conversations.filter( - conv => conv.unreadCount > 0 -) - -console.log(`You have ${unread.length} conversations with unread messages`) -``` - -### Get total unread count - -```typescript -const result = await client.conversation.getConversations() - -const totalUnread = result.conversations.reduce( - (sum, conv) => sum + conv.unreadCount, - 0 -) - -console.log(`Total unread messages: ${totalUnread}`) -document.getElementById('unread-badge').textContent = totalUnread -``` - -### Find specific conversation - -```typescript -const result = await client.conversation.getConversations() - -const conversation = result.conversations.find( - conv => conv.name === 'Team Discussion' -) - -if (conversation) { - console.log('Found conversation:', conversation.id) -} -``` - -### Refresh conversations list - -```typescript -async function refreshConversations() { - const result = await client.conversation.getConversations() - - updateConversationsList(result.conversations) - - const totalUnread = result.conversations.reduce( - (sum, conv) => sum + conv.unreadCount, - 0 - ) - - updateUnreadBadge(totalUnread) -} - -setInterval(refreshConversations, 30000) -``` - diff --git a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Conversation/conversation-get-messages.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Conversation/conversation-get-messages.mdx index 1fc13aaba..6698772ae 100644 --- a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Conversation/conversation-get-messages.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Conversation/conversation-get-messages.mdx @@ -11,24 +11,6 @@ Retrieves messages across all conversations, providing a unified view of message The `conversation.getMessages` method fetches messages from all conversations the subscriber has access to. This is useful for displaying a combined message feed or searching across conversations. -## Key concepts - -### Cross-conversation retrieval - -This method: -- Aggregates messages from multiple conversations -- Provides a unified message feed -- Supports filtering and sorting -- Enables global message search - -### Use cases - -Common scenarios: -- Displaying recent messages from all conversations -- Search across all conversations -- Activity feed -- Global message notifications - ## Parameters @@ -68,139 +50,3 @@ const result = await client.conversation.getMessages() console.log('Recent messages:', result.messages) ``` - -### Display unified message feed - -```typescript -const result = await client.conversation.getMessages({ - limit: 20 -}) - -const feedContainer = document.getElementById('message-feed') - -result.messages.forEach(message => { - const item = document.createElement('div') - item.className = 'message-item' - item.innerHTML = ` -
${message.conversationName}
-
${message.from}
-
${message.content}
-
${new Date(message.timestamp).toLocaleString()}
- ` - feedContainer.appendChild(item) -}) -``` - -### Paginate through messages - -```typescript -const result = await client.conversation.getMessages({ - limit: 20, - offset: 0 -}) - -console.log(`Showing ${result.messages.length} of ${result.total} messages`) -``` - -### Error handling - -```typescript -try { - const result = await client.conversation.getMessages() - console.log('Retrieved messages:', result.messages.length) -} catch (error) { - console.error('Failed to get messages:', error) -} -``` - -### Search all messages - -```typescript -const result = await client.conversation.getMessages() - -const searchTerm = 'meeting' -const matches = result.messages.filter( - msg => msg.content.toLowerCase().includes(searchTerm.toLowerCase()) -) - -console.log(`Found ${matches.length} messages containing "${searchTerm}"`) -``` - -### Group messages by conversation - -```typescript -const result = await client.conversation.getMessages() - -const grouped = result.messages.reduce((acc, message) => { - if (!acc[message.conversationId]) { - acc[message.conversationId] = [] - } - acc[message.conversationId].push(message) - return acc -}, {}) - -console.log('Messages by conversation:', grouped) -``` - -### Get messages from today - -```typescript -const result = await client.conversation.getMessages() - -const today = new Date() -today.setHours(0, 0, 0, 0) - -const todayMessages = result.messages.filter( - msg => new Date(msg.timestamp) >= today -) - -console.log(`${todayMessages.length} messages today`) -``` - -### Load more messages - -```typescript -let offset = 0 -const limit = 20 - -async function loadMoreMessages() { - const result = await client.conversation.getMessages({ - limit: limit, - offset: offset - }) - - appendToFeed(result.messages) - offset += limit - - return result.hasMore -} -``` - -### Get unread messages - -```typescript -const result = await client.conversation.getMessages() - -const unread = result.messages.filter( - msg => !msg.read && msg.from !== currentUserId -) - -console.log(`${unread.length} unread messages`) -``` - -### Activity summary - -```typescript -const result = await client.conversation.getMessages({ - limit: 100 -}) - -const summary = { - total: result.messages.length, - conversations: new Set(result.messages.map(m => m.conversationId)).size, - unread: result.messages.filter(m => !m.read).length -} - -console.log('Activity summary:', summary) -``` - diff --git a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Conversation/conversation-join.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Conversation/conversation-join.mdx index 4953e17f6..caed81979 100644 --- a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Conversation/conversation-join.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Conversation/conversation-join.mdx @@ -11,23 +11,6 @@ Joins a persistent conversation, allowing you to send and receive messages in th The `conversation.join` method adds you as a participant to a persistent conversation. Once joined, you can send messages, receive updates, and access the conversation history. -## Key concepts - -### Conversation participation - -Joining a conversation allows you to: -- Send and receive messages -- Access conversation history -- Receive real-time updates -- View participant list - -### Persistent vs ephemeral - -Unlike chat (ephemeral), conversations are: -- Permanently stored -- Available across sessions -- Accessible after leaving and rejoining - ## Parameters @@ -65,107 +48,3 @@ const response = await client.conversation.join({ console.log('Joined conversation:', response.conversationId) ``` - -### Join and load history - -```typescript -const response = await client.conversation.join({ - conversationId: 'conversation-id-here' -}) - -const messages = await client.conversation.getConversationMessages({ - conversationId: response.conversationId -}) - -console.log('Loaded message history:', messages.messages.length) -``` - -### Join with member ID - -```typescript -const response = await client.conversation.join({ - conversationId: 'conversation-id-here', - memberId: 'my-member-id' -}) - -console.log('Joined as:', response.memberId) -``` - -### Error handling - -```typescript -try { - const response = await client.conversation.join({ - conversationId: 'conversation-id-here' - }) - console.log('Successfully joined conversation') -} catch (error) { - console.error('Failed to join conversation:', error) -} -``` - -### Join and subscribe - -```typescript -const response = await client.conversation.join({ - conversationId: 'conversation-id-here' -}) - -await client.conversation.subscribe((event) => { - if (event.type === 'message.created') { - console.log('New message:', event.message.content) - } -}) -``` - -### Join conversation from list - -```typescript -async function openConversation(conversationId) { - const response = await client.conversation.join({ - conversationId: conversationId - }) - - const messages = await client.conversation.getConversationMessages({ - conversationId: conversationId - }) - - displayConversation(response, messages) -} -``` - -### Auto-join on notification - -```typescript -async function handleConversationNotification(notificationData) { - const conversationId = notificationData.conversationId - - const response = await client.conversation.join({ - conversationId: conversationId - }) - - console.log('Joined conversation from notification') - openConversationUI(conversationId) -} -``` - -### Join with UI update - -```typescript -async function joinConversation(conversationId) { - try { - const response = await client.conversation.join({ - conversationId: conversationId - }) - - document.getElementById('conversation-title').textContent = response.name - document.getElementById('participant-count').textContent = response.participantCount - - return response - } catch (error) { - console.error('Failed to join:', error) - showError('Could not join conversation') - } -} -``` - diff --git a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Conversation/conversation-send-message.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Conversation/conversation-send-message.mdx index 83f1cd6c4..2488ac3d1 100644 --- a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Conversation/conversation-send-message.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Conversation/conversation-send-message.mdx @@ -11,24 +11,6 @@ Sends a message in a persistent conversation. Messages are stored permanently an The `conversation.sendMessage` method delivers a message to all participants in a persistent conversation. Unlike ephemeral chat messages, these messages are permanently stored. -## Key concepts - -### Message persistence - -Conversation messages are: -- Permanently stored -- Accessible across sessions -- Available to all participants -- Synced across devices - -### Message delivery - -Messages are: -- Delivered in real-time to active participants -- Available for retrieval by offline participants -- Ordered chronologically -- Guaranteed delivery - ## Parameters @@ -70,191 +52,4 @@ const response = await client.conversation.sendMessage({ }) console.log('Message sent:', response.messageId) -``` - -### Send message from input - -```typescript -const sendButton = document.getElementById('send-btn') -const messageInput = document.getElementById('message-input') - -sendButton.addEventListener('click', async () => { - const content = messageInput.value.trim() - - if (content) { - await client.conversation.sendMessage({ - conversationId: 'conversation-id-here', - content: content - }) - - messageInput.value = '' - } -}) -``` - -### Send message with metadata - -```typescript -const response = await client.conversation.sendMessage({ - conversationId: 'conversation-id-here', - content: 'Check out this file!', - metadata: { - type: 'file_share', - fileUrl: 'https://example.com/file.pdf', - fileName: 'document.pdf' - } -}) -``` - -### Error handling - -```typescript -try { - await client.conversation.sendMessage({ - conversationId: 'conversation-id-here', - content: 'Hello!' - }) - console.log('Message sent successfully') -} catch (error) { - console.error('Failed to send message:', error) -} -``` - -### Send message on Enter key - -```typescript -const messageInput = document.getElementById('message-input') - -messageInput.addEventListener('keypress', async (e) => { - if (e.key === 'Enter' && !e.shiftKey) { - e.preventDefault() - - const content = messageInput.value.trim() - - if (content) { - await client.conversation.sendMessage({ - conversationId: 'conversation-id-here', - content: content - }) - - messageInput.value = '' - } - } -}) -``` - -### Display sent message immediately - -```typescript -async function sendAndDisplayMessage(content) { - const tempId = `temp-${Date.now()}` - - displayMessage({ - id: tempId, - content: content, - from: currentUserId, - timestamp: new Date(), - status: 'sending' - }) - - try { - const response = await client.conversation.sendMessage({ - conversationId: 'conversation-id-here', - content: content - }) - - updateMessage(tempId, { - id: response.messageId, - status: 'sent' - }) - } catch (error) { - updateMessage(tempId, { - status: 'failed' - }) - console.error('Failed to send:', error) - } -} -``` - -### Send with retry logic - -```typescript -async function sendMessageWithRetry(content, maxRetries = 3) { - for (let i = 0; i < maxRetries; i++) { - try { - const response = await client.conversation.sendMessage({ - conversationId: 'conversation-id-here', - content: content - }) - return response - } catch (error) { - console.log(`Send attempt ${i + 1} failed`) - - if (i < maxRetries - 1) { - await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1))) - } else { - throw error - } - } - } -} -``` - -### Send formatted message - -```typescript -await client.conversation.sendMessage({ - conversationId: 'conversation-id-here', - content: 'Important announcement!', - metadata: { - format: 'announcement', - priority: 'high', - timestamp: new Date().toISOString() - } -}) -``` - -### Reply to a message - -```typescript -await client.conversation.sendMessage({ - conversationId: 'conversation-id-here', - content: 'Thanks for the update!', - metadata: { - replyTo: originalMessageId, - quotedText: originalMessage.content - } -}) -``` - -### Send with typing indicator - -```typescript -let typingTimer - -messageInput.addEventListener('input', () => { - clearTimeout(typingTimer) - - client.conversation.sendTypingIndicator({ - conversationId: 'conversation-id-here' - }) - - typingTimer = setTimeout(() => { - }, 3000) -}) - -messageInput.addEventListener('keypress', async (e) => { - if (e.key === 'Enter') { - clearTimeout(typingTimer) - - const content = messageInput.value.trim() - if (content) { - await client.conversation.sendMessage({ - conversationId: 'conversation-id-here', - content: content - }) - } - } -}) -``` - +``` \ No newline at end of file diff --git a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Conversation/conversation-subscribe.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Conversation/conversation-subscribe.mdx index d382647b3..39d4cbd1d 100644 --- a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Conversation/conversation-subscribe.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Conversation/conversation-subscribe.mdx @@ -11,25 +11,6 @@ Subscribes to real-time conversation events, allowing you to receive notificatio The `conversation.subscribe` method establishes a real-time subscription to conversation events. When events occur (new messages, participants joining/leaving, etc.), your callback function is invoked with event details. -## Key concepts - -### Real-time subscriptions - -Subscriptions provide: -- Instant event notifications -- Live conversation updates -- Bi-directional communication -- Event-driven architecture - -### Event types - -Common events include: -- New messages -- Message updates/deletions -- Participant joined/left -- Conversation metadata changes -- Typing indicators - ## Parameters @@ -61,178 +42,3 @@ const subscription = await client.conversation.subscribe((event) => { } }) ``` - -### Handle different event types - -```typescript -await client.conversation.subscribe((event) => { - switch (event.type) { - case 'message.created': - displayNewMessage(event.message) - break - case 'message.updated': - updateMessage(event.message) - break - case 'message.deleted': - removeMessage(event.messageId) - break - case 'participant.joined': - console.log(`${event.participant.name} joined`) - break - case 'participant.left': - console.log(`${event.participant.name} left`) - break - } -}) -``` - -### Subscribe with UI updates - -```typescript -await client.conversation.subscribe((event) => { - if (event.type === 'message.created') { - const chatContainer = document.getElementById('chat-messages') - - const messageDiv = document.createElement('div') - messageDiv.className = 'message' - messageDiv.innerHTML = ` -
${event.message.from}
-
${event.message.content}
-
${new Date(event.message.timestamp).toLocaleTimeString()}
- ` - - chatContainer.appendChild(messageDiv) - chatContainer.scrollTop = chatContainer.scrollHeight - } -}) -``` - -### Unsubscribe when done - -```typescript -const subscription = await client.conversation.subscribe((event) => { - console.log('Event:', event.type) -}) - -await subscription.unsubscribe() -console.log('Unsubscribed from conversation events') -``` - -### Error handling - -```typescript -try { - await client.conversation.subscribe((event) => { - handleEvent(event) - }) - console.log('Subscribed to conversation updates') -} catch (error) { - console.error('Failed to subscribe:', error) -} -``` - -### Filter events by conversation - -```typescript -const activeConversationId = 'conversation-id-here' - -await client.conversation.subscribe((event) => { - if (event.conversationId === activeConversationId) { - handleEvent(event) - } -}) -``` - -### Play notification sound - -```typescript -const notificationSound = new Audio('/notification.mp3') - -await client.conversation.subscribe((event) => { - if (event.type === 'message.created') { - displayMessage(event.message) - - if (event.message.from !== currentUserId) { - notificationSound.play() - } - } -}) -``` - -### Update unread count - -```typescript -let unreadCount = 0 - -await client.conversation.subscribe((event) => { - if (event.type === 'message.created' && event.message.from !== currentUserId) { - unreadCount++ - document.getElementById('unread-badge').textContent = unreadCount - } -}) -``` - -### Track typing indicators - -```typescript -const typingUsers = new Set() - -await client.conversation.subscribe((event) => { - if (event.type === 'typing.started') { - typingUsers.add(event.userId) - updateTypingIndicator(typingUsers) - } else if (event.type === 'typing.stopped') { - typingUsers.delete(event.userId) - updateTypingIndicator(typingUsers) - } -}) - -function updateTypingIndicator(users) { - const indicator = document.getElementById('typing-indicator') - - if (users.size === 0) { - indicator.textContent = '' - } else if (users.size === 1) { - indicator.textContent = `${Array.from(users)[0]} is typing...` - } else { - indicator.textContent = `${users.size} people are typing...` - } -} -``` - -### Manage subscription lifecycle - -```typescript -let conversationSubscription = null - -async function enableConversationUpdates() { - conversationSubscription = await client.conversation.subscribe((event) => { - handleConversationEvent(event) - }) -} - -async function disableConversationUpdates() { - if (conversationSubscription) { - await conversationSubscription.unsubscribe() - conversationSubscription = null - } -} -``` - -### Log all conversation activity - -```typescript -await client.conversation.subscribe((event) => { - console.log(`[${new Date().toISOString()}] ${event.type}`, event) - - const logEntry = { - timestamp: new Date(), - eventType: event.type, - conversationId: event.conversationId, - details: event - } - - saveToActivityLog(logEntry) -}) -``` - diff --git a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/dial.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/dial.mdx index 54f3b82c7..b73a9c9fd 100644 --- a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/dial.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/dial.mdx @@ -114,10 +114,5 @@ const callSession = await client.dial({ rootElement: document.getElementById('video-container'), audio: true, video: true, - listen: { - onCallStateChanged: (state) => { - console.log('Call state:', state) - } - } }) ``` diff --git a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/disconnect.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/disconnect.mdx index a25e18bd6..304fa79e1 100644 --- a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/disconnect.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/disconnect.mdx @@ -5,24 +5,8 @@ slug: /signalwire-client/disconnect import APIField from '@site/src/components/APIField'; -Disconnects from the SignalWire network and cleans up all active resources, including calls and subscriptions. - -## How it works - -The `disconnect` method gracefully terminates the client connection to SignalWire. It ends all active calls, removes event listeners, and frees up system resources. - -## Key concepts - -### Clean shutdown - -When disconnecting, the client: -1. Ends all active calls -2. Closes all subscriptions -3. Removes event listeners -4. Releases media devices -5. Terminates the WebSocket connection - -### Reconnection +The `disconnect` method gracefully terminates the client connection to SignalWire, including all +active calls, and event subscriptions. After disconnecting, you need to create a new client instance or call connection methods again to reconnect. @@ -50,104 +34,3 @@ Returns a Promise that resolves when the disconnection is complete. await client.disconnect() console.log('Disconnected from SignalWire') ``` - -### Disconnect on page unload - -```typescript -window.addEventListener('beforeunload', async () => { - await client.disconnect() -}) -``` - -### Disconnect with cleanup - -```typescript -async function cleanup() { - console.log('Cleaning up...') - - await client.disconnect() - - console.log('Client disconnected') -} - -cleanup() -``` - -### Disconnect button - -```typescript -const disconnectButton = document.getElementById('disconnect-btn') - -disconnectButton.addEventListener('click', async () => { - try { - await client.disconnect() - disconnectButton.disabled = true - disconnectButton.textContent = 'Disconnected' - } catch (error) { - console.error('Disconnect failed:', error) - } -}) -``` - -### Reconnect after disconnect - -```typescript -await client.disconnect() -console.log('Disconnected') - -await client.online({ - incomingCallHandlers: { - onCallReceived: (call) => { - console.log('Incoming call:', call.id) - } - } -}) - -console.log('Reconnected') -``` - -### Disconnect with error handling - -```typescript -try { - await client.disconnect() - console.log('Successfully disconnected') -} catch (error) { - console.error('Error during disconnect:', error) -} -``` - -### Disconnect with timeout - -```typescript -const disconnectWithTimeout = async () => { - const timeoutPromise = new Promise((_, reject) => { - setTimeout(() => reject(new Error('Disconnect timeout')), 5000) - }) - - try { - await Promise.race([ - client.disconnect(), - timeoutPromise - ]) - console.log('Disconnected successfully') - } catch (error) { - console.error('Disconnect failed or timed out:', error) - } -} - -await disconnectWithTimeout() -``` - -### Disconnect multiple clients - -```typescript -const clients = [client1, client2, client3] - -await Promise.all( - clients.map(client => client.disconnect()) -) - -console.log('All clients disconnected') -``` - diff --git a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/events.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/events.mdx index be91f2b31..59f52dc37 100644 --- a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/events.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/events.mdx @@ -100,10 +100,11 @@ client.on("ai.response_utterance", (params) => { ### user_event -Emitted for custom user-defined events. This allows you to send and receive custom application-specific events. +You can write SWML scripts to send custom events to your application. That way, when you +use the `client.dial()` method to dial to a SWML script, you can listen for those events. - Custom event data defined by your application. + Custom event data sent by the SWML script. ```typescript @@ -112,285 +113,33 @@ client.on("user_event", (params) => { }) ``` -## Examples +This can be useful for triggering actions and UI updates on the client side. The AI can +also send these custom events, making it very powerful. -### Track AI conversation flow +Consider this simple SWML script: -```typescript -client.on("ai.speech_detect", (params) => { - const cleanText = params.text.replace(/\{confidence=[\d.]+\}/, "") - console.log('User:', cleanText) - updateChatUI('user', cleanText) -}) - -client.on("ai.partial_result", (params) => { - console.log('AI typing...') - showTypingIndicator() -}) - -client.on("ai.completion", (params) => { - console.log('AI:', params.text) - hideTypingIndicator() - updateChatUI('ai', params.text) -}) -``` - -### Display AI responses in UI - -```typescript -const chatContainer = document.getElementById('chat-container') - -client.on("ai.response_utterance", (params) => { - const messageDiv = document.createElement('div') - messageDiv.className = 'ai-message' - messageDiv.textContent = params.utterance - chatContainer.appendChild(messageDiv) - chatContainer.scrollTop = chatContainer.scrollHeight -}) -``` - -### Handle barged interactions - -```typescript -client.on("ai.partial_result", (params) => { - if (params.barged) { - console.log('User interrupted AI') - markResponseAsInterrupted() - } -}) - -client.on("ai.completion", (params) => { - if (params.type === 'barged') { - console.log('Response was interrupted') - showInterruptionIndicator() - } -}) +```yaml andJson +version: 1.0.0 +sections: + main: + - user_event: + event: + myCustomEvent: 'Hello, world!' + - play: + url: 'say: Custom event sent.' ``` -### Log AI interactions +This will send a custom event to the dialing client with the name `myCustomEvent` and the value `Hello, world!`. -```typescript -const conversationLog = [] - -client.on("ai.speech_detect", (params) => { - conversationLog.push({ - type: 'user', - text: params.text, - timestamp: new Date() - }) -}) - -client.on("ai.completion", (params) => { - conversationLog.push({ - type: 'ai', - text: params.text, - timestamp: new Date(), - interrupted: params.type === 'barged' - }) -}) - -console.log('Conversation history:', conversationLog) -``` - -### Real-time transcript +You can listen to this event like so: ```typescript -const transcriptContainer = document.getElementById('transcript') - -client.on("ai.speech_detect", (params) => { - const cleanText = params.text.replace(/\{confidence=[\d.]+\}/, "") - - const entry = document.createElement('div') - entry.className = 'transcript-entry user' - entry.innerHTML = ` - User: - ${cleanText} - ${new Date().toLocaleTimeString()} - ` - transcriptContainer.appendChild(entry) -}) +const client = await SignalWire({token:""}) +const callSession = await client.dial({to:"/private/swml-script"}) -client.on("ai.response_utterance", (params) => { - const entry = document.createElement('div') - entry.className = 'transcript-entry ai' - entry.innerHTML = ` - AI: - ${params.utterance} - ${new Date().toLocaleTimeString()} - ` - transcriptContainer.appendChild(entry) -}) -``` - -### Handle custom application events - -```typescript client.on("user_event", (params) => { - switch (params.action) { - case 'button_clicked': - handleButtonClick(params.buttonId) - break - case 'form_submitted': - handleFormSubmission(params.formData) - break - case 'status_update': - updateStatus(params.status) - break - default: - console.log('Unknown user event:', params) - } -}) -``` - -### Typing indicator for AI - -```typescript -let typingIndicatorTimeout - -client.on("ai.partial_result", (params) => { - const indicator = document.getElementById('ai-typing') - indicator.style.display = 'block' - indicator.textContent = 'AI is thinking...' - - clearTimeout(typingIndicatorTimeout) -}) - -client.on("ai.completion", (params) => { - typingIndicatorTimeout = setTimeout(() => { - document.getElementById('ai-typing').style.display = 'none' - }, 500) -}) -``` - -### Speech confidence tracking - -```typescript -client.on("ai.speech_detect", (params) => { - const confidenceMatch = params.text.match(/\{confidence=([\d.]+)\}/) - - if (confidenceMatch) { - const confidence = parseFloat(confidenceMatch[1]) - console.log(`Speech confidence: ${(confidence * 100).toFixed(1)}%`) - - if (confidence < 0.5) { - console.warn('Low confidence detection') - } - } -}) -``` - -### Event analytics - -```typescript -const analytics = { - totalUserMessages: 0, - totalAIResponses: 0, - interruptedResponses: 0, - customEvents: 0 -} - -client.on("ai.speech_detect", () => { - analytics.totalUserMessages++ -}) - -client.on("ai.completion", (params) => { - analytics.totalAIResponses++ - if (params.type === 'barged') { - analytics.interruptedResponses++ - } -}) - -client.on("user_event", () => { - analytics.customEvents++ -}) - -console.log('Analytics:', analytics) -``` - -### Error handling in event listeners - -```typescript -client.on("ai.completion", (params) => { - try { - processAIResponse(params.text) - updateUI(params) - } catch (error) { - console.error('Error processing AI completion:', error) - showErrorMessage('Failed to process AI response') - } -}) - -client.on("user_event", (params) => { - try { - handleCustomEvent(params) - } catch (error) { - console.error('Error handling user event:', error) - } + console.log('User event received:', params) }) ``` -## Best practices - -### Remove event listeners - -Always remove event listeners when they're no longer needed to prevent memory leaks: - -```typescript -const handler = (params) => { - console.log('Event received:', params) -} - -client.on("ai.completion", handler) - -client.off("ai.completion", handler) -``` - -### Use event namespacing - -Group related event handlers for easier management: - -```typescript -class AIConversationManager { - constructor(client) { - this.client = client - this.setupEventListeners() - } - - setupEventListeners() { - this.client.on("ai.speech_detect", this.handleSpeech.bind(this)) - this.client.on("ai.completion", this.handleCompletion.bind(this)) - this.client.on("ai.partial_result", this.handlePartial.bind(this)) - } - - handleSpeech(params) { - } - - handleCompletion(params) { - } - - handlePartial(params) { - } - - cleanup() { - this.client.off("ai.speech_detect", this.handleSpeech) - this.client.off("ai.completion", this.handleCompletion) - this.client.off("ai.partial_result", this.handlePartial) - } -} -``` - -### Debounce rapid events - -For events that fire frequently, consider debouncing: - -```typescript -let partialResultTimeout - -client.on("ai.partial_result", (params) => { - clearTimeout(partialResultTimeout) - - partialResultTimeout = setTimeout(() => { - updatePartialResult(params.text) - }, 100) -}) -``` +For more details on writing SWML scripts to send custom events, see the [user_event](/swml/methods/user_event) SWML method. \ No newline at end of file diff --git a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/get-subscriber-info.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/get-subscriber-info.mdx index a31e2e062..93c73d3b4 100644 --- a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/get-subscriber-info.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/get-subscriber-info.mdx @@ -5,30 +5,15 @@ slug: /signalwire-client/get-subscriber-info import APIField from '@site/src/components/APIField'; -Retrieves information about the current subscriber, including capabilities, permissions, and account details. +The `getSubscriberInfo` method queries the SignalWire platform for detailed information about the authenticated subscriber. +This includes all the details filled in while creating the subscriber from the Dashboard or the +[Create Subscriber REST API](/rest/signalwire-rest/endpoints/fabric/subscribers-create)). -## How it works +This includes the subscriber's name, email, country, region, job and whatever other fields are filled in. -The `getSubscriberInfo` method queries the SignalWire platform for detailed information about the authenticated subscriber. This includes what features the subscriber has access to, their permissions, and configuration settings. +In addition, it includes the subscriber's push notification key (if any) and their addresses. -## Key concepts - -### Subscriber information - -The response typically includes: -- Subscriber ID -- Display name -- Capabilities and permissions -- Available features -- Account settings - -### Use cases - -Common uses for subscriber info: -- Checking available features before showing UI -- Validating permissions before actions -- Displaying user profile information -- Customizing UI based on capabilities +For full type information of the response, see the [`GetSubscriberInfoResponse`](../Types#getsubscriberinforesponse) type. ## Parameters @@ -42,7 +27,7 @@ getSubscriberInfo(): Promise ## Returns -**Type:** `Promise` +**Type:** `Promise<`[`GetSubscriberInfoResponse`](../Types#getsubscriberinforesponse)`>` Returns a Promise that resolves with subscriber information including capabilities and permissions. @@ -55,133 +40,4 @@ const info = await client.getSubscriberInfo() console.log('Subscriber ID:', info.id) console.log('Display name:', info.displayName) -``` - -### Check capabilities - -```typescript -const info = await client.getSubscriberInfo() - -if (info.capabilities.canMakeOutboundCalls) { - console.log('Outbound calling is enabled') -} else { - console.log('Outbound calling is disabled') -} -``` - -### Display user profile - -```typescript -async function showUserProfile() { - const info = await client.getSubscriberInfo() - - document.getElementById('user-name').textContent = info.displayName - document.getElementById('user-id').textContent = info.id - document.getElementById('user-email').textContent = info.email -} - -showUserProfile() -``` - -### Customize UI based on capabilities - -```typescript -const info = await client.getSubscriberInfo() - -const dialButton = document.getElementById('dial-btn') -dialButton.disabled = !info.capabilities.canMakeOutboundCalls - -const videoButton = document.getElementById('video-btn') -videoButton.disabled = !info.capabilities.hasVideoAccess -``` - -### Log subscriber details - -```typescript -const info = await client.getSubscriberInfo() - -console.log('Subscriber Info:', { - id: info.id, - name: info.displayName, - features: info.features, - permissions: info.permissions -}) -``` - -### Error handling - -```typescript -try { - const info = await client.getSubscriberInfo() - console.log('Retrieved subscriber info:', info) -} catch (error) { - console.error('Failed to get subscriber info:', error) -} -``` - -### Cache subscriber info - -```typescript -let cachedSubscriberInfo = null - -async function getSubscriberInfoCached() { - if (!cachedSubscriberInfo) { - cachedSubscriberInfo = await client.getSubscriberInfo() - } - return cachedSubscriberInfo -} - -const info = await getSubscriberInfoCached() -console.log('Subscriber info:', info) -``` - -### Validate permissions before action - -```typescript -async function makeVideoCall(to) { - const info = await client.getSubscriberInfo() - - if (!info.capabilities.hasVideoAccess) { - alert('Video calling is not available for your account') - return - } - - const callSession = await client.dial({ - to: to, - video: true - }) -} -``` - -### Show feature availability - -```typescript -async function updateFeatureList() { - const info = await client.getSubscriberInfo() - - const features = { - 'Outbound Calls': info.capabilities.canMakeOutboundCalls, - 'Video Calls': info.capabilities.hasVideoAccess, - 'Screen Sharing': info.capabilities.canShareScreen, - 'Recording': info.capabilities.canRecord - } - - for (const [feature, available] of Object.entries(features)) { - console.log(`${feature}: ${available ? 'Available' : 'Not available'}`) - } -} -``` - -### Refresh info on token update - -```typescript -async function refreshToken(newToken) { - await client.updateToken(newToken) - - const info = await client.getSubscriberInfo() - console.log('Updated subscriber info:', info) - - updateUIWithNewCapabilities(info) -} -``` - +``` \ No newline at end of file diff --git a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/handle-push-notification.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/handle-push-notification.mdx index a9c1a4c3b..849fc37c9 100644 --- a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/handle-push-notification.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/handle-push-notification.mdx @@ -5,53 +5,64 @@ slug: /signalwire-client/handle-push-notification import APIField from '@site/src/components/APIField'; -Processes incoming push notifications for call or message events, allowing the app to respond appropriately when a notification is received. +Processes incoming push notifications for call or message events, decrypting the encrypted payload and preparing the client to handle the incoming event. ## How it works -The `handlePushNotification` method processes push notification payloads received from the platform's notification system. It extracts call or message information and prepares the client to handle the incoming event. +The `handlePushNotification` method processes encrypted push notification payloads received from the platform's notification system (APNS for iOS, FCM for Android). SignalWire sends all push notifications encrypted using AES-256-GCM encryption. -## Key concepts +The method: +1. Retrieves the `push_notification_key` that was stored during device registration +2. Extracts the encrypted invite from the platform-specific payload structure +3. Decrypts the invite using the encryption key, IV, and authentication tag +4. Decompresses the decrypted invite to get the SDP information +5. Returns a Call object that can be answered or declined -### Notification flow +## Parameters -1. SignalWire sends push notification to device -2. Platform delivers notification to app -3. App calls `handlePushNotification` with payload -4. Client processes and triggers appropriate handlers + + The push notification payload received from the platform's notification system. + -### Platform integration +### iOS payload structure -This method integrates with: -- **iOS:** APNs notifications -- **Android:** FCM notifications -- **Web:** Service Worker notifications + + Contains the encrypted notification data on iOS devices. + -## Parameters + + Base64-encoded encrypted invite data. + + + + The encryption algorithm used (always 'aes_256_gcm'). + - - The push notification payload to process. + + Base64-encoded initialization vector for decryption. - - The platform-specific notification data. + + Base64-encoded authentication tag for AES-GCM. - - Custom data payload from the notification. +### Android payload structure + + + JSON string containing the encrypted notification data on Android devices. ## Signature ```typescript -handlePushNotification(params: HandlePushNotificationParams): Promise +handlePushNotification(payload: IHandlePushNotificationParams): Promise ``` ## Returns -**Type:** `Promise` +**Type:** `Promise` -Returns a Promise that resolves with information about the processed notification. +Returns a Promise that resolves with a Call object if successful, or null if the notification couldn't be processed. ## Examples @@ -59,149 +70,93 @@ Returns a Promise that resolves with information about the processed notificatio ```typescript async function onNotificationReceived(notification) { - const result = await client.handlePushNotification({ - notification: notification - }) + const pnKey = await AsyncStorage.getItem( + '@signalwire_push_notification_key' + ) - console.log('Notification processed:', result) -} -``` - -### Handle Android FCM notification - -```typescript -messaging.onMessage(async (payload) => { - const result = await client.handlePushNotification({ - notification: payload - }) + if (!pnKey) { + console.error('Push notification key not found. Did you call registerDevice()?') + return + } - console.log('FCM notification handled:', result) -}) -``` - -### Handle notification when app is closed - -```typescript -async function handleBackgroundNotification(notificationData) { - await client.online({ - incomingCallHandlers: { - onCallReceived: (call) => { - console.log('Incoming call from notification') - showCallUI(call) - } - } - }) + const call = await client.handlePushNotification(notification) - await client.handlePushNotification({ - notification: notificationData - }) + if (call) { + console.log('Incoming call from:', call.remotePeer) + } } ``` -### Extract call information +### Handle Android push notification ```typescript -async function processCallNotification(notification) { - const result = await client.handlePushNotification({ - notification: notification - }) +messaging().setBackgroundMessageHandler(async (remoteMessage) => { + const call = await client.handlePushNotification(remoteMessage) - if (result.type === 'call') { - console.log('Incoming call from:', result.from) - console.log('Call ID:', result.callId) + if (call) { + await call.answer() } -} +}) ``` -### Show notification UI +### Complete implementation with decryption ```typescript -async function handleNotification(notification) { - const result = await client.handlePushNotification({ - notification: notification - }) +client.handlePushNotification = async (payload) => { + const pnKeyB64 = await AsyncStorage.getItem( + '@signalwire_push_notification_key' + ) - if (result.type === 'call') { - showIncomingCallScreen({ - caller: result.from, - callId: result.callId - }) - } else if (result.type === 'message') { - showMessageNotification({ - message: result.content, - sender: result.from - }) + if (!pnKeyB64) { + console.error('Push notification decryption key not found') + return null } -} -``` - -### Error handling - -```typescript -try { - const result = await client.handlePushNotification({ - notification: notificationPayload - }) - console.log('Notification handled successfully') -} catch (error) { - console.error('Failed to handle notification:', error) -} -``` - -### Handle notification with deep linking -```typescript -async function handleNotificationTap(notification) { - const result = await client.handlePushNotification({ - notification: notification - }) - - if (result.type === 'call' && result.callId) { - window.location.href = `/call/${result.callId}` - } else if (result.type === 'message' && result.conversationId) { - window.location.href = `/conversation/${result.conversationId}` + let corePayload + if (payload?.aps?.alert) { + corePayload = payload.aps.alert + } else if (typeof payload?.notification?.body === 'string') { + try { + corePayload = JSON.parse(payload.notification.body) + } catch (e) { + console.error('Failed to parse notification body') + return null + } } -} -``` -### Log notification handling + if (!corePayload?.invite) { + console.error('Push notification payload is ill-formed') + return null + } -```typescript -async function logAndHandleNotification(notification) { - console.log('Received notification:', notification) - - const result = await client.handlePushNotification({ - notification: notification - }) - - console.log('Notification processing result:', { - type: result.type, - timestamp: new Date().toISOString() - }) -} -``` + let invite = corePayload.invite + + if (corePayload.encryption_type === 'aes_256_gcm') { + const ivHex = Buffer.from(corePayload.iv, 'base64').toString('hex') + const tagHex = Buffer.from(corePayload.tag, 'base64').toString('hex') + + try { + invite = await AesGcmCrypto.decrypt( + corePayload.invite, + pnKeyB64, + ivHex, + tagHex, + true + ) + } catch (e) { + console.error('Decryption failed:', e) + return null + } + } -### Handle multiple notification types + const decompressedInvite = pako.inflate(Buffer.from(invite, 'base64')) + const sdpJson = JSON.parse(Buffer.from(decompressedInvite).toString('utf8')) -```typescript -async function processNotification(notification) { - const result = await client.handlePushNotification({ - notification: notification + const call = client._handlePushNotification({ + ...corePayload, + decrypted: sdpJson, }) - switch (result.type) { - case 'call': - handleIncomingCall(result) - break - case 'message': - handleIncomingMessage(result) - break - case 'voicemail': - handleVoicemail(result) - break - default: - console.log('Unknown notification type:', result.type) - } + return call } ``` - diff --git a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/offline.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/offline.mdx index 7507213ea..40c08d307 100644 --- a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/offline.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/offline.mdx @@ -1,30 +1,14 @@ --- title: offline slug: /signalwire-client/offline +description: Takes the client offline, preventing reception of new incoming calls and messages while maintaining the connection. --- import APIField from '@site/src/components/APIField'; -Takes the client offline, preventing reception of new incoming calls and messages while maintaining the connection. +The `offline` method changes the client's availability state to offline. Unlike `disconnect`, which terminates the connection entirely, `offline` keeps the connection active but stops receiving notifications. -## How it works - -The `offline` method changes the client's availability state to offline. Unlike `disconnect`, which terminates the connection entirely, `offline` keeps the connection active but stops receiving incoming calls and messages. - -## Key concepts - -### Offline vs disconnect - -- **offline():** Maintains connection but doesn't receive calls -- **disconnect():** Completely terminates the connection - -### Use cases - -Going offline is useful when: -- User is temporarily unavailable -- App moves to background -- Do Not Disturb mode is enabled -- Temporarily pausing call reception without full disconnect +This method is the opposite of the client.[`online`](./online.mdx) method. ## Parameters diff --git a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/online.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/online.mdx index ee1f29281..b69afd074 100644 --- a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/online.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/online.mdx @@ -11,13 +11,6 @@ Brings the client online to receive incoming calls and messages. This method reg The `online` method establishes the client's availability on the SignalWire network. Once online, the client can receive incoming calls and other real-time events through the provided callback handlers. -## Key concepts - -### Availability state - -- **Offline:** Client cannot receive incoming calls or messages -- **Online:** Client is registered and can receive incoming calls and messages - ### Callback handlers You must provide handlers for incoming calls. These callbacks are invoked when events occur, allowing you to manage incoming calls appropriately. @@ -64,139 +57,3 @@ await client.online({ console.log('Client is now online') ``` - -### Handle incoming calls with UI - -```typescript -await client.online({ - incomingCallHandlers: { - onCallReceived: (call) => { - const notification = document.getElementById('call-notification') - notification.textContent = `Incoming call from ${call.from}` - notification.style.display = 'block' - - const answerBtn = document.getElementById('answer-btn') - answerBtn.onclick = () => { - call.answer() - notification.style.display = 'none' - } - - const rejectBtn = document.getElementById('reject-btn') - rejectBtn.onclick = () => { - call.hangup() - notification.style.display = 'none' - } - } - } -}) -``` - -### Handle call ended events - -```typescript -await client.online({ - incomingCallHandlers: { - onCallReceived: (call) => { - console.log('Incoming call:', call.id) - }, - onCallEnded: (call) => { - console.log('Call ended:', call.id) - } - } -}) -``` - -### Auto-answer incoming calls - -```typescript -await client.online({ - incomingCallHandlers: { - onCallReceived: async (call) => { - console.log('Auto-answering call from:', call.from) - await call.answer() - } - } -}) -``` - -### Log incoming call details - -```typescript -await client.online({ - incomingCallHandlers: { - onCallReceived: (call) => { - console.log('Incoming call details:', { - id: call.id, - from: call.from, - to: call.to, - timestamp: new Date().toISOString() - }) - - call.answer() - } - } -}) -``` - -### Go online after authentication - -```typescript -async function initialize() { - const token = await getAuthToken() - const client = await SignalWire.Client({ token }) - - await client.online({ - incomingCallHandlers: { - onCallReceived: (call) => { - handleIncomingCall(call) - } - } - }) - - console.log('Client initialized and online') -} - -initialize() -``` - -### Toggle online/offline state - -```typescript -let isOnline = false - -async function toggleOnlineState() { - if (isOnline) { - await client.offline() - console.log('Now offline') - } else { - await client.online({ - incomingCallHandlers: { - onCallReceived: (call) => { - console.log('Incoming call:', call.id) - } - } - }) - console.log('Now online') - } - - isOnline = !isOnline -} -``` - -### Error handling - -```typescript -try { - await client.online({ - incomingCallHandlers: { - onCallReceived: (call) => { - console.log('Incoming call:', call.id) - } - } - }) - console.log('Successfully online') -} catch (error) { - console.error('Failed to go online:', error) -} -``` - diff --git a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/reattach.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/reattach.mdx index 24b8651eb..81d3dd8fc 100644 --- a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/reattach.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/reattach.mdx @@ -11,22 +11,6 @@ Reattaches to an existing call session using a call ID. This is useful for recon The `reattach` method allows you to reconnect to an active call that you were previously part of. By providing the call ID, you can restore the CallSession object and resume control of the call. -## Key concepts - -### Call persistence - -Calls remain active on the SignalWire platform even if your client loses connection. Using `reattach` allows you to: -- Resume a call after network interruption -- Reconnect after page refresh -- Resume a call on a different device - -### Call ID storage - -To reattach to a call, you need to store the call ID. Common storage methods: -- Browser localStorage -- Session storage -- Server-side database -- URL parameters ## Parameters @@ -61,166 +45,3 @@ const callSession = await client.reattach({ console.log('Reattached to call:', callSession.id) ``` - -### Reattach with localStorage - -```typescript -const storedCallId = localStorage.getItem('activeCallId') - -if (storedCallId) { - try { - const callSession = await client.reattach({ - callId: storedCallId - }) - console.log('Reconnected to call') - } catch (error) { - console.error('Failed to reattach:', error) - localStorage.removeItem('activeCallId') - } -} -``` - -### Store call ID on dial - -```typescript -const callSession = await client.dial({ - to: '+15551234567', - from: '+15559876543' -}) - -localStorage.setItem('activeCallId', callSession.id) - -callSession.on('call.ended', () => { - localStorage.removeItem('activeCallId') -}) -``` - -### Reattach on page load - -```typescript -window.addEventListener('load', async () => { - const activeCallId = localStorage.getItem('activeCallId') - - if (activeCallId) { - try { - const callSession = await client.reattach({ - callId: activeCallId - }) - - console.log('Reattached to active call') - setupCallUI(callSession) - } catch (error) { - console.log('No active call to reattach') - localStorage.removeItem('activeCallId') - } - } -}) -``` - -### Reattach with network recovery - -```typescript -let currentCallId = null - -window.addEventListener('online', async () => { - if (currentCallId) { - try { - const callSession = await client.reattach({ - callId: currentCallId - }) - console.log('Reconnected to call after network recovery') - } catch (error) { - console.error('Could not reattach to call:', error) - currentCallId = null - } - } -}) - -window.addEventListener('offline', () => { - console.log('Network connection lost') -}) -``` - -### Reattach with retry logic - -```typescript -async function reattachWithRetry(callId, maxRetries = 3) { - for (let i = 0; i < maxRetries; i++) { - try { - const callSession = await client.reattach({ callId }) - console.log('Successfully reattached') - return callSession - } catch (error) { - console.log(`Reattach attempt ${i + 1} failed`) - - if (i < maxRetries - 1) { - await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1))) - } - } - } - - throw new Error('Failed to reattach after multiple attempts') -} - -const callSession = await reattachWithRetry('call-id') -``` - -### Reattach button in UI - -```typescript -const reattachButton = document.getElementById('reattach-btn') -const callIdInput = document.getElementById('call-id-input') - -reattachButton.addEventListener('click', async () => { - const callId = callIdInput.value - - if (!callId) { - alert('Please enter a call ID') - return - } - - try { - const callSession = await client.reattach({ callId }) - console.log('Reattached to call:', callSession.id) - setupCallControls(callSession) - } catch (error) { - alert('Failed to reattach to call') - console.error(error) - } -}) -``` - -### Track call state after reattach - -```typescript -const callSession = await client.reattach({ - callId: storedCallId -}) - -console.log('Current call state:', callSession.state) - -callSession.on('call.state', (event) => { - console.log('Call state changed:', event.call.state) -}) -``` - -### Multiple device scenario - -```typescript -async function transferCallToDevice(callId) { - localStorage.setItem('transferredCallId', callId) - - window.location.href = '/call-page' -} - -async function receiveTransferredCall() { - const callId = localStorage.getItem('transferredCallId') - - if (callId) { - const callSession = await client.reattach({ callId }) - localStorage.removeItem('transferredCallId') - return callSession - } -} -``` - diff --git a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/register-device.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/register-device.mdx index 5896b3eb1..38c296d30 100644 --- a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/register-device.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/register-device.mdx @@ -9,172 +9,100 @@ Registers a device for push notifications, enabling the client to receive calls ## How it works -The `registerDevice` method registers your device with SignalWire's push notification system. Once registered, your device can receive notifications for incoming calls and messages even when the app is not actively running. +The `registerDevice` method registers your device with SignalWire's push notification system. You call this method AFTER receiving the push notification token from your device's operating system (APNS for iOS, FCM for Android). -## Key concepts - -### Platform-specific tokens - -Different platforms use different token formats: -- **iOS:** APNs device token -- **Android:** FCM registration token -- **Web:** Service Worker registration - -### Token lifecycle - -Device tokens can change and should be re-registered when: -- App is reinstalled -- Token expires or is refreshed -- User logs in on a new device +Once registered, your device can receive encrypted push notifications for incoming calls and messages. The response includes a `push_notification_key` that you must store securely, as it's required to decrypt incoming push notifications. ## Parameters - + Configuration for device registration. - - The platform-specific push notification token. + + The token you receive from the device after getting notification permission from the user. - - The platform type for the device. - - - - Optional unique identifier for the device. + + The device platform type. ## Signature ```typescript -registerDevice(params: RegisterDeviceParams): Promise +registerDevice(options: RegisterDeviceParams): Promise ``` ## Returns **Type:** `Promise` -Returns a Promise that resolves when the device is successfully registered. - -## Examples +Returns a Promise that resolves with device registration details including the encryption key for push notifications. -### Register iOS device +### Response structure -```typescript -const response = await client.registerDevice({ - deviceToken: 'apns-token-here', - platform: 'ios' -}) - -console.log('Device registered:', response) -``` + + ID of the current device registration. Use this when unregistering the device. + -### Register Android device + + Echo of the deviceToken that was sent during registration. + -```typescript -const response = await client.registerDevice({ - deviceToken: 'fcm-token-here', - platform: 'android' -}) + + Echo of the deviceType that was sent during registration. + -console.log('Device registered:', response) -``` + + Not yet implemented. + -### Register with device ID + + Encryption key for decrypting push notifications. Store this securely as it's required by handlePushNotification(). + -```typescript -const deviceId = localStorage.getItem('deviceId') || crypto.randomUUID() -localStorage.setItem('deviceId', deviceId) + + ISO 8601 timestamp when the device was registered. + -await client.registerDevice({ - deviceToken: 'push-token-here', - platform: 'ios', - deviceId: deviceId -}) -``` +## Examples -### Register on app launch +### Register iOS device ```typescript -async function initializeApp() { - const pushToken = await getPushNotificationToken() - - await client.registerDevice({ - deviceToken: pushToken, - platform: 'ios' +async function onTokenReceived(token) { + const registrationInfo = await client.registerDevice({ + deviceToken: token, + deviceType: 'iOS' }) - console.log('Device registered for push notifications') + await AsyncStorage.setItem( + '@signalwire_device_id', + registrationInfo.id + ) + await AsyncStorage.setItem( + '@signalwire_push_notification_key', + registrationInfo.push_notification_key + ) } - -initializeApp() ``` -### Handle token refresh - -```typescript -async function onTokenRefresh(newToken) { - try { - await client.registerDevice({ - deviceToken: newToken, - platform: 'android' - }) - console.log('Updated device token') - } catch (error) { - console.error('Failed to update device token:', error) - } -} -``` - -### Error handling +### Register Android device ```typescript -try { - await client.registerDevice({ - deviceToken: 'device-token', - platform: 'ios' - }) - console.log('Device registration successful') -} catch (error) { - console.error('Device registration failed:', error) -} -``` - -### Register with user preferences +const registrationInfo = await client.registerDevice({ + deviceToken: 'fcm-token-here', + deviceType: 'Android' +}) -```typescript -async function registerWithPreferences(enablePush) { - if (!enablePush) { - console.log('Push notifications disabled by user') - return - } - - const token = await requestPushPermission() - - if (token) { - await client.registerDevice({ - deviceToken: token, - platform: 'ios' - }) - console.log('Push notifications enabled') - } -} +console.log('Device registered:', registrationInfo.id) ``` -### Re-register after login +### Register desktop device ```typescript -async function onUserLogin(userId) { - const deviceToken = await getDeviceToken() - - await client.registerDevice({ - deviceToken: deviceToken, - platform: 'android', - deviceId: `${userId}-${deviceToken.slice(0, 8)}` - }) - - console.log('Device registered for user:', userId) -} +const registrationInfo = await client.registerDevice({ + deviceToken: 'desktop-token', + deviceType: 'Desktop' +}) ``` - diff --git a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/unregister-device.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/unregister-device.mdx index 963ed1b7b..ec8845984 100644 --- a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/unregister-device.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/unregister-device.mdx @@ -9,173 +9,55 @@ Unregisters a device from push notifications, stopping the delivery of push noti ## How it works -The `unregisterDevice` method removes your device from SignalWire's push notification system. After unregistering, your device will no longer receive push notifications for incoming calls or messages. - -## Key concepts - -### When to unregister - -Unregister devices when: -- User logs out -- User disables push notifications in settings -- App is being uninstalled -- Device token is no longer valid - -### Re-registration - -If the user wants to receive notifications again, you'll need to call `registerDevice` with a new token. +The `unregisterDevice` method removes your device from SignalWire's push notification system using the device ID that was returned during registration. After unregistering, your device will no longer receive push notifications for incoming calls or messages. ## Parameters - + Configuration for device unregistration. - - The device token that was previously registered. - - - - Optional device identifier used during registration. + + The ID of the device that you need to unregister. This ID is returned when registering the device. ## Signature ```typescript -unregisterDevice(params: UnregisterDeviceParams): Promise +unregisterDevice(options: { id: string }): Promise<{}> ``` ## Returns -**Type:** `Promise` +**Type:** `Promise<{}>` -Returns a Promise that resolves when the device is successfully unregistered. +Returns a Promise that resolves to an empty object when successful. Throws an error if unsuccessful. ## Examples -### Basic unregister +### Unregister a device ```typescript -await client.unregisterDevice({ - deviceToken: 'device-token-here' +const device = await client.registerDevice({ + deviceToken: 'device-token', + deviceType: 'iOS' }) -console.log('Device unregistered') +await AsyncStorage.setItem('@signalwire_device_id', device.id) + +await client.unregisterDevice({ id: device.id }) ``` ### Unregister on logout ```typescript async function logout() { - const deviceToken = localStorage.getItem('deviceToken') - - if (deviceToken) { - await client.unregisterDevice({ - deviceToken: deviceToken - }) - } - - await client.disconnect() - localStorage.clear() - - console.log('Logged out and device unregistered') -} -``` - -### Unregister with device ID - -```typescript -const deviceId = localStorage.getItem('deviceId') -const deviceToken = localStorage.getItem('deviceToken') - -await client.unregisterDevice({ - deviceToken: deviceToken, - deviceId: deviceId -}) -``` - -### Unregister when disabling notifications - -```typescript -async function togglePushNotifications(enabled) { - const deviceToken = localStorage.getItem('deviceToken') - - if (enabled) { - await client.registerDevice({ - deviceToken: deviceToken, - platform: 'ios' - }) - console.log('Push notifications enabled') - } else { - await client.unregisterDevice({ - deviceToken: deviceToken - }) - console.log('Push notifications disabled') - } -} -``` - -### Error handling - -```typescript -try { - await client.unregisterDevice({ - deviceToken: 'device-token' - }) - console.log('Successfully unregistered device') -} catch (error) { - console.error('Failed to unregister device:', error) -} -``` - -### Unregister on app uninstall - -```typescript -window.addEventListener('beforeunload', async () => { - const isAppUninstalling = checkIfUninstalling() + const deviceId = await AsyncStorage.getItem('@signalwire_device_id') - if (isAppUninstalling) { - const deviceToken = localStorage.getItem('deviceToken') - - await client.unregisterDevice({ - deviceToken: deviceToken - }) + if (deviceId) { + await client.unregisterDevice({ id: deviceId }) + await AsyncStorage.removeItem('@signalwire_device_id') + await AsyncStorage.removeItem('@signalwire_push_notification_key') } -}) -``` - -### Cleanup multiple devices - -```typescript -async function cleanupOldDevices(deviceTokens) { - await Promise.all( - deviceTokens.map(token => - client.unregisterDevice({ deviceToken: token }) - ) - ) - - console.log('Cleaned up old device registrations') } ``` - -### Unregister with UI toggle - -```typescript -const notificationToggle = document.getElementById('notification-toggle') - -notificationToggle.addEventListener('change', async (e) => { - const deviceToken = localStorage.getItem('deviceToken') - - if (e.target.checked) { - await client.registerDevice({ - deviceToken: deviceToken, - platform: 'android' - }) - } else { - await client.unregisterDevice({ - deviceToken: deviceToken - }) - } -}) -``` - From a747d8492f3dbece71d5923e5d43f3d8703f59a7 Mon Sep 17 00:00:00 2001 From: nirav Date: Thu, 16 Oct 2025 12:11:28 +0545 Subject: [PATCH 05/12] newintro --- website/docs/signalwire-client-sdk/index.mdx | 25 ++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/website/docs/signalwire-client-sdk/index.mdx b/website/docs/signalwire-client-sdk/index.mdx index 2f5bc82a8..12d016f17 100644 --- a/website/docs/signalwire-client-sdk/index.mdx +++ b/website/docs/signalwire-client-sdk/index.mdx @@ -7,6 +7,7 @@ sidebar_custom_props: import { SiJavascript } from "react-icons/si"; import { MdCode, MdLibraryBooks } from "react-icons/md"; +import { TbApi } from "react-icons/tb"; "]}' ``` +This [Create Guest Tokens](/rest/signalwire-rest/endpoints/fabric/guest-tokens-create) endpoint +will give you a JSON response with a `token` property. To quickly get started, you can +choose to run the endpoint directly from the +[Guest Tokens documentation page](/rest/signalwire-rest/endpoints/fabric/guest-tokens-create). + The API credentials can be found in your dashboard. To learn how to find it, see [Your Credentials](/platform/dashboard/getting-started/your-signalwire-api-space) page. @@ -264,6 +270,25 @@ callSession.hangup(); +### Next steps and variations + +If you're coming from other providers, you might find our compatibility XML offering [cXML](/compatibility-api/cxml) easier. +It can be created and dialed to the same as SWML. To get the full feature set of our platform, we still recommend using SWML. + +Of course, scripts are not the only things to dial to. You can try dialing phone numbers directly, in e.164 format, or SIP addresses. + +Similarly, you can create AI agents either through the dashboard, or directly in SWML. + + + } + /> + + + + ## Explore the SDK From 6a62ac260da5ff367bad089e74816305fdb1a389 Mon Sep 17 00:00:00 2001 From: nirav Date: Thu, 16 Oct 2025 12:57:13 +0545 Subject: [PATCH 06/12] fix broken links --- .../about_call_fabric.mdx | 2 +- .../Address/address-get-address.mdx | 4 +-- .../Address/address-get-addresses.mdx | 2 +- .../tech-ref/SignalWireClient/dial.mdx | 4 +-- .../SignalWireClient/get-subscriber-info.mdx | 4 +-- .../tech-ref/SignalWireClient/index.mdx | 34 +++++++++---------- .../tech-ref/authentication.mdx | 4 +-- .../tech-ref/call-session/events.mdx | 8 ++--- .../tech-ref/call-session/index.mdx | 8 ++--- .../call-session/methods/set-audio-flags.mdx | 2 +- .../call-session/methods/set-layout.mdx | 2 +- .../call-session/methods/set-positions.mdx | 2 +- .../methods/start-screen-share.mdx | 2 +- 13 files changed, 39 insertions(+), 39 deletions(-) diff --git a/website/docs/signalwire-client-sdk/about_call_fabric.mdx b/website/docs/signalwire-client-sdk/about_call_fabric.mdx index 7a7d0f089..94881942d 100644 --- a/website/docs/signalwire-client-sdk/about_call_fabric.mdx +++ b/website/docs/signalwire-client-sdk/about_call_fabric.mdx @@ -6,7 +6,7 @@ manage customer interactions. To support this new paradigm, SignalWire has created a new SDK called the [SignalWire SDK](./index.mdx). This new SDK is designed to run on the user's browser and allow for communication to all resources via the assigned addresses. -This new SDK replaces the older [SignalWire Browser SDK](./sdks/browser-sdk/). +This new SDK replaces the older [SignalWire Browser SDK](/sdks/browser-sdk/). :::info Looking for more details? diff --git a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Address/address-get-address.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Address/address-get-address.mdx index 77be9a12d..e75febbab 100644 --- a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Address/address-get-address.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Address/address-get-address.mdx @@ -8,7 +8,7 @@ import APIField from '@site/src/components/APIField'; Retrieves detailed information about a specific address by its ID or by its name. The response includes the preview URL, display name, resource type, available channels, lock status, and timestamps. -For full type information, see the [`GetAddressResult`](../Types#getaddressresult) type. +For full type information, see the [`GetAddressResult`](../../Types/index.mdx#getaddressresult) type. ## Parameters @@ -24,7 +24,7 @@ address.getAddress(addressId: string): Promise ## Returns -**Type:** `Promise<`[`GetAddressResult`](../Types#getaddressresult)`>` +**Type:** `Promise<`[`GetAddressResult`](../../Types/index.mdx#getaddressresult)`>` Returns a Promise that resolves with detailed information about the requested address. diff --git a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Address/address-get-addresses.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Address/address-get-addresses.mdx index 9c5309cc3..47e98d313 100644 --- a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Address/address-get-addresses.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/Address/address-get-addresses.mdx @@ -46,7 +46,7 @@ address.getAddresses(params?: GetAddressesParams): Promise Returns a Promise that resolves with a paginated list of address details. -For full type information, see the [`GetAddressesResult`](../Types#getaddressesresult) type. +For full type information, see the [`GetAddressesResult`](../../Types/index.mdx#getaddressesresult) type. ## Examples diff --git a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/dial.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/dial.mdx index b73a9c9fd..8cf7225a3 100644 --- a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/dial.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/dial.mdx @@ -5,7 +5,7 @@ slug: /signalwire-client/dial import APIField from '@site/src/components/APIField'; -Initiates an outbound call to a destination and returns a [CallSession](../call-session) object for managing the active call. +Initiates an outbound call to a destination and returns a [CallSession](../call-session/index.mdx) object for managing the active call. ## Signature @@ -88,7 +88,7 @@ dial(params: DialParams): Promise **Type:** `Promise` -Returns a Promise that resolves to a [CallSession](../CallSession) object representing the active call. +Returns a Promise that resolves to a [CallSession](../call-session/index.mdx) object representing the active call. ## Permissions diff --git a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/get-subscriber-info.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/get-subscriber-info.mdx index 93c73d3b4..33c2e835d 100644 --- a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/get-subscriber-info.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/get-subscriber-info.mdx @@ -13,7 +13,7 @@ This includes the subscriber's name, email, country, region, job and whatever ot In addition, it includes the subscriber's push notification key (if any) and their addresses. -For full type information of the response, see the [`GetSubscriberInfoResponse`](../Types#getsubscriberinforesponse) type. +For full type information of the response, see the [`GetSubscriberInfoResponse`](/types#getsubscriberinforesponse) type. ## Parameters @@ -27,7 +27,7 @@ getSubscriberInfo(): Promise ## Returns -**Type:** `Promise<`[`GetSubscriberInfoResponse`](../Types#getsubscriberinforesponse)`>` +**Type:** `Promise<`[`GetSubscriberInfoResponse`](../Types/index.mdx#getsubscriberinforesponse)`>` Returns a Promise that resolves with subscriber information including capabilities and permissions. diff --git a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/index.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/index.mdx index 1c11b8264..b654c1f31 100644 --- a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/index.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/index.mdx @@ -5,7 +5,7 @@ slug: /signalwire-client import APIField from '@site/src/components/APIField'; -The SignalWire Client ([`SignalWireContract`](../Types#signalwirecontract)) is the main entry point for the SignalWire SDK. It provides methods for managing calls, conversations, device registration, and real-time communication. +The SignalWire Client ([`SignalWireContract`](/types#signalwirecontract)) is the main entry point for the SignalWire SDK. It provides methods for managing calls, conversations, device registration, and real-time communication. ## Core methods @@ -17,7 +17,7 @@ The SignalWire Client ([`SignalWireContract`](../Types#signalwirecontract)) is t Disconnects from the SignalWire network and cleans up all active resources. - + Brings the client online to receive incoming calls and messages. Requires callback handlers for incoming calls. @@ -25,21 +25,21 @@ The SignalWire Client ([`SignalWireContract`](../Types#signalwirecontract)) is t Takes the client offline, preventing reception of new incoming calls and messages. - + Reattaches to an existing call session using a call ID. Useful for reconnecting after network interruptions. ## Device management - + Registers a device for push notifications. Required for receiving calls when the app is in the background. - + Unregisters a device from push notifications. - + Processes incoming push notifications for call or message events. @@ -73,19 +73,19 @@ The `address` namespace provides methods for managing and retrieving address inf The `chat` namespace provides methods for real-time chat functionality within calls. - + Retrieves chat messages from a conversation. - + Joins a chat conversation. - + Sends a message in a chat conversation. - + Subscribes to real-time chat message events. @@ -93,27 +93,27 @@ The `chat` namespace provides methods for real-time chat functionality within ca The `conversation` namespace provides methods for managing persistent conversations and messaging. - + Retrieves messages from a specific conversation. - + Retrieves a list of conversations. - + Retrieves messages across conversations. - + Joins a conversation. - + Sends a message in a conversation. - + Subscribes to real-time conversation events. @@ -123,4 +123,4 @@ The `conversation` namespace provides methods for managing persistent conversati ## See also -- [Events](/signalwire-client/events) - Available events for the SignalWire Client \ No newline at end of file +- [Events](./events.mdx) - Available events for the SignalWire Client \ No newline at end of file diff --git a/website/docs/signalwire-client-sdk/tech-ref/authentication.mdx b/website/docs/signalwire-client-sdk/tech-ref/authentication.mdx index 7217c6825..c213bf47d 100644 --- a/website/docs/signalwire-client-sdk/tech-ref/authentication.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/authentication.mdx @@ -8,7 +8,7 @@ sidebar_position: 1 The SignalWire Client SDK is a browser-side library. The source code for all browser-side code is publicly available, so we cannot use the same token authentication method as the REST API. -Authentication is scoped to [subscribers](./about_call_fabric#subscribers). +Authentication is scoped to [subscribers](/sdks/signalwire-client-sdk/about_call_fabric#subscribers). You can create subscribers either through the dashboard or through the REST API. For temporary usage, you can create a guest token which creates a temporary subscriber with limited permissions to access only the specified `allowed_address`. @@ -270,7 +270,7 @@ Use this comparison table to select the authentication method that best fits you ## Using the Token -After you have received the access token by an authentication method, you can use that token to initialize the [SignalWire Client](./signalwire-client): +After you have received the access token by an authentication method, you can use that token to initialize the [SignalWire Client](./SignalWireClient/index.mdx): ```js import { SignalWire } from "@signalwire/client"; diff --git a/website/docs/signalwire-client-sdk/tech-ref/call-session/events.mdx b/website/docs/signalwire-client-sdk/tech-ref/call-session/events.mdx index 749195b6c..616c32c37 100644 --- a/website/docs/signalwire-client-sdk/tech-ref/call-session/events.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/call-session/events.mdx @@ -33,7 +33,7 @@ Fired when you successfully join a call. Your member ID. - + Your permissions and capabilities for this call session. @@ -404,7 +404,7 @@ call.on('room.left', (event) => { Fired when a new member joins the call. - + The member object with all properties. @@ -448,7 +448,7 @@ call.on('member.updated', (event) => { Fired when a member leaves the call. - + The member who left. @@ -661,7 +661,7 @@ call.on('member.updated.noiseSuppression', (event) => { Fired when the video layout changes. - + Layout object with name and layers. diff --git a/website/docs/signalwire-client-sdk/tech-ref/call-session/index.mdx b/website/docs/signalwire-client-sdk/tech-ref/call-session/index.mdx index f16822988..77d2dcdef 100644 --- a/website/docs/signalwire-client-sdk/tech-ref/call-session/index.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/call-session/index.mdx @@ -81,7 +81,7 @@ call.on('destroy', () => { ``` - + The full layout changed event object containing the current layout and all member positions. Updated automatically when the room layout changes. ```typescript @@ -100,7 +100,7 @@ call.on('destroy', () => { ``` - + Your current position within the video layout, or `undefined` if not found in any layer. ```typescript @@ -111,7 +111,7 @@ call.on('destroy', () => { ``` - + Defines what actions are allowed for this call session based on your role and permissions. ```typescript @@ -126,7 +126,7 @@ call.on('destroy', () => { ``` - + Array of active screen sharing sessions in this call. ```typescript diff --git a/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/set-audio-flags.mdx b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/set-audio-flags.mdx index 841292bf4..9ca5509c5 100644 --- a/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/set-audio-flags.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/set-audio-flags.mdx @@ -15,7 +15,7 @@ setAudioFlags(params: SetAudioFlagsParams): Promise ## Parameters - + Audio processing configuration. diff --git a/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/set-layout.mdx b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/set-layout.mdx index 27ee16b81..b555b1caf 100644 --- a/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/set-layout.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/set-layout.mdx @@ -23,7 +23,7 @@ setLayout(params: SetLayoutParams): Promise Name of the layout to apply (e.g., "grid-responsive", "2x2", "6x6"). - + Map of member IDs to specific positions in the layout. diff --git a/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/set-positions.mdx b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/set-positions.mdx index 9736c8eda..05f095a4c 100644 --- a/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/set-positions.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/set-positions.mdx @@ -19,7 +19,7 @@ setPositions(params: SetPositionsParams): Promise Positioning configuration object. - + Map of member IDs to their desired positions in the layout. diff --git a/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/start-screen-share.mdx b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/start-screen-share.mdx index 3960a1e9d..b1f8a77ab 100644 --- a/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/start-screen-share.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/start-screen-share.mdx @@ -9,7 +9,7 @@ Starts screen sharing within the call, allowing you to share your screen, applic ## Parameters - + Screen share configuration options. From c282a57992482302321d21790e20dc995cd3fd38 Mon Sep 17 00:00:00 2001 From: nirav Date: Thu, 16 Oct 2025 13:09:50 +0545 Subject: [PATCH 07/12] minor --- .../signalwire-client-sdk/index.ts | 2 +- .../about_call_fabric.mdx | 27 +++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/website/config/sidebarsConfig/signalwire-client-sdk/index.ts b/website/config/sidebarsConfig/signalwire-client-sdk/index.ts index 387825d9a..ecfe8ac56 100644 --- a/website/config/sidebarsConfig/signalwire-client-sdk/index.ts +++ b/website/config/sidebarsConfig/signalwire-client-sdk/index.ts @@ -4,7 +4,7 @@ const signalwireSdkSidebar: SidebarsConfig = { signalwireSdkSidebar: [ { type: "category", - label: "Browser SDK", + label: "SignalWire Client SDK", collapsible: false, className: "menu-category", items: [ diff --git a/website/docs/signalwire-client-sdk/about_call_fabric.mdx b/website/docs/signalwire-client-sdk/about_call_fabric.mdx index 94881942d..d1f45481c 100644 --- a/website/docs/signalwire-client-sdk/about_call_fabric.mdx +++ b/website/docs/signalwire-client-sdk/about_call_fabric.mdx @@ -131,3 +131,30 @@ The Conversation API allows you to interact with those conversations in two very Based on your program requirements, you can use one or both of these APIs. + +## Recommended Application Structure + +We recommend that you keep the following things in mind when building your application: + +### Keep the client instance global and maintain persistent connection + +Rather than instantiating new client instances for each action, keep a single global client instance and +maintain a persistent connection to the SignalWire network. You can use it like a singleton. + +{/* TODO: once client manager is final, it WILL be a singleton unless multiple profiles, Update once that's out */} + +In some advanced cases, you might want to have multiple client instances with different tokens. + +### When using in a React application, ensure you don't create multiple instances. + +The `useEffect` hook makes it very easy to create multiple instances of the client or when dialing a call. +That can create race conditions and other issues, and cause your client or the call to fail. Ensure your +client instantiation and dial happens only once, and have proper cleanup. + +### Many APIs return paginated output, make sure you handle it properly + +{/* TODO: this might have to be a separate article or a guide */} + +Many APIs return paginated output, and you need to handle it properly. The SDK provides a `PaginatedResult`. + +### Ensure you `unregisterDevice` when the user logs out to ensure they don't get Push Notifications \ No newline at end of file From d850412d1a70fea2f51b1d8adf528459e7b7cb7a Mon Sep 17 00:00:00 2001 From: nirav Date: Fri, 17 Oct 2025 11:37:09 +0545 Subject: [PATCH 08/12] fix links --- .../tech-ref/SignalWireClient/get-subscriber-info.mdx | 2 +- .../tech-ref/SignalWireClient/index.mdx | 2 +- .../tech-ref/SignalWireClient/reattach.mdx | 2 +- .../tech-ref/call-session/events.mdx | 8 ++++---- .../signalwire-client-sdk/tech-ref/call-session/index.mdx | 8 ++++---- .../tech-ref/call-session/methods/set-audio-flags.mdx | 2 +- .../tech-ref/call-session/methods/set-layout.mdx | 2 +- .../tech-ref/call-session/methods/set-positions.mdx | 2 +- .../tech-ref/call-session/methods/start-screen-share.mdx | 2 +- 9 files changed, 15 insertions(+), 15 deletions(-) diff --git a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/get-subscriber-info.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/get-subscriber-info.mdx index 33c2e835d..19358d982 100644 --- a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/get-subscriber-info.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/get-subscriber-info.mdx @@ -13,7 +13,7 @@ This includes the subscriber's name, email, country, region, job and whatever ot In addition, it includes the subscriber's push notification key (if any) and their addresses. -For full type information of the response, see the [`GetSubscriberInfoResponse`](/types#getsubscriberinforesponse) type. +For full type information of the response, see the [`GetSubscriberInfoResponse`](../Types/index.mdx#getsubscriberinforesponse) type. ## Parameters diff --git a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/index.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/index.mdx index b654c1f31..5eb451850 100644 --- a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/index.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/index.mdx @@ -5,7 +5,7 @@ slug: /signalwire-client import APIField from '@site/src/components/APIField'; -The SignalWire Client ([`SignalWireContract`](/types#signalwirecontract)) is the main entry point for the SignalWire SDK. It provides methods for managing calls, conversations, device registration, and real-time communication. +The SignalWire Client ([`SignalWireContract`](types#signalwirecontract)) is the main entry point for the SignalWire SDK. It provides methods for managing calls, conversations, device registration, and real-time communication. ## Core methods diff --git a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/reattach.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/reattach.mdx index 81d3dd8fc..1732ae67d 100644 --- a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/reattach.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/reattach.mdx @@ -32,7 +32,7 @@ reattach(params: ReattachParams): Promise **Type:** `Promise` -Returns a Promise that resolves to a [CallSession](/call-session) object representing the reattached call. +Returns a Promise that resolves to a [CallSession](../call-session) object representing the reattached call. ## Examples diff --git a/website/docs/signalwire-client-sdk/tech-ref/call-session/events.mdx b/website/docs/signalwire-client-sdk/tech-ref/call-session/events.mdx index 616c32c37..74f4c14c8 100644 --- a/website/docs/signalwire-client-sdk/tech-ref/call-session/events.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/call-session/events.mdx @@ -33,7 +33,7 @@ Fired when you successfully join a call. Your member ID. - + Your permissions and capabilities for this call session. @@ -404,7 +404,7 @@ call.on('room.left', (event) => { Fired when a new member joins the call. - + The member object with all properties. @@ -448,7 +448,7 @@ call.on('member.updated', (event) => { Fired when a member leaves the call. - + The member who left. @@ -661,7 +661,7 @@ call.on('member.updated.noiseSuppression', (event) => { Fired when the video layout changes. - + Layout object with name and layers. diff --git a/website/docs/signalwire-client-sdk/tech-ref/call-session/index.mdx b/website/docs/signalwire-client-sdk/tech-ref/call-session/index.mdx index 77d2dcdef..bd1416f53 100644 --- a/website/docs/signalwire-client-sdk/tech-ref/call-session/index.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/call-session/index.mdx @@ -81,7 +81,7 @@ call.on('destroy', () => { ``` - + The full layout changed event object containing the current layout and all member positions. Updated automatically when the room layout changes. ```typescript @@ -100,7 +100,7 @@ call.on('destroy', () => { ``` - + Your current position within the video layout, or `undefined` if not found in any layer. ```typescript @@ -111,7 +111,7 @@ call.on('destroy', () => { ``` - + Defines what actions are allowed for this call session based on your role and permissions. ```typescript @@ -126,7 +126,7 @@ call.on('destroy', () => { ``` - + Array of active screen sharing sessions in this call. ```typescript diff --git a/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/set-audio-flags.mdx b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/set-audio-flags.mdx index 9ca5509c5..841292bf4 100644 --- a/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/set-audio-flags.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/set-audio-flags.mdx @@ -15,7 +15,7 @@ setAudioFlags(params: SetAudioFlagsParams): Promise ## Parameters - + Audio processing configuration. diff --git a/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/set-layout.mdx b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/set-layout.mdx index b555b1caf..27ee16b81 100644 --- a/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/set-layout.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/set-layout.mdx @@ -23,7 +23,7 @@ setLayout(params: SetLayoutParams): Promise Name of the layout to apply (e.g., "grid-responsive", "2x2", "6x6"). - + Map of member IDs to specific positions in the layout. diff --git a/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/set-positions.mdx b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/set-positions.mdx index 05f095a4c..9736c8eda 100644 --- a/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/set-positions.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/set-positions.mdx @@ -19,7 +19,7 @@ setPositions(params: SetPositionsParams): Promise Positioning configuration object. - + Map of member IDs to their desired positions in the layout. diff --git a/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/start-screen-share.mdx b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/start-screen-share.mdx index b1f8a77ab..3960a1e9d 100644 --- a/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/start-screen-share.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/call-session/methods/start-screen-share.mdx @@ -9,7 +9,7 @@ Starts screen sharing within the call, allowing you to share your screen, applic ## Parameters - + Screen share configuration options. From 87049d88f919a81d69ee7161547ba612b3c69df5 Mon Sep 17 00:00:00 2001 From: nirav Date: Fri, 17 Oct 2025 19:29:02 +0545 Subject: [PATCH 09/12] upd --- website/docs/signalwire-client-sdk/index.mdx | 99 ++++++++++++++++++- .../tech-ref/SignalWireClient/dial.mdx | 12 ++- .../tech-ref/call-session/events.mdx | 6 +- 3 files changed, 105 insertions(+), 12 deletions(-) diff --git a/website/docs/signalwire-client-sdk/index.mdx b/website/docs/signalwire-client-sdk/index.mdx index 12d016f17..490f31bcb 100644 --- a/website/docs/signalwire-client-sdk/index.mdx +++ b/website/docs/signalwire-client-sdk/index.mdx @@ -6,8 +6,9 @@ sidebar_custom_props: --- import { SiJavascript } from "react-icons/si"; -import { MdCode, MdLibraryBooks } from "react-icons/md"; -import { TbApi } from "react-icons/tb"; +import { MdCode, MdLibraryBooks, MdPhoneIphone, MdVideoCall, MdAutoAwesome, MdCallMerge, MdChatBubble, MdSecurity } from "react-icons/md"; +import { TbApi, TbBrandReactNative, TbFileCode } from "react-icons/tb"; +import { FaLayerGroup } from "react-icons/fa"; + + } + > + One consistent API for every call type—AI agents, humans, conferences, or scripts + + + } + > + Build iOS and Android apps with React Native support and VoIP push notifications for incoming calls + + + } + > + HD video calls and conferences supporting hundreds of simultaneous participants + + + } + > + Use SWML or cXML to create intelligent call flows, route between destinations, and make real-time decisions + + + } + > + Update your website UI in real-time based on AI agent output using SWML user events + + + + } + > + Route, compose, parallelize, and merge phone calls directly from the browser with powerful telephony controls + + + } + > + Subscriber-centric interaction tracking that combines chat, events, and logs in a single real-time stream + + + } + > + Build secure, frontend-only telephony applications with modern OAuth2 authentication and subscriber management + + + + ## Getting Started @@ -56,13 +120,40 @@ Or include it via CDN: Create a [SWML Resource](/platform/call-fabric/resources/swml-scripts) from the Dashboard. -```yaml andJson +{/* TODO: replace this with an AI thing ofc */} + + + + +```yaml +version: 1.0.0 +sections: + main: + - ai: + prompt: | + You are Franklin's assistant, and your job is to collect messages + for him over the phone. + You can reassure that Franklin will get in touch as soon as possible. + Collect the user's name and number if you do not already know it from + the caller id. + post_prompt: | + Summarize the message in JSON with `name`, `number` and `message` + post_prompt_url: "https://example.com/my-api" +``` + + + + +```yaml version: 1.0.0 sections: main: - play: "https://cdn.signalwire.com/swml/April_Kisses.mp3" ``` + + + Navigate to the newly created SWML Resource's `Addresses and Phone Numbers` tab, and note the Address UUID. ### Create a Guest Token for that address diff --git a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/dial.mdx b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/dial.mdx index 8cf7225a3..1a7aacf8c 100644 --- a/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/dial.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/SignalWireClient/dial.mdx @@ -5,7 +5,11 @@ slug: /signalwire-client/dial import APIField from '@site/src/components/APIField'; -Initiates an outbound call to a destination and returns a [CallSession](../call-session/index.mdx) object for managing the active call. +Initiates an outbound call to a destination and returns a +[CallSession](../call-session/index.mdx) object for managing the active call. + +The `dial()` method is one of the primary methods of initiating an interaction in SignalWire. +You can use it to dial phone numbers, SIP addresses, or any address that is assigned to a resource. ## Signature @@ -90,10 +94,6 @@ dial(params: DialParams): Promise Returns a Promise that resolves to a [CallSession](../call-session/index.mdx) object representing the active call. -## Permissions - -Requires the ability to make outbound calls based on your subscriber configuration and space settings. - ## Examples ### Basic outbound call @@ -116,3 +116,5 @@ const callSession = await client.dial({ video: true, }) ``` + +{/* TODO better examples showcasing usecases */} \ No newline at end of file diff --git a/website/docs/signalwire-client-sdk/tech-ref/call-session/events.mdx b/website/docs/signalwire-client-sdk/tech-ref/call-session/events.mdx index 74f4c14c8..ae0c198cb 100644 --- a/website/docs/signalwire-client-sdk/tech-ref/call-session/events.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/call-session/events.mdx @@ -33,7 +33,7 @@ Fired when you successfully join a call. Your member ID. - + Your permissions and capabilities for this call session. @@ -404,7 +404,7 @@ call.on('room.left', (event) => { Fired when a new member joins the call. - + The member object with all properties. @@ -661,7 +661,7 @@ call.on('member.updated.noiseSuppression', (event) => { Fired when the video layout changes. - + Layout object with name and layers. From 70c107b6dfb1ad00136c6a8565d210d458c6e365 Mon Sep 17 00:00:00 2001 From: nirav Date: Fri, 17 Oct 2025 19:37:13 +0545 Subject: [PATCH 10/12] sf --- .../docs/signalwire-client-sdk/tech-ref/call-session/events.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/signalwire-client-sdk/tech-ref/call-session/events.mdx b/website/docs/signalwire-client-sdk/tech-ref/call-session/events.mdx index ae0c198cb..749195b6c 100644 --- a/website/docs/signalwire-client-sdk/tech-ref/call-session/events.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/call-session/events.mdx @@ -448,7 +448,7 @@ call.on('member.updated', (event) => { Fired when a member leaves the call. - + The member who left. From 2f3b030255fc74207bb0bbe53544a8a0e41550c9 Mon Sep 17 00:00:00 2001 From: nirav Date: Fri, 17 Oct 2025 22:25:02 +0545 Subject: [PATCH 11/12] link fix --- website/docs/signalwire-client-sdk/tech-ref/authentication.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/signalwire-client-sdk/tech-ref/authentication.mdx b/website/docs/signalwire-client-sdk/tech-ref/authentication.mdx index c213bf47d..624400934 100644 --- a/website/docs/signalwire-client-sdk/tech-ref/authentication.mdx +++ b/website/docs/signalwire-client-sdk/tech-ref/authentication.mdx @@ -174,7 +174,7 @@ You can obtain authentication tokens directly through the REST API. The followin :::info For browser-based applications, we recommend using the OAuth2 flow to authenticate subscribers and obtain tokens. See -[Authenticate subscribers using OAuth2](#authenticate-subscribers-using-oauth2) below for details. +[Authenticate subscribers using OAuth2](#oauth2-subscriber-log-in) below for details. ::: ### Guest Token Authentication From 64af59a9e2c72eb76a46a096a20001dc1dce9502 Mon Sep 17 00:00:00 2001 From: nirav Date: Tue, 21 Oct 2025 13:56:22 +0545 Subject: [PATCH 12/12] hide things --- website/config/navbar.ts | 8 ++++---- website/config/pluginsConfig/index.ts | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/website/config/navbar.ts b/website/config/navbar.ts index 3029f2f7f..fdf9f7bc6 100644 --- a/website/config/navbar.ts +++ b/website/config/navbar.ts @@ -99,10 +99,10 @@ const navbar: NavbarItem[] = [ label: "RELAY Browser SDK", to: "/sdks/browser-sdk/", }, - { - label: "SignalWire Client SDK", - to: "/sdks/signalwire-client-sdk/", - }, + // { + // label: "SignalWire Client SDK", + // to: "/sdks/signalwire-client-sdk/", + // }, { label: "RELAY Realtime Server SDK", to: "/sdks/realtime-sdk/", diff --git a/website/config/pluginsConfig/index.ts b/website/config/pluginsConfig/index.ts index 515d83a57..0081f101d 100644 --- a/website/config/pluginsConfig/index.ts +++ b/website/config/pluginsConfig/index.ts @@ -20,7 +20,7 @@ import { showcasePlugin } from "./guide-showcase"; import { llmsTxtPlugin } from "./docusaurus-plugin-llms-txt"; import { realtimeSdkPlugin } from "./realtime-sdk-docs"; import { browserSdkPlugin } from "./browser-sdk-docs"; -import { signalwireSdkPlugin } from "./signalwire-client-sdk-docs"; +// import { signalwireSdkPlugin } from "./signalwire-client-sdk-docs"; import { ogImagesPlugin } from "../ogImages/index"; const plugins: PluginConfig[] = [ @@ -33,7 +33,7 @@ const plugins: PluginConfig[] = [ llmsTxtPlugin, realtimeSdkPlugin, browserSdkPlugin, - signalwireSdkPlugin, + // signalwireSdkPlugin, ogImagesPlugin, ];