ahs-cti 0.0.2-beta.9 β†’ 1.0.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,508 +1,639 @@
1
- <div align="center">
2
-
3
- ## Call Control SDK
4
-
5
- [![npm version](https://img.shields.io/npm/v/call-control-sdk.svg?color=blue&style=for-the-badge)](https://www.npmjs.com/package/call-control-sdk)
6
- [![npm downloads](https://img.shields.io/npm/dm/call-control-sdk.svg?color=green&style=for-the-badge)](https://www.npmjs.com/package/call-control-sdk)
7
- [![bundle size](https://img.shields.io/bundlephobia/minzip/call-control-sdk?color=orange&style=for-the-badge)](https://bundlephobia.com/package/call-control-sdk)
8
-
9
- **A powerful, lightweight SDK for real-time call management**
10
-
11
- **πŸ”‘AUTHORIZED ACCESS REQUIRED - API Key & Tenant IDπŸ”‘**
12
-
13
- </div>
14
-
15
- ### ⭐ **License Features**
16
-
17
- - **API Key Authentication** - Secure access through authorized API keys
18
- - **Tenant ID Management** - Multi-tenant support with isolated access
19
- - **Cross-Platform Support** - Use across web, mobile, desktop, and server platforms
20
- - **Usage Monitoring** - Real-time tracking and compliance monitoring
21
- - **Flexible Deployment** - Deploy on authorized platforms with proper credentials
22
-
23
- ### 🚫 **Prohibited Activities**
24
-
25
- - **No Unauthorized Access** - Cannot use without valid credentials
26
- - **No Credential Sharing** - API keys and tenant IDs are confidential
27
- - **No Reverse Engineering** - Cannot decompile or reverse engineer
28
- - **No Platform Violations** - Must use only on authorized platforms
29
- - **No Usage Abuse** - Cannot exceed subscription limits
30
-
31
- ## πŸ“‘ Table of Contents
32
-
33
- - [✨ Key Features](#-key-features)
34
- - [πŸ“¦ Installation](#-installation)
35
- - [πŸš€ Quick Start](#-quick-start)
36
- - [1️⃣ Initialize the SDK](#1️⃣-initialize-the-sdk)
37
- - [2️⃣ Add Call Control Panel](#2️⃣-add-call-control-panel)
38
- - [3️⃣ Use Call Management Hooks](#3️⃣-use-call-management-hooks)
39
- - [πŸ”§ Configuration Options](#-configuration-options)
40
- - [πŸ“š API Reference](#-api-reference)
41
- - [πŸ”§ Core Functions](#-core-functions)
42
- - [πŸͺ React Hooks](#-react-hooks)
43
- - [πŸ“¦ Data Types](#-data-types)
44
- - [πŸŽ› Control Features](#-control-features)
45
- - [🌍 Browser Support](#-browser-support)
46
- - [πŸ“„ License](#-license)
47
-
48
- ---
49
-
50
- ## ✨ Key Features
51
-
52
- ### 🎯 **Complete Call Control**
53
-
54
- - Hold/Resume calls
55
- - Mute/Unmute functionality
56
- - Agent status management
57
- - End call with disposition
58
-
59
- ### πŸ’Ύ **Smart State Management**
60
-
61
- - Real-time call timer
62
- - Persistent state storage
63
- - Singleton state pattern
64
- - Cross-component sync
65
- - TypeScript support
66
-
67
- ## πŸ“¦ Installation
68
-
69
- ```bash
70
- npm install call-control-sdk
71
- ```
72
-
73
- ### πŸ”‘ Required Dependencies
74
-
75
- Make sure you have these peer dependencies installed:
76
-
77
- ```bash
78
- npm install react react-dom axios @mui/material @mui/icons-material @emotion/react @emotion/styled
79
- ```
80
-
81
- ---
82
-
83
- ## πŸš€ Quick Start
84
-
85
- ### 1️⃣ **Initialize the SDK**
86
-
87
- First, initialize the SDK at the root of your application:
88
-
89
- ```tsx
90
- import { useEffect } from "react";
91
- import { initSDK } from "call-control-sdk";
92
-
93
- function App() {
94
- useEffect(() => {
95
- try {
96
- initSDK({
97
- apiKey: "your-api-key",
98
- tenantId: "your-tenant-id",
99
- agentId: "your-agent-id",
100
- });
101
- console.log("βœ… SDK initialized successfully");
102
- } catch (error) {
103
- console.error("❌ SDK initialization failed:", error);
104
- }
105
- }, []);
106
-
107
- return <YourAppContent />;
108
- }
109
- ```
110
-
111
- ### 2️⃣ **Add Call Control Panel**
112
-
113
- Drop in the draggable call control panel anywhere in your app:
114
-
115
- ```tsx
116
- import { CallControlPanel } from "call-control-sdk";
117
-
118
- export default function AgentDashboard() {
119
- const handleCallDataChange = (data) => {
120
- console.log("πŸ“ž Call data updated:", data);
121
- // Handle call data changes (mobileNumber, callReferenceId, agentLoginId)
122
- };
123
-
124
- return (
125
- <div>
126
- <h1>Agent Dashboard</h1>
127
- <CallControlPanel onDataChange={handleCallDataChange} />
128
- </div>
129
- );
130
- }
131
- ```
132
-
133
- #### πŸ“ž **Get Caller Data (Alternative to onDataChange)**
134
-
135
- The `useGetCallerData` hook is an **independent alternative** to the `CallControlPanel`'s `onDataChange` prop. It provides the same call data but can be used anywhere in your application without depending on the `CallControlPanel` component.
136
-
137
- **Key Differences:**
138
-
139
- - πŸ”„ **onDataChange**: Requires `CallControlPanel` component, callback-based
140
- - 🎯 **useGetCallerData**: Independent hook, reactive, can be used anywhere
141
-
142
- **When to use each:**
143
-
144
- - Use `onDataChange` when you need the call control UI and want to handle data changes
145
- - Use `useGetCallerData` when you only need call data without the control panel UI
146
-
147
- The `useGetCallerData` hook provides reactive access to current call data. It automatically updates when call status changes, new calls arrive, or call information is modified.
148
-
149
- ```tsx
150
- import { useGetCallerData } from "call-control-sdk";
151
-
152
- export default function AgentDashboard() {
153
- const callerData = useGetCallerData();
154
-
155
- // Sample data structure returned:
156
- // {
157
- // "phone_number": "1234567890",
158
- // "status": "ONCALL",
159
- // "callReferenceId": "convox_call_id_123",
160
- // "agent_id": "agent001",
161
- // "process_id": "proc001",
162
- // "process_name": "Sales Process"
163
- // }
164
-
165
- return (
166
- <div>
167
- <h1>Current Call Information</h1>
168
- <p>Phone Number: {callerData.phone_number}</p>
169
- <p>Call Status: {callerData.status}</p>
170
- <p>Call Reference ID: {callerData.callReferenceId}</p>
171
- <p>Agent ID: {callerData.agent_id}</p>
172
- <p>Process: {callerData.process_name}</p>
173
- </div>
174
- );
175
- }
176
- ```
177
-
178
- **Example: Using useGetCallerData independently (without CallControlPanel)**
179
-
180
- ```tsx
181
- import { useGetCallerData } from "call-control-sdk";
182
-
183
- // This component can be used anywhere, even without CallControlPanel
184
- export default function CallStatusWidget() {
185
- const callerData = useGetCallerData();
186
-
187
- return (
188
- <div className="call-status-widget">
189
- <h3>Current Call Status</h3>
190
- {callerData.status === "ONCALL" ?
191
- <div>
192
- <p>πŸ“ž Active Call: {callerData.phone_number}</p>
193
- <p>Agent: {callerData.agent_id}</p>
194
- <p>Process: {callerData.process_name}</p>
195
- </div>
196
- : <p>No active call</p>}
197
- </div>
198
- );
199
- }
200
-
201
- // You can use this widget anywhere in your app
202
- export default function MainApp() {
203
- return (
204
- <div>
205
- <h1>My Application</h1>
206
- <CallStatusWidget /> {/* Independent component */}
207
- {/* No CallControlPanel needed here */}
208
- </div>
209
- );
210
- }
211
- ```
212
-
213
- **Key Features:**
214
-
215
- - βœ… **Reactive Updates**: Automatically re-renders when call data changes
216
- - βœ… **Real-time Data**: Reflects current call state from WebSocket updates
217
- - βœ… **Type Safety**: Fully typed with TypeScript interfaces
218
- - βœ… **Complete Data**: Returns all available call information
219
- - βœ… **Independent**: Works without `CallControlPanel` component
220
-
221
- **Returned Data Fields:**
222
-
223
- - `phone_number`: The phone number involved in the call
224
- - `status`: Current call status (ONCALL, RINGING, WRAPUP, etc.)
225
- - `callReferenceId`: Unique identifier for the call
226
- - `agent_id`: ID of the agent handling the call
227
- - `process_id`: Process identifier for the call
228
- - `process_name`: Name of the process handling the call
229
-
230
- ### 3️⃣ **Use Call Management Hooks**
231
-
232
- #### πŸ”΄ **Start a Call**
233
-
234
- ```tsx
235
- import { useClickToCall } from "call-control-sdk";
236
-
237
- export default function CallButton() {
238
- const { handleStartCall, isLoading, isSuccess, isError, error } = useClickToCall();
239
-
240
- const startCall = () => {
241
- handleStartCall({
242
- mobileNumber: "1234567890",
243
- });
244
- };
245
-
246
- return (
247
- <button
248
- onClick={startCall}
249
- disabled={isLoading}
250
- >
251
- {isLoading ? "πŸ”„ Calling..." : "πŸ“ž Start Call"}
252
- </button>
253
- );
254
- }
255
- ```
256
-
257
- #### πŸ”š **End a Call**
258
-
259
- ```tsx
260
- import { useEndCall } from "call-control-sdk";
261
-
262
- export default function EndCallButton() {
263
- const { handleEndCall, isLoading, isSuccess, isError, error } = useEndCall();
264
-
265
- const endCall = () => {
266
- handleEndCall({
267
- disposition: "RES", // Call disposition
268
- });
269
- };
270
-
271
- return (
272
- <button
273
- onClick={endCall}
274
- disabled={isLoading}
275
- >
276
- {isLoading ? "πŸ”„ Ending..." : "πŸ”š End Call"}
277
- </button>
278
- );
279
- }
280
- ```
281
-
282
- #### πŸšͺ **Agent Logout**
283
-
284
- ```tsx
285
- import { useLogout } from "call-control-sdk";
286
-
287
- export default function LogoutButton() {
288
- const { logout, isLoading, isSuccess, isError, error } = useLogout();
289
-
290
- return (
291
- <button
292
- onClick={logout}
293
- disabled={isLoading}
294
- >
295
- {isLoading ? "πŸ”„ Logging out..." : "πŸšͺ Logout"}
296
- </button>
297
- );
298
- }
299
- ```
300
-
301
- ### πŸ” Authorization Token
302
-
303
- get Authorization token for external API call
304
-
305
- ```tsx
306
- import { useGetAuthorizationToken } from "call-control-sdk";
307
-
308
- export default function axios() {
309
- const token = useGetAuthorizationToken();
310
-
311
- console.log(token);
312
- }
313
- ```
314
-
315
- ---
316
-
317
- ## πŸ”§ Configuration Options
318
-
319
- Customize the SDK behavior to fit your needs:
320
-
321
- ```tsx
322
- initSDK({
323
- // Required configuration
324
- apiKey: "your-api-key",
325
- tenantId: "your-tenant-id",
326
- agentId: "your-agent-id",
327
-
328
- // Optional customization
329
- disableEndCallButton: false, // Hide end call button
330
- disabledDialButton: false, // Hide dial button
331
- disableCallTransferButton: false, // Hide transfer button
332
- disableConferenceButton: false, // Hide conference button
333
- disableSoftPhone: false, // Hide soft phone iframe
334
- isDraggable: true, // Enable/disable dragging
335
-
336
- // Custom styling (Material-UI SxProps)
337
- disabled: { opacity: 0.5 }, // Disabled button styles
338
- enabled: { color: "primary" }, // Enabled button styles
339
- outlined: { border: "1px solid" }, // Outlined button styles
340
- });
341
- ```
342
-
343
- ### 🎨 **Styling Options**
344
-
345
- | Option | Type | Default | Description |
346
- | --------------------------- | --------- | ------- | --------------------------------- |
347
- | `disableEndCallButton` | `boolean` | `false` | Hide the "End Call" button |
348
- | `disabledDialButton` | `boolean` | `false` | Hide the "Dial" button |
349
- | `disableCallTransferButton` | `boolean` | `false` | Hide the "Call Transfer" button |
350
- | `disableConferenceButton` | `boolean` | `false` | Hide the "Conference" button |
351
- | `disableSoftPhone` | `boolean` | `false` | Hide the embedded soft phone |
352
- | `isDraggable` | `boolean` | `true` | Enable/disable panel dragging |
353
- | `disabled` | `SxProps` | - | Custom styles for disabled states |
354
- | `enabled` | `SxProps` | - | Custom styles for enabled states |
355
- | `outlined` | `SxProps` | - | Custom styles for outlined states |
356
-
357
- ---
358
-
359
- ## πŸ“š API Reference
360
-
361
- ### πŸ”§ **Core Functions**
362
-
363
- #### `initSDK(config)`
364
-
365
- Initialize the SDK with your configuration. **Must be called before using any components or hooks.**
366
-
367
- ```tsx
368
- initSDK({
369
- apiKey: string, // βœ… Required - API key for authentication
370
- tenantId: string, // βœ… Required - Tenant ID for events/authentication
371
- agentId: string, // βœ… Required - Agent ID for call controls
372
- // ... plus optional configuration options
373
- });
374
- ```
375
-
376
- #### `CallControlPanel`
377
-
378
- Draggable control panel component for call management.
379
-
380
- ```tsx
381
- <CallControlPanel
382
- onDataChange={(data) => {
383
- console.log("Call data updated:", data);
384
- }}
385
- />
386
- ```
387
-
388
- ### πŸͺ **React Hooks**
389
-
390
- #### `useLogout()`
391
-
392
- Hook for agent logout functionality.
393
-
394
- ```tsx
395
- const { logout, isLoading, isSuccess, isError, error } = useLogout();
396
-
397
- // Usage:
398
- logout();
399
-
400
- // Returns:
401
- // - logout: () => void - Function to trigger logout
402
- // - isLoading: boolean - Loading state
403
- // - isSuccess: boolean - Success state
404
- // - isError: boolean - Error state
405
- // - error: any - Error object if failed
406
- ```
407
-
408
- #### `useClickToCall()`
409
-
410
- Hook for initiating calls to mobile numbers.
411
-
412
- ```tsx
413
- const { handleStartCall, isLoading, isSuccess, isError, error, data } = useClickToCall();
414
-
415
- // Usage:
416
- handleStartCall({ mobileNumber: "1234567890" });
417
-
418
- // Returns:
419
- // - handleStartCall: (payload: StartCallPayload) => void
420
- // - isLoading: boolean - Loading state
421
- // - isSuccess: boolean - Success state
422
- // - isError: boolean - Error state
423
- // - error: any - Error object if failed
424
- // - data: any - API response on success
425
- ```
426
-
427
- #### `useEndCall()`
428
-
429
- Hook for ending active calls.
430
-
431
- ```tsx
432
- const { handleEndCall, isLoading, isSuccess, isError, error, data } = useEndCall();
433
-
434
- // Usage:
435
- handleEndCall({ disposition: "RES" });
436
-
437
- // Returns:
438
- // - handleEndCall: (payload: EndCallPayload) => void
439
- // - isLoading: boolean - Loading state
440
- // - isSuccess: boolean - Success state
441
- // - isError: boolean - Error state
442
- // - error: any - Error object if failed
443
- // - data: any - API response on success
444
- ```
445
-
446
- ---
447
-
448
- ## πŸ“¦ **Data Types**
449
-
450
- ### `StartCallPayload`
451
-
452
- ```tsx
453
- interface StartCallPayload {
454
- mobileNumber?: string; // Mobile number to call
455
- }
456
- ```
457
-
458
- ### `EndCallPayload`
459
-
460
- ```tsx
461
- interface EndCallPayload {
462
- disposition?: string; // Call disposition (default: "RES")
463
- }
464
- ```
465
-
466
- ---
467
-
468
- ## πŸŽ› **Control Features**
469
-
470
- ### πŸ“ž **Call Management**
471
-
472
- - **Hold/Resume** - Pause and resume active calls
473
- - **Mute/Unmute** - Control audio during calls
474
- - **End Call** - Terminate calls with disposition tracking
475
- - **Agent Status** - Switch between Idle/Break states
476
-
477
- ### πŸ’Ύ **State Persistence**
478
-
479
- - **Call Timer** - Real-time duration tracking
480
- - **Panel Position** - Remembers draggable panel location
481
- - **Agent Status** - Maintains current status across sessions
482
- - **Call State** - Preserves hold/mute states
483
-
484
- ---
485
-
486
- ## 🌍 **Browser Support**
487
-
488
- <div align="left">
489
-
490
- | Browser | Version | Status |
491
- | ----------------------------------------------------------------------------- | ------- | ------------ |
492
- | ![Chrome](https://img.shields.io/badge/Chrome-60%2B-green?logo=google-chrome) | 60+ | βœ… Supported |
493
- | ![Firefox](https://img.shields.io/badge/Firefox-60%2B-green?logo=firefox) | 60+ | βœ… Supported |
494
- | ![Safari](https://img.shields.io/badge/Safari-12%2B-green?logo=safari) | 12+ | βœ… Supported |
495
- | ![Edge](https://img.shields.io/badge/Edge-79%2B-green?logo=microsoft-edge) | 79+ | βœ… Supported |
496
-
497
- </div>
498
-
499
- ---
500
-
501
- ## πŸ“„ **License**
502
-
503
- <div align="center">
504
-
505
- ![license](https://img.shields.io/badge/License-Achala-blue?style=for-the-badge)
506
- ![license](https://img.shields.io/badge/License-Proprietary-red?style=for-the-badge)
507
-
508
- </div>
1
+ <div align="center">
2
+
3
+ ## AHS CTI SDK
4
+
5
+ [![npm version](https://img.shields.io/npm/v/ahs-cti.svg?color=blue&style=for-the-badge)](https://www.npmjs.com/package/ahs-cti)
6
+ [![npm downloads](https://img.shields.io/npm/dm/ahs-cti.svg?color=green&style=for-the-badge)](https://www.npmjs.com/package/ahs-cti)
7
+ [![bundle size](https://img.shields.io/bundlephobia/minzip/ahs-cti?color=orange&style=for-the-badge)](https://bundlephobia.com/package/ahs-cti)
8
+
9
+ **A powerful, lightweight SDK for real-time call management with dynamic configuration and permission-based access control**
10
+
11
+ **πŸ”‘AUTHORIZED ACCESS REQUIRED - API Key & Tenant IDπŸ”‘**
12
+
13
+ </div>
14
+
15
+ ### ⭐ **License Features**
16
+
17
+ - **API Key Authentication** - Secure access through authorized API keys
18
+ - **Tenant ID Management** - Multi-tenant support with isolated access
19
+ - **Permission-Based Access Control** - Entitlement-driven feature enablement
20
+ - **Cross-Platform Support** - Use across web, mobile, desktop, and server platforms
21
+ - **Usage Monitoring** - Real-time tracking and compliance monitoring
22
+ - **Flexible Deployment** - Deploy on authorized platforms with proper credentials
23
+
24
+ ### 🚫 **Prohibited Activities**
25
+
26
+ - **No Unauthorized Access** - Cannot use without valid credentials
27
+ - **No Credential Sharing** - API keys and tenant IDs are confidential
28
+ - **No Reverse Engineering** - Cannot decompile or reverse engineer
29
+ - **No Platform Violations** - Must use only on authorized platforms
30
+ - **No Usage Abuse** - Cannot exceed subscription limits
31
+
32
+ ## πŸ“‘ Table of Contents
33
+
34
+ - [✨ Key Features](#-key-features)
35
+ - [πŸ“¦ Installation](#-installation)
36
+ - [πŸš€ Quick Start](#-quick-start)
37
+ - [1️⃣ Initialize the SDK](#1️⃣-initialize-the-sdk)
38
+ - [2️⃣ Add Call Control Panel](#2️⃣-add-call-control-panel)
39
+ - [3️⃣ Use Call Management Hooks](#3️⃣-use-call-management-hooks)
40
+ - [βš™οΈ Dynamic Configuration](#️-dynamic-configuration)
41
+ - [πŸ”§ SDK Config](#-sdk-config)
42
+ - [🌐 URL Config](#-url-config)
43
+ - [πŸ” Permission-Based Controls](#-permission-based-controls)
44
+ - [πŸ“Š Configuration Merge Priority](#-configuration-merge-priority)
45
+ - [πŸ“š API Reference](#-api-reference)
46
+ - [πŸ”§ Core Functions](#-core-functions)
47
+ - [πŸͺ React Hooks](#-react-hooks)
48
+ - [πŸ”’ Permissions System](#-permissions-system)
49
+ - [πŸ”Œ WebSocket Events](#-websocket-events)
50
+ - [πŸ“¦ Data Types](#-data-types)
51
+ - [🌍 Browser Support](#-browser-support)
52
+ - [πŸ“„ License](#-license)
53
+
54
+ ---
55
+
56
+ ## ✨ Key Features
57
+
58
+ ### 🎯 **Complete Call Control**
59
+
60
+ - Inbound and outbound call management
61
+ - Hold/Resume calls
62
+ - Mute/Unmute functionality
63
+ - Blind, Attended, and Warm call transfers
64
+ - Multi-line conference calling (up to 5 lines)
65
+ - Agent status management (Ready, Break, Wrapup)
66
+ - End call with disposition tracking
67
+ - Ringtone support for incoming calls
68
+
69
+ ### βš™οΈ **Dynamic Configuration**
70
+
71
+ - **Three-layer config merging** - Backend defaults, permission-based controls, and explicit SDK config
72
+ - **Permission-based feature toggling** - Controls auto-disabled based on entitlements
73
+ - **Runtime URL configuration** - All endpoints dynamically resolved from config
74
+ - **Customizable UI** - Material-UI SxProps for button styling
75
+
76
+ ### πŸ’Ύ **Smart State Management**
77
+
78
+ - Real-time call timer
79
+ - Persistent state storage via `@react-solutions/vault`
80
+ - Singleton state pattern
81
+ - Cross-component sync via observer pattern
82
+ - Full TypeScript support
83
+
84
+ ## πŸ“¦ Installation
85
+
86
+ ```bash
87
+ npm install ahs-cti
88
+ ```
89
+
90
+ ### πŸ”‘ Required Peer Dependencies
91
+
92
+ ```bash
93
+ npm install react react-dom axios @mui/material @mui/icons-material @emotion/react @emotion/styled @react-solutions/vault
94
+ ```
95
+
96
+ ---
97
+
98
+ ## πŸš€ Quick Start
99
+
100
+ ### 1️⃣ **Initialize the SDK**
101
+
102
+ Initialize the SDK at the root of your application with the required credentials and optional dynamic configuration:
103
+
104
+ ```tsx
105
+ import { useEffect } from "react";
106
+ import { initSDK } from "ahs-cti";
107
+
108
+ function App() {
109
+ useEffect(() => {
110
+ const initialize = async () => {
111
+ try {
112
+ await initSDK({
113
+ // Required credentials
114
+ apiKey: "your-api-key",
115
+ tenantId: "your-tenant-id",
116
+ agentId: "your-agent-id",
117
+
118
+ // Optional: URL configuration for API endpoints
119
+ urlConfig: {
120
+ },
121
+
122
+ // Optional: Feature configuration overrides
123
+ sdkConfig: {
124
+ },
125
+ });
126
+ console.log("βœ… SDK initialized successfully");
127
+ } catch (error) {
128
+ console.error("❌ SDK initialization failed:", error);
129
+ }
130
+ };
131
+
132
+ initialize();
133
+ }, []);
134
+
135
+ return <YourAppContent />;
136
+ }
137
+ ```
138
+
139
+ ### 2️⃣ **Add Call Control Panel**
140
+
141
+ Drop in the draggable call control panel anywhere in your app:
142
+
143
+ ```tsx
144
+ import { CallControlPanel } from "ahs-cti";
145
+
146
+ export default function AgentDashboard() {
147
+ const handleCallDataChange = (data) => {
148
+ console.log("πŸ“ž Call data updated:", data);
149
+ };
150
+
151
+ return (
152
+ <div>
153
+ <h1>Agent Dashboard</h1>
154
+ <CallControlPanel onDataChange={handleCallDataChange} />
155
+ </div>
156
+ );
157
+ }
158
+ ```
159
+
160
+ ### 3️⃣ **Use Call Management Hooks**
161
+
162
+ #### πŸ”΄ **Start a Call**
163
+
164
+ ```tsx
165
+ import { useClickToCall } from "ahs-cti";
166
+
167
+ export default function CallButton() {
168
+ const { handleStartCall, isLoading, isSuccess, isError, error } =
169
+ useClickToCall();
170
+
171
+ const startCall = () => {
172
+ handleStartCall({ mobileNumber: "1234567890" });
173
+ };
174
+
175
+ return (
176
+ <button onClick={startCall} disabled={isLoading}>
177
+ {isLoading ? "πŸ”„ Calling..." : "πŸ“ž Start Call"}
178
+ </button>
179
+ );
180
+ }
181
+ ```
182
+
183
+ #### πŸ”š **End a Call**
184
+
185
+ ```tsx
186
+ import { useEndCall } from "ahs-cti";
187
+
188
+ export default function EndCallButton() {
189
+ const { handleEndCall, isLoading } = useEndCall();
190
+
191
+ const endCall = () => {
192
+ handleEndCall({ disposition: "RES" });
193
+ };
194
+
195
+ return (
196
+ <button onClick={endCall} disabled={isLoading}>
197
+ {isLoading ? "πŸ”„ Ending..." : "πŸ”š End Call"}
198
+ </button>
199
+ );
200
+ }
201
+ ```
202
+
203
+ #### πŸšͺ **Agent Logout**
204
+
205
+ ```tsx
206
+ import { useLogout } from "ahs-cti";
207
+
208
+ export default function LogoutButton() {
209
+ const { logout, isLoading } = useLogout();
210
+
211
+ return (
212
+ <button onClick={logout} disabled={isLoading}>
213
+ {isLoading ? "πŸ”„ Logging out..." : "πŸšͺ Logout"}
214
+ </button>
215
+ );
216
+ }
217
+ ```
218
+
219
+ #### πŸ“ž **Get Caller Data**
220
+
221
+ The `useGetCallerData` hook provides reactive access to current call data independently of `CallControlPanel`:
222
+
223
+ ```tsx
224
+ import { useGetCallerData } from "ahs-cti";
225
+
226
+ export default function CallStatusWidget() {
227
+ const callerData = useGetCallerData();
228
+
229
+ return (
230
+ <div>
231
+ <h3>Current Call Status</h3>
232
+ {callerData.status === "ONCALL" ? (
233
+ <div>
234
+ <p>Active Call: {callerData.phone_number}</p>
235
+ <p>Agent: {callerData.agent_id}</p>
236
+ <p>Process: {callerData.process_name}</p>
237
+ <p>Queue: {callerData.queue_name}</p>
238
+ </div>
239
+ ) : (
240
+ <p>No active call</p>
241
+ )}
242
+ </div>
243
+ );
244
+ }
245
+ ```
246
+
247
+ #### πŸ”„ **Subscribe to SDK State**
248
+
249
+ ```tsx
250
+ import { useSDKState } from "ahs-cti";
251
+
252
+ export default function AgentStatusDisplay() {
253
+ const state = useSDKState();
254
+
255
+ return (
256
+ <div>
257
+ <p>Agent: {state.agentId}</p>
258
+ <p>Status: {state.agentStatus}</p>
259
+ <p>Initialized: {state.isInitialized ? "Yes" : "No"}</p>
260
+ <p>Hold: {state.hold ? "On Hold" : "Active"}</p>
261
+ <p>Mute: {state.mute ? "Muted" : "Unmuted"}</p>
262
+ </div>
263
+ );
264
+ }
265
+ ```
266
+
267
+ #### πŸ” **Get Authorization Token**
268
+
269
+ Retrieve the access token for external API calls:
270
+
271
+ ```tsx
272
+ import { useGetAuthorizationToken } from "ahs-cti";
273
+
274
+ export default function ExternalAPICall() {
275
+ const token = useGetAuthorizationToken();
276
+
277
+ const fetchData = async () => {
278
+ const response = await fetch("https://api.example.com/data", {
279
+ headers: { Authorization: `Bearer ${token}` },
280
+ });
281
+ // handle response
282
+ };
283
+
284
+ return <button onClick={fetchData}>Fetch External Data</button>;
285
+ }
286
+ ```
287
+
288
+ ---
289
+
290
+ ## βš™οΈ Dynamic Configuration
291
+
292
+ The SDK supports a three-layer dynamic configuration system that determines which call control features are enabled.
293
+
294
+ ### πŸ”§ SDK Config
295
+
296
+ Feature toggle options passed via `sdkConfig` in `initSDK()`:
297
+
298
+ ### 🎨 **Configuration Options**
299
+
300
+ | Option | Type | Default | Description |
301
+ | --------------------------- | --------- | ------- | --------------------------------------- |
302
+ | `disableEndCallButton` | `boolean` | `false` | Disable the end call button |
303
+ | `disabledDialButton` | `boolean` | `false` | Disable the dial/outbound call button |
304
+ | `disableCallTransferButton` | `boolean` | `false` | Disable the call transfer button |
305
+ | `disableBlindTransfer` | `boolean` | `false` | Disable blind transfer option |
306
+ | `disableAttendedTransfer` | `boolean` | `false` | Disable attended transfer option |
307
+ | `disableWarmTransfer` | `boolean` | `false` | Disable warm transfer option |
308
+ | `disableConferenceButton` | `boolean` | `false` | Disable the conference call button |
309
+ | `disableHoldButton` | `boolean` | `false` | Disable the hold functionality |
310
+ | `disableMuteButton` | `boolean` | `false` | Disable the mute functionality |
311
+ | `disabledMoreOptionsButton` | `boolean` | `false` | Disable the more options menu |
312
+ | `disableSoftPhone` | `boolean` | `false` | Disable the embedded soft phone iframe |
313
+ | `isDraggable` | `boolean` | `true` | Enable/disable panel dragging |
314
+ | `enableSmsServices` | `boolean` | `false` | Enable SMS services |
315
+ | `enableQueueName` | `boolean` | `false` | Show queue name in call data |
316
+ | `enableRingtone` | `boolean` | `false` | Enable ringtone for incoming calls |
317
+ | `auto_wrapup_time` | `number` | - | Auto wrapup time in seconds |
318
+ | `break_time` | `number` | - | Break duration in seconds |
319
+ | `disabled` | `SxProps` | - | Custom MUI styles for disabled states |
320
+ | `enabled` | `SxProps` | - | Custom MUI styles for enabled states |
321
+ | `outlined` | `SxProps` | - | Custom MUI styles for outlined states |
322
+
323
+ ### 🌐 URL Config
324
+
325
+ All API endpoints are dynamically resolved from the URL configuration:
326
+
327
+ ```typescript
328
+ interface URLConfig {
329
+ id: string; // Configuration identifier
330
+ baseURL: string; // Main API base URL
331
+ coreBaseURL: string; // Core API URL for call control actions
332
+ webSocketURL: string; // WebSocket URL for real-time events
333
+ iframeURL: string; // Soft phone iframe URL
334
+ iframeAPIURL: string; // Iframe API endpoint
335
+ password: string; // Agent password for authentication
336
+ accessToken?: string; // Pre-provided access token (optional)
337
+ }
338
+ ```
339
+
340
+ If `baseURL` is not provided, the SDK falls back to `window.location.origin`.
341
+
342
+ ### πŸ” Permission-Based Controls
343
+
344
+ The SDK implements a **fail-closed** permission model. After authentication, the backend returns entitlements that automatically determine which controls are enabled:
345
+
346
+ ```typescript
347
+ // Entitlements structure from login response
348
+ {
349
+ calls: {
350
+ enabled: boolean,
351
+ items: [
352
+ { code: "call_inbound", enabled: boolean },
353
+ { code: "call_outbound", enabled: boolean }
354
+ ]
355
+ },
356
+ call_transfer: {
357
+ enabled: boolean,
358
+ items: [
359
+ { code: "call_transfer_blind", enabled: boolean },
360
+ { code: "call_transfer_attended", enabled: boolean },
361
+ { code: "call_transfer_warm", enabled: boolean }
362
+ ]
363
+ },
364
+ call_conference: {
365
+ enabled: boolean,
366
+ items: [
367
+ { code: "call_conference", enabled: boolean }
368
+ ]
369
+ }
370
+ }
371
+ ```
372
+
373
+ If permissions have not been loaded, **all controls are disabled by default**.
374
+
375
+ You can use the exported `SDK_PERMISSIONS` constants to reference permission codes:
376
+
377
+ ```typescript
378
+ import { SDK_PERMISSIONS } from "ahs-cti";
379
+
380
+ // Permission categories
381
+ SDK_PERMISSIONS.CALLS; // "calls"
382
+ SDK_PERMISSIONS.CALL_TRANSFER; // "call_transfer"
383
+ SDK_PERMISSIONS.CALL_CONFERENCE; // "call_conference"
384
+
385
+ // Permission codes
386
+ SDK_PERMISSIONS.CALL_INBOUND; // "call_inbound"
387
+ SDK_PERMISSIONS.CALL_OUTBOUND; // "call_outbound"
388
+ SDK_PERMISSIONS.TRANSFER_BLIND; // "call_transfer_blind"
389
+ SDK_PERMISSIONS.TRANSFER_ATTENDED; // "call_transfer_attended"
390
+ SDK_PERMISSIONS.TRANSFER_WARM; // "call_transfer_warm"
391
+ SDK_PERMISSIONS.CONFERENCE; // "call_conference"
392
+ ```
393
+
394
+ ### πŸ“Š Configuration Merge Priority
395
+
396
+ The SDK merges configuration from three sources (highest priority wins):
397
+
398
+ ```
399
+ 1. Explicit sdkConfig (passed to initSDK) <- Highest priority
400
+ 2. Permission-based controls (from entitlements) <- Medium priority
401
+ 3. Backend callControls (from login response) <- Lowest priority
402
+ ```
403
+
404
+ This means:
405
+
406
+ - Backend defaults set the baseline configuration
407
+ - Entitlements override backend defaults based on the agent's permissions
408
+ - Explicit `sdkConfig` overrides everything, allowing host applications to force-enable or force-disable features
409
+
410
+ ---
411
+
412
+ ## πŸ“š API Reference
413
+
414
+ ### πŸ”§ **Core Functions**
415
+
416
+ #### `initSDK(params)`
417
+
418
+ Initialize the SDK with credentials and configuration. **Must be called before using any components or hooks.** Returns a `Promise<void>`.
419
+
420
+ ```typescript
421
+ await initSDK({
422
+ apiKey: string, // βœ… Required - API key for authentication
423
+ tenantId: string, // βœ… Required - Tenant identifier
424
+ agentId: string, // βœ… Required - Agent identifier
425
+ sessionId?: string, // πŸ“Ž Optional - Session identifier
426
+ urlConfig?: URLConfig, // πŸ“Ž Optional - URL configuration for endpoints
427
+ sdkConfig?: SDKConfig, // πŸ“Ž Optional - Feature configuration overrides
428
+ });
429
+ ```
430
+
431
+ #### `isSDKInitialized()`
432
+
433
+ Check if the SDK has been successfully initialized.
434
+
435
+ ```typescript
436
+ const initialized: boolean = isSDKInitialized();
437
+ ```
438
+
439
+ #### `getSDKVersion()`
440
+
441
+ Get the current SDK version.
442
+
443
+ ```typescript
444
+ const version: string = getSDKVersion();
445
+ ```
446
+
447
+ #### `CallControlPanel`
448
+
449
+ Draggable control panel component for call management.
450
+
451
+ ```tsx
452
+ <CallControlPanel
453
+ onDataChange={(data: CallData) => {
454
+ // Called when call status, phone number, or any call data changes
455
+ }}
456
+ />
457
+ ```
458
+
459
+ ### πŸͺ **React Hooks**
460
+
461
+ | Hook | Description | Returns |
462
+ | --------------------------- | -------------------------------------------- | ----------------------------------------------------------- |
463
+ | `useClickToCall()` | Initiate outbound calls | `{ handleStartCall, isLoading, isSuccess, isError, error }` |
464
+ | `useEndCall()` | End active calls with disposition | `{ handleEndCall, isLoading, isSuccess, isError, error }` |
465
+ | `useLogout()` | Agent logout | `{ logout, isLoading, isSuccess, isError, error }` |
466
+ | `useGetCallerData()` | Reactive access to current call data | `CallData` |
467
+ | `useSDKState()` | Subscribe to full SDK state changes | `SDKState` |
468
+ | `useGetAuthorizationToken()`| Get the current access token | `string \| undefined` |
469
+
470
+ ---
471
+
472
+ ## πŸ”Œ WebSocket Events
473
+
474
+ The SDK connects to a WebSocket for real-time call events:
475
+
476
+ ```
477
+ WebSocket URL: {urlConfig.webSocketURL}/api/v1/ws/agent/events?token={accessToken}
478
+ ```
479
+
480
+ **Connection behavior:**
481
+ - Auto-reconnects with exponential backoff (base: 2s, max: 30s, up to 60 attempts)
482
+ - Sends ping every 30 seconds to keep the connection alive
483
+
484
+ **Event data structure:**
485
+
486
+ ```typescript
487
+ {
488
+ agent_id: number;
489
+ status: CallStatus; // IDLE, READY, ONCALL, RINGING, DIALING, WRAPUP, etc.
490
+ type: string; // Call type
491
+ event_time: string;
492
+ phone_number: string;
493
+ convox_id: string;
494
+ process_id: number;
495
+ process_name: string;
496
+ hold: number; // 0 = not held, 1 = held
497
+ mute: number; // 0 = not muted, 1 = muted
498
+ mode: string; // 'manual' or automated
499
+ queue_name: string;
500
+ conferencestatus?: { // Present during conference calls
501
+ line_1_status: string;
502
+ line_1_phonenumber: string;
503
+ line_2_status: string;
504
+ line_2_phonenumber: string;
505
+ // ... up to line 5
506
+ }
507
+ }
508
+ ```
509
+
510
+ ---
511
+
512
+ ## πŸ“¦ Data Types
513
+
514
+ ### `CallStatus` Enum
515
+
516
+ ```typescript
517
+ enum CallStatus {
518
+ IDLE = "IDLE",
519
+ READY = "READY",
520
+ BREAK = "BREAK",
521
+ ONCALL = "ONCALL",
522
+ WRAPUP = "WRAPUP",
523
+ RINGING = "RINGING",
524
+ DIALING = "DIALING",
525
+ MISSED = "MISSED",
526
+ HOLD = "HOLD",
527
+ UNHOLD = "UNHOLD",
528
+ MUTE = "MUTE",
529
+ UNMUTE = "UNMUTE",
530
+ DISCONNECTED = "DISCONNECTED",
531
+ CONFERENCE = "CONFERENCE",
532
+ }
533
+ ```
534
+
535
+ ### `CallData`
536
+
537
+ ```typescript
538
+ interface CallData {
539
+ mobileNumber?: string;
540
+ callReferenceId?: string;
541
+ convoxId?: string;
542
+ type?: string;
543
+ status: string;
544
+ agent_id: number;
545
+ phone_number?: string;
546
+ event_time?: string;
547
+ convox_id?: string;
548
+ process_id?: string;
549
+ process_name?: string;
550
+ mode?: string;
551
+ queue_name?: string;
552
+ mute?: number; // 1 = muted, 0 = unmuted
553
+ hold?: number; // 1 = on hold, 0 = not on hold
554
+ }
555
+ ```
556
+
557
+ ### `ConferenceLineTypes`
558
+
559
+ ```typescript
560
+ type ConferenceLineTypes = {
561
+ line: number; // Line number (1-5)
562
+ status: string; // ONCALL, IDLE, LINE USED, etc.
563
+ type: "external" | "internal" | "";
564
+ phone: string;
565
+ isMute: boolean;
566
+ isHold: boolean;
567
+ isCallStart: boolean;
568
+ isMergeCall: boolean;
569
+ };
570
+ ```
571
+
572
+ ### `StartCallPayload`
573
+
574
+ ```typescript
575
+ interface StartCallPayload {
576
+ mobileNumber?: string;
577
+ }
578
+ ```
579
+
580
+ ### `EndCallPayload`
581
+
582
+ ```typescript
583
+ interface EndCallPayload {
584
+ disposition?: string; // Default: "RES"
585
+ }
586
+ ```
587
+
588
+ ---
589
+
590
+ ## πŸ“€ Exported Types
591
+
592
+ ```typescript
593
+ // Types
594
+ export type { CallData, CallControlPanelProps, SDKConfig, URLConfig };
595
+ export type { SDKPermissionState, ControlsFromPermissions, SDKPermissionContextValue };
596
+ export type { RequestResult, RequestOptions };
597
+ export type { UseGetRequest, UsePostRequest, UsePutRequest, UseDeleteRequest, UsePatchRequest };
598
+
599
+ // Enum
600
+ export { CallStatus };
601
+
602
+ // Constants
603
+ export { SDK_PERMISSIONS };
604
+
605
+ // Functions
606
+ export { initSDK, getSDKVersion, isSDKInitialized };
607
+
608
+ // Hooks
609
+ export { useLogout, useEndCall, useClickToCall, useGetCallerData, useGetAuthorizationToken, useSDKState };
610
+
611
+ // Components
612
+ export { CallControlPanel };
613
+ ```
614
+
615
+ ---
616
+
617
+ ## 🌍 **Browser Support**
618
+
619
+ <div align="left">
620
+
621
+ | Browser | Version | Status |
622
+ | ----------------------------------------------------------------------------- | ------- | ---------- |
623
+ | ![Chrome](https://img.shields.io/badge/Chrome-60%2B-green?logo=google-chrome) | 60+ | βœ… Supported |
624
+ | ![Firefox](https://img.shields.io/badge/Firefox-60%2B-green?logo=firefox) | 60+ | βœ… Supported |
625
+ | ![Safari](https://img.shields.io/badge/Safari-12%2B-green?logo=safari) | 12+ | βœ… Supported |
626
+ | ![Edge](https://img.shields.io/badge/Edge-79%2B-green?logo=microsoft-edge) | 79+ | βœ… Supported |
627
+
628
+ </div>
629
+
630
+ ---
631
+
632
+ ## πŸ“„ **License**
633
+
634
+ <div align="center">
635
+
636
+ ![license](https://img.shields.io/badge/License-Achala-blue?style=for-the-badge)
637
+ ![license](https://img.shields.io/badge/License-Proprietary-red?style=for-the-badge)
638
+
639
+ </div>