ahs-cti 1.0.0-beta.1 β 1.0.0-beta.3
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 +639 -639
- package/dist/callHistory-OGSCDW6R.mjs +339 -0
- package/dist/callHistory-OGSCDW6R.mjs.map +1 -0
- package/dist/chunk-LIXUDT6G.mjs +913 -0
- package/dist/chunk-LIXUDT6G.mjs.map +1 -0
- package/dist/index.d.mts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2314 -1380
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1261 -1627
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,639 +1,639 @@
|
|
|
1
|
-
<div align="center">
|
|
2
|
-
|
|
3
|
-
## AHS CTI SDK
|
|
4
|
-
|
|
5
|
-
[](https://www.npmjs.com/package/ahs-cti)
|
|
6
|
-
[](https://www.npmjs.com/package/ahs-cti)
|
|
7
|
-
[](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
|
-
|  | 60+ | β
Supported |
|
|
624
|
-
|  | 60+ | β
Supported |
|
|
625
|
-
|  | 12+ | β
Supported |
|
|
626
|
-
|  | 79+ | β
Supported |
|
|
627
|
-
|
|
628
|
-
</div>
|
|
629
|
-
|
|
630
|
-
---
|
|
631
|
-
|
|
632
|
-
## π **License**
|
|
633
|
-
|
|
634
|
-
<div align="center">
|
|
635
|
-
|
|
636
|
-

|
|
637
|
-

|
|
638
|
-
|
|
639
|
-
</div>
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
## AHS CTI SDK
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/ahs-cti)
|
|
6
|
+
[](https://www.npmjs.com/package/ahs-cti)
|
|
7
|
+
[](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
|
+
|  | 60+ | β
Supported |
|
|
624
|
+
|  | 60+ | β
Supported |
|
|
625
|
+
|  | 12+ | β
Supported |
|
|
626
|
+
|  | 79+ | β
Supported |
|
|
627
|
+
|
|
628
|
+
</div>
|
|
629
|
+
|
|
630
|
+
---
|
|
631
|
+
|
|
632
|
+
## π **License**
|
|
633
|
+
|
|
634
|
+
<div align="center">
|
|
635
|
+
|
|
636
|
+

|
|
637
|
+

|
|
638
|
+
|
|
639
|
+
</div>
|