@cemscale-voip/voip-sdk 2.0.11 → 2.0.12
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 +443 -46
- package/dist/client.d.ts +3531 -211
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +3456 -136
- package/dist/client.js.map +1 -1
- package/dist/types.d.ts +1172 -32
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/types.d.ts
CHANGED
|
@@ -1,30 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parameters for logging in as an extension user (softphone / SDK consumer).
|
|
3
|
+
*
|
|
4
|
+
* Extensions authenticate with their extension number + password, scoped to a tenant.
|
|
5
|
+
* After login you receive a JWT token valid for the tenant.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* const { token, user } = await voip.login({
|
|
10
|
+
* username: '1001',
|
|
11
|
+
* password: 'my-sip-password',
|
|
12
|
+
* tenantId: 'uuid-of-tenant',
|
|
13
|
+
* });
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
1
16
|
export interface LoginParams {
|
|
17
|
+
/** Extension number (e.g. `"1001"`, `"2005"`). 3-6 digit identifier within a tenant. */
|
|
2
18
|
username: string;
|
|
19
|
+
/** SIP password set on the extension. Case-sensitive, min 6 characters. */
|
|
3
20
|
password: string;
|
|
21
|
+
/** UUID of the tenant this extension belongs to. Obtain this from the dashboard or from the list of tenants. */
|
|
4
22
|
tenantId: string;
|
|
5
23
|
}
|
|
24
|
+
/**
|
|
25
|
+
* Parameters for logging in as a tenant admin (dashboard user).
|
|
26
|
+
*
|
|
27
|
+
* Tenant admins authenticate with email + password and get a JWT that allows
|
|
28
|
+
* management of their own tenant's resources (extensions, DIDs, queues, etc.).
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```ts
|
|
32
|
+
* const { token, tenant } = await voip.adminLogin({
|
|
33
|
+
* email: 'admin@acme.com',
|
|
34
|
+
* password: 'admin-password',
|
|
35
|
+
* });
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
6
38
|
export interface AdminLoginParams {
|
|
39
|
+
/** Admin email address for the tenant (set during tenant creation). */
|
|
7
40
|
email: string;
|
|
41
|
+
/** Admin password for the tenant admin account. */
|
|
8
42
|
password: string;
|
|
9
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* Response from both `login()` (extension) and `adminLogin()` (admin).
|
|
46
|
+
*
|
|
47
|
+
* Always contains a JWT `token`. The SDK stores this internally and attaches it
|
|
48
|
+
* to subsequent requests as `Authorization: Bearer <token>`.
|
|
49
|
+
*
|
|
50
|
+
* For extension login, `user` is populated with the extension profile.
|
|
51
|
+
* For admin login, `tenant` is populated. Global superadmin login populates both.
|
|
52
|
+
*/
|
|
10
53
|
export interface AuthResponse {
|
|
54
|
+
/** JWT token (HS256). Store this and pass it to the SDK constructor or set on the client. Expires based on server config (default 24h). */
|
|
11
55
|
token: string;
|
|
56
|
+
/** Extension profile — populated when logging in as an extension user. Null for admin logins. */
|
|
12
57
|
user?: {
|
|
58
|
+
/** Extension UUID in the database (not the extension number). */
|
|
13
59
|
id: string;
|
|
60
|
+
/** Extension number string (e.g. `"1001"`). */
|
|
14
61
|
extension: string;
|
|
62
|
+
/** Human-readable display name. `null` if not set on the extension. */
|
|
15
63
|
displayName: string | null;
|
|
64
|
+
/** UUID of the tenant this extension belongs to. */
|
|
16
65
|
tenantId: string;
|
|
17
66
|
};
|
|
67
|
+
/** Tenant info — populated when logging in as an admin or superadmin. Null for extension-only logins. */
|
|
18
68
|
tenant?: {
|
|
69
|
+
/** Tenant UUID. */
|
|
19
70
|
id: string;
|
|
71
|
+
/** Subdomain slug (e.g. `"acme"`). Used in URLs like `acme.demo.cemscale.com`. */
|
|
20
72
|
subdomain: string;
|
|
73
|
+
/** Company/tenant display name (e.g. `"Acme Corp"`). */
|
|
21
74
|
companyName: string;
|
|
22
75
|
};
|
|
23
76
|
}
|
|
77
|
+
/**
|
|
78
|
+
* TURN/STUN credentials for WebRTC ICE negotiation.
|
|
79
|
+
*
|
|
80
|
+
* The TURN server relays media when a direct peer-to-peer connection can't be
|
|
81
|
+
* established (NAT, firewall). These credentials are time-limited (default 86400s).
|
|
82
|
+
*
|
|
83
|
+
* Retrieve via `getTurnCredentials()`. Pass to the WebRTCPhone constructor.
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* ```ts
|
|
87
|
+
* const creds = await voip.getTurnCredentials();
|
|
88
|
+
* const phone = new WebRTCPhone({
|
|
89
|
+
* ...sipConfig,
|
|
90
|
+
* turnServers: [{
|
|
91
|
+
* urls: creds.urls,
|
|
92
|
+
* username: creds.username,
|
|
93
|
+
* credential: creds.credential,
|
|
94
|
+
* }],
|
|
95
|
+
* });
|
|
96
|
+
* ```
|
|
97
|
+
*/
|
|
24
98
|
export interface TurnCredentials {
|
|
99
|
+
/** TURN server URLs (e.g. `["turn:3.20.219.41:3478?transport=udp", "turns:3.20.219.41:5349?transport=tcp"]`). */
|
|
25
100
|
urls: string[];
|
|
101
|
+
/** Temporary TURN username generated for this session. Format: `<expiry_timestamp>:<extension>`. */
|
|
26
102
|
username: string;
|
|
103
|
+
/** HMAC-SHA1 credential derived from the TURN secret + username. Valid only until expiry. */
|
|
27
104
|
credential: string;
|
|
105
|
+
/** Time-to-live in seconds (default 86400 = 24 hours). Credentials expire after this. */
|
|
28
106
|
ttl: number;
|
|
29
107
|
}
|
|
30
108
|
/**
|
|
@@ -77,20 +155,31 @@ export interface TurnCredentials {
|
|
|
77
155
|
* database, send them in emails, or cache them indefinitely.
|
|
78
156
|
*/
|
|
79
157
|
export interface CallRecord {
|
|
158
|
+
/** Database record UUID. Use this for `getCall(id)`, `getRecordingUrl(id)`, and the recording audio endpoint `/api/recordings/<id>/audio`. Distinguish from `call_uuid` which is the FreeSWITCH-level identifier. */
|
|
80
159
|
id: string;
|
|
160
|
+
/** Tenant UUID the call belongs to. Present for tenant-scoped queries; may be absent if querying as superadmin across all tenants. */
|
|
81
161
|
tenant_id?: string;
|
|
162
|
+
/** FreeSWITCH call UUID. This is the server-side channel identifier used in FreeSWITCH commands (e.g. `uuid_kill`). Different from `id` (the DB record UUID). Use `call_uuid` for live call operations, `id` for API/CDR lookups. Example: `"a1b2c3d4-e5f6-7890-abcd-ef1234567890"`. */
|
|
82
163
|
call_uuid: string;
|
|
164
|
+
/** Direction of the call relative to the tenant: `'inbound'` (PSTN → extension), `'outbound'` (extension → PSTN), `'internal'` (extension → extension within same tenant). */
|
|
83
165
|
direction: 'inbound' | 'outbound' | 'internal';
|
|
166
|
+
/** Display name from the caller's SIP header. `null` if not provided by the carrier. Example: `"John Doe"`. */
|
|
84
167
|
caller_id_name: string | null;
|
|
168
|
+
/** E.164 caller phone number. `null` if the caller number was hidden/unknown. Example: `"+17865551234"`. */
|
|
85
169
|
caller_id_number: string | null;
|
|
170
|
+
/** Destination of the call. For inbound calls this is the DID or extension DNIS. For outbound calls this is the dialed PSTN number. `null` for some internal calls. Example: `"+17869876543"` or `"1001"`. */
|
|
86
171
|
destination: string | null;
|
|
172
|
+
/** Call outcome: `'completed'` (answered + hung up normally), `'failed'` (never connected), `'missed'` (rang but not answered), `'voicemail'` (went to voicemail). `null` for in-progress or unknown state. */
|
|
87
173
|
status: string | null;
|
|
174
|
+
/** FreeSWITCH hangup cause code string (e.g. `"NORMAL_CLEARING"`, `"NO_ANSWER"`, `"USER_BUSY"`). `null` if the call hasn't ended. */
|
|
88
175
|
hangup_cause: string | null;
|
|
176
|
+
/** Total call duration in seconds from start to end. `null` for active/unfinished calls. */
|
|
89
177
|
duration_seconds: number | null;
|
|
178
|
+
/** Billable seconds — from answer to hangup. `null` if call was never answered. Always ≤ `duration_seconds`. */
|
|
90
179
|
billsec: number | null;
|
|
91
|
-
/** External number the call was forwarded to. Null if no forwarding occurred. */
|
|
180
|
+
/** External number the call was forwarded to. Null if no forwarding occurred. Example: `"+13051234567"`. */
|
|
92
181
|
forwarded_to?: string | null;
|
|
93
|
-
/** Whether a voicemail message was left by the caller */
|
|
182
|
+
/** Whether a voicemail message was left by the caller. `true` = voicemail left, `false` or `null` = no voicemail. */
|
|
94
183
|
was_voicemail?: boolean | null;
|
|
95
184
|
/**
|
|
96
185
|
* API endpoint URL for streaming/downloading the call recording.
|
|
@@ -138,42 +227,81 @@ export interface CallRecord {
|
|
|
138
227
|
* ```
|
|
139
228
|
*/
|
|
140
229
|
cdn_url: string | null;
|
|
230
|
+
/** ISO 8601 timestamp when the call was initiated. `null` for pre-CDR records. Example: `"2025-06-04T14:30:00.000Z"`. */
|
|
141
231
|
started_at: string | null;
|
|
232
|
+
/** ISO 8601 timestamp when the call was answered (picked up). `null` if never answered. Example: `"2025-06-04T14:30:05.000Z"`. */
|
|
142
233
|
answered_at: string | null;
|
|
234
|
+
/** ISO 8601 timestamp when the call ended (hung up). `null` for active calls. Example: `"2025-06-04T14:32:30.000Z"`. */
|
|
143
235
|
ended_at: string | null;
|
|
236
|
+
/** Arbitrary key-value metadata attached to the call. `null` if no metadata was set. */
|
|
144
237
|
metadata?: Record<string, unknown> | null;
|
|
145
|
-
/** Present when queried as global superadmin */
|
|
238
|
+
/** Present when queried as global superadmin — contains tenant details for this call. */
|
|
146
239
|
tenants?: TenantInfo;
|
|
147
|
-
/** Present when queried as global superadmin (convenience top-level fields) */
|
|
240
|
+
/** Present when queried as global superadmin (convenience top-level fields). Tenant company name. */
|
|
148
241
|
company_name?: string;
|
|
242
|
+
/** Present when queried as global superadmin (convenience top-level fields). Tenant subdomain. */
|
|
149
243
|
subdomain?: string;
|
|
150
244
|
}
|
|
245
|
+
/**
|
|
246
|
+
* Standard pagination metadata returned by all list endpoints.
|
|
247
|
+
*
|
|
248
|
+
* Use `pages` to render page controls and `total` for summary text.
|
|
249
|
+
* On the last page, `page` === `pages`.
|
|
250
|
+
*/
|
|
151
251
|
export interface PaginationInfo {
|
|
252
|
+
/** Current page number (1-indexed). Example: `1`. */
|
|
152
253
|
page: number;
|
|
254
|
+
/** Number of items per page as requested. Example: `50`. */
|
|
153
255
|
limit: number;
|
|
256
|
+
/** Total number of items across all pages. Example: `142`. */
|
|
154
257
|
total: number;
|
|
258
|
+
/** Total number of pages. Example: `3`. Computed as `Math.ceil(total / limit)`. */
|
|
155
259
|
pages: number;
|
|
156
260
|
}
|
|
261
|
+
/**
|
|
262
|
+
* Response from `listCalls()` — a paginated list of call detail records.
|
|
263
|
+
*
|
|
264
|
+
* Use `pagination.total` for a summary badge and `pagination.pages` for pagination controls.
|
|
265
|
+
*/
|
|
157
266
|
export interface CallListResponse {
|
|
158
267
|
calls: CallRecord[];
|
|
159
268
|
pagination: PaginationInfo;
|
|
160
269
|
}
|
|
270
|
+
/**
|
|
271
|
+
* Filtering/pagination params for `listCalls()`.
|
|
272
|
+
*
|
|
273
|
+
* All fields are optional. Omitted fields are not filtered (returns all matching records).
|
|
274
|
+
* Combine filters: `{ direction: 'inbound', status: 'completed', dateFrom: '2025-06-01' }`
|
|
275
|
+
* returns only completed inbound calls since June 1.
|
|
276
|
+
*
|
|
277
|
+
* @example
|
|
278
|
+
* ```ts
|
|
279
|
+
* // Get last 10 missed inbound calls
|
|
280
|
+
* const { calls } = await voip.listCalls({
|
|
281
|
+
* direction: 'inbound',
|
|
282
|
+
* status: 'missed',
|
|
283
|
+
* limit: 10,
|
|
284
|
+
* });
|
|
285
|
+
* ```
|
|
286
|
+
*/
|
|
161
287
|
export interface CallListParams {
|
|
288
|
+
/** Page number (1-indexed). Default: `1`. */
|
|
162
289
|
page?: number;
|
|
163
|
-
/** Max 500 per page */
|
|
290
|
+
/** Max 500 per page. Default: `50`. */
|
|
164
291
|
limit?: number;
|
|
292
|
+
/** Filter by call direction. Default: `'all'` (no filter). */
|
|
165
293
|
direction?: 'inbound' | 'outbound' | 'internal' | 'all';
|
|
166
|
-
/** Filter by call status */
|
|
294
|
+
/** Filter by call status. Default: `'all'` (no filter). */
|
|
167
295
|
status?: 'completed' | 'failed' | 'missed' | 'voicemail' | 'all';
|
|
168
|
-
/** ISO date string — calls started on or after this date */
|
|
296
|
+
/** ISO date string — calls started on or after this date. Example: `"2025-06-01T00:00:00.000Z"`. */
|
|
169
297
|
dateFrom?: string;
|
|
170
|
-
/** ISO date string — calls started on or before this date */
|
|
298
|
+
/** ISO date string — calls started on or before this date. Example: `"2025-06-04T23:59:59.999Z"`. */
|
|
171
299
|
dateTo?: string;
|
|
172
|
-
/** Filter by extension number (matches caller or destination) */
|
|
300
|
+
/** Filter by extension number (matches caller or destination). Example: `"1001"`. */
|
|
173
301
|
extension?: string;
|
|
174
|
-
/** Search by phone number or name (matches caller_id_number, destination, caller_id_name) */
|
|
302
|
+
/** Search by phone number or name (matches caller_id_number, destination, caller_id_name). Partial match, case-insensitive. Example: `"+1786"`. */
|
|
175
303
|
number?: string;
|
|
176
|
-
/** Filter by tenant ID (superadmin only — alternative to X-Tenant-ID header) */
|
|
304
|
+
/** Filter by tenant ID (superadmin only — alternative to X-Tenant-ID header). */
|
|
177
305
|
tenantId?: string;
|
|
178
306
|
/**
|
|
179
307
|
* Filter by forwarding status.
|
|
@@ -182,54 +310,178 @@ export interface CallListParams {
|
|
|
182
310
|
* - omit: return all calls regardless of forwarding
|
|
183
311
|
*/
|
|
184
312
|
forwarded?: 'true' | 'false';
|
|
185
|
-
/** Search by the external number the call was forwarded to (partial match, case-insensitive) */
|
|
313
|
+
/** Search by the external number the call was forwarded to (partial match, case-insensitive). */
|
|
186
314
|
forwardedTo?: string;
|
|
187
315
|
}
|
|
316
|
+
/**
|
|
317
|
+
* Parameters for originating (placing) a new outbound call from a webphone/extension.
|
|
318
|
+
*
|
|
319
|
+
* The server creates a new call leg from the specified extension to the PSTN number
|
|
320
|
+
* and bridges it to the extension's WebRTC session.
|
|
321
|
+
*
|
|
322
|
+
* @example
|
|
323
|
+
* ```ts
|
|
324
|
+
* const { callUuid } = await voip.originateCall({
|
|
325
|
+
* fromExtension: '1001',
|
|
326
|
+
* toNumber: '+17865551234',
|
|
327
|
+
* });
|
|
328
|
+
* ```
|
|
329
|
+
*/
|
|
188
330
|
export interface OriginateParams {
|
|
331
|
+
/** Extension number to originate the call from. Must be an active extension in your tenant. Example: `"1001"`. */
|
|
189
332
|
fromExtension: string;
|
|
333
|
+
/** Destination PSTN number in E.164 format. Example: `"+17865551234"`. */
|
|
190
334
|
toNumber: string;
|
|
191
335
|
}
|
|
336
|
+
/**
|
|
337
|
+
* Response from `originateCall()`.
|
|
338
|
+
*
|
|
339
|
+
* Contains the FreeSWITCH UUID of the outbound call leg for monitoring.
|
|
340
|
+
*/
|
|
192
341
|
export interface OriginateResponse {
|
|
342
|
+
/** Human-readable status message. Example: `"Call originated successfully"`. */
|
|
193
343
|
message: string;
|
|
344
|
+
/** FreeSWITCH call UUID of the originated outbound leg. Use this to track the call. */
|
|
194
345
|
callUuid: string;
|
|
195
346
|
}
|
|
347
|
+
/**
|
|
348
|
+
* Parameters for transferring an active call to another destination.
|
|
349
|
+
*
|
|
350
|
+
* Supports blind transfer (immediate, no consultation) and attended transfer
|
|
351
|
+
* (speak to the target first, then merge).
|
|
352
|
+
*
|
|
353
|
+
* @example
|
|
354
|
+
* ```ts
|
|
355
|
+
* // Blind transfer — caller goes directly to target
|
|
356
|
+
* await voip.transferCall(callId, {
|
|
357
|
+
* targetExtension: '1002',
|
|
358
|
+
* type: 'blind',
|
|
359
|
+
* });
|
|
360
|
+
*
|
|
361
|
+
* // Attended transfer — you speak first, then complete the transfer
|
|
362
|
+
* await voip.transferCall(callId, {
|
|
363
|
+
* targetExtension: '1002',
|
|
364
|
+
* type: 'attended',
|
|
365
|
+
* });
|
|
366
|
+
* ```
|
|
367
|
+
*/
|
|
196
368
|
export interface TransferParams {
|
|
369
|
+
/** Target extension number to transfer the call to. Example: `"1002"`. */
|
|
197
370
|
targetExtension: string;
|
|
371
|
+
/** Transfer type. `'blind'` = immediate (SIP REFER). `'attended'` = consult then complete (conference bridge). Default: `'blind'`. */
|
|
198
372
|
type?: 'blind' | 'attended';
|
|
199
373
|
}
|
|
374
|
+
/**
|
|
375
|
+
* Response from call eavesdropping (listen in on an active call).
|
|
376
|
+
*
|
|
377
|
+
* Returned by `eavesdropCall()`. Supports whisper (coach can talk to the agent
|
|
378
|
+
* without the caller hearing), spy (listen-only), and full (3-way join).
|
|
379
|
+
*/
|
|
200
380
|
export interface EavesdropResponse {
|
|
381
|
+
/** Human-readable message. Example: `"Whisper session started"`. */
|
|
201
382
|
message: string;
|
|
383
|
+
/** FreeSWITCH UUID of the eavesdrop channel. */
|
|
202
384
|
spyUuid: string;
|
|
385
|
+
/** FreeSWITCH UUID of the target call being monitored. */
|
|
203
386
|
targetCallUuid: string;
|
|
387
|
+
/** Eavesdrop mode: `'whisper'`, `'spy'`, or `'full'`. */
|
|
204
388
|
mode: string;
|
|
205
389
|
}
|
|
390
|
+
/**
|
|
391
|
+
* A currently active (in-progress) call on the FreeSWITCH server.
|
|
392
|
+
*
|
|
393
|
+
* Returned by `listActiveCalls()`. Each entry represents one call leg (channel).
|
|
394
|
+
* For a two-party call, you'll see two entries — one for each leg.
|
|
395
|
+
*
|
|
396
|
+
* **Key field:** `uuid` — this is the FreeSWITCH channel UUID required for
|
|
397
|
+
* three-way calling operations (`addCallParticipant`, `mergeCalls`).
|
|
398
|
+
* It is NOT the same as `call_uuid` (which is the logical call identifier).
|
|
399
|
+
*
|
|
400
|
+
* @example
|
|
401
|
+
* ```ts
|
|
402
|
+
* // List all active calls and show the caller/destination
|
|
403
|
+
* const { calls } = await voip.listActiveCalls();
|
|
404
|
+
* calls.forEach(c => {
|
|
405
|
+
* console.log(`${c.caller_id_number} → ${c.destination} (${c.status})`);
|
|
406
|
+
* });
|
|
407
|
+
* ```
|
|
408
|
+
*/
|
|
206
409
|
export interface ActiveCall {
|
|
207
|
-
/** FreeSWITCH channel UUID — required for three-way operations */
|
|
410
|
+
/** FreeSWITCH channel UUID — required for three-way operations. This is the server-side channel identifier. Example: `"a1b2c3d4-e5f6-7890-abcd-ef1234567890"`. */
|
|
208
411
|
uuid: string;
|
|
412
|
+
/** Logical call UUID (same across both legs of a bridged call). Use for CDR matching and WebSocket event correlation. Example: `"c0ffee00-dead-beef-0000-000000000001"`. */
|
|
209
413
|
call_uuid: string;
|
|
414
|
+
/** Caller display name from SIP header. Example: `"John Smith"`. */
|
|
210
415
|
caller_id_name: string;
|
|
416
|
+
/** Caller phone number. Example: `"+17865551234"` or `"1001"` for internal calls. */
|
|
211
417
|
caller_id_number: string;
|
|
418
|
+
/** Destination of the call. For outbound calls this is the PSTN number being dialed. For inbound this is the DID or extension. Example: `"+17869876543"`. */
|
|
212
419
|
destination: string;
|
|
420
|
+
/** Call direction: `'inbound'`, `'outbound'`, or `'internal'`. */
|
|
213
421
|
direction: string;
|
|
422
|
+
/** Channel state: `'CS_EXECUTE'`, `'CS_CONSUME_MEDIA'`, `'CS_HIBERNATE'`, etc. Use `answered` boolean for high-level state. */
|
|
214
423
|
status: string;
|
|
424
|
+
/** ISO 8601 timestamp when the call channel was created. Example: `"2025-06-04T14:30:00Z"`. */
|
|
215
425
|
started_at: string;
|
|
426
|
+
/** Whether the call has been answered (both parties connected). `false` during ringing/early-media. */
|
|
216
427
|
answered: boolean;
|
|
428
|
+
/** Whether this channel currently has music-on-hold active. */
|
|
217
429
|
on_hold: boolean;
|
|
218
430
|
}
|
|
431
|
+
/**
|
|
432
|
+
* Quick call statistics for the current tenant (today and this month).
|
|
433
|
+
*
|
|
434
|
+
* Returned by `getCallStats()`. Use for dashboard summary badges.
|
|
435
|
+
*
|
|
436
|
+
* @example
|
|
437
|
+
* ```ts
|
|
438
|
+
* const { stats } = await voip.getCallStats();
|
|
439
|
+
* console.log(`Today: ${stats.total} calls (${stats.inbound} in, ${stats.outbound} out)`);
|
|
440
|
+
* ```
|
|
441
|
+
*/
|
|
219
442
|
export interface CallStats {
|
|
220
443
|
stats: {
|
|
444
|
+
/** Total calls in the current period. */
|
|
221
445
|
total: number;
|
|
446
|
+
/** Inbound calls in the current period. */
|
|
222
447
|
inbound: number;
|
|
448
|
+
/** Outbound calls in the current period. */
|
|
223
449
|
outbound: number;
|
|
450
|
+
/** Internal (extension-to-extension) calls in the current period. */
|
|
224
451
|
internal: number;
|
|
452
|
+
/** Period description: `'today'` or `'month'`. */
|
|
225
453
|
period: string;
|
|
226
454
|
};
|
|
227
455
|
}
|
|
456
|
+
/**
|
|
457
|
+
* A SIP extension (phone user) within a tenant.
|
|
458
|
+
*
|
|
459
|
+
* Extensions are the core entity — every person who makes/receives calls has one.
|
|
460
|
+
* Each extension has a SIP password for registration, voicemail settings,
|
|
461
|
+
* call forwarding rules, recording preferences, and real-time presence status.
|
|
462
|
+
*
|
|
463
|
+
* Returned by `listExtensions()`, `getExtension()`, `createExtension()`, and `updateExtension()`.
|
|
464
|
+
*
|
|
465
|
+
* @example
|
|
466
|
+
* ```ts
|
|
467
|
+
* // List all extensions and show their presence
|
|
468
|
+
* const { extensions } = await voip.listExtensions();
|
|
469
|
+
* extensions.forEach(ext => {
|
|
470
|
+
* const presenceIcon = ext.presence === 'on_call' ? '🟢' : ext.presence === 'offline' ? '⚫' : '⭕';
|
|
471
|
+
* console.log(`${presenceIcon} ${ext.extension} — ${ext.display_name}`);
|
|
472
|
+
* });
|
|
473
|
+
* ```
|
|
474
|
+
*/
|
|
228
475
|
export interface Extension {
|
|
476
|
+
/** Database UUID of the extension record. */
|
|
229
477
|
id: string;
|
|
478
|
+
/** Tenant UUID this extension belongs to. Present for tenant-scoped queries; may be absent in superadmin global lists. */
|
|
230
479
|
tenant_id?: string;
|
|
480
|
+
/** Extension number (3-6 digits). Used for dialing internally and as the SIP username. Example: `"1001"`. */
|
|
231
481
|
extension: string;
|
|
482
|
+
/** Human-readable display name shown to other callers and in the dashboard. `null` if not set. Example: `"John Smith"`. */
|
|
232
483
|
display_name: string | null;
|
|
484
|
+
/** Whether voicemail is enabled for this extension. When enabled, unanswered calls go to voicemail after the ring timeout. Example: `true`. */
|
|
233
485
|
voicemail_enabled: boolean;
|
|
234
486
|
/**
|
|
235
487
|
* Whether call recording is enabled for this extension.
|
|
@@ -243,31 +495,68 @@ export interface Extension {
|
|
|
243
495
|
* The tenant must also have `noise_cancellation_enabled = true` (the default) for NC to apply.
|
|
244
496
|
*/
|
|
245
497
|
noise_cancellation_enabled?: boolean;
|
|
498
|
+
/** 4-6 digit PIN required to access voicemail via *97. `null` if no PIN is set (voicemail has no password protection). */
|
|
246
499
|
voicemail_pin?: string | null;
|
|
500
|
+
/** Type of voicemail greeting: `'default'`, `'name'`, `'custom_audio'`, `'custom_tts'`. `null` if using default system greeting. */
|
|
247
501
|
voicemail_greeting_type?: VoicemailGreetingType | null;
|
|
502
|
+
/** Text spoken for TTS greeting. `null` if not using TTS. Example: `"You've reached John. Please leave a message."`. */
|
|
248
503
|
voicemail_greeting_text?: string | null;
|
|
504
|
+
/** Server path to uploaded custom audio greeting file. `null` if no custom audio. */
|
|
249
505
|
voicemail_greeting_audio_path?: string | null;
|
|
506
|
+
/** Whether Do Not Disturb is enabled. When true, calls go directly to voicemail without ringing. */
|
|
250
507
|
do_not_disturb: boolean;
|
|
508
|
+
/** Outbound caller ID (DID number) shown to recipients when this extension makes outbound calls. Falls back to tenant's first active DID if `null`. Example: `"+17868392727"`. */
|
|
251
509
|
outbound_caller_id?: string | null;
|
|
510
|
+
/** Extension status: `'active'` (can register and make/receive calls), `'disabled'` (cannot register or call). */
|
|
252
511
|
status: string;
|
|
253
|
-
/** Real-time presence status: 'available'
|
|
512
|
+
/** Real-time presence status from Redis: `'available'`, `'on_call'`, `'offline'`, `'do_not_disturb'`. Use for presence indicators in the UI. Not persisted — comes from live registration/call state. */
|
|
254
513
|
presence?: string;
|
|
514
|
+
/** ISO 8601 timestamp when this extension was created. Example: `"2025-01-15T10:30:00.000Z"`. */
|
|
255
515
|
created_at: string;
|
|
516
|
+
/** Whether unconditional call forwarding is enabled. */
|
|
256
517
|
call_forward_enabled?: boolean;
|
|
518
|
+
/** Number to forward calls to when `call_forward_enabled` is true. E.164 for external, extension number for internal. Example: `"+13051234567"`. */
|
|
257
519
|
call_forward_number?: string | null;
|
|
520
|
+
/** Forward type: `'always'`, `'busy'`, or `'no-answer'`. `null` when forwarding is disabled. */
|
|
258
521
|
call_forward_type?: string | null;
|
|
522
|
+
/** External CRM user ID for integration mapping. `null` if not linked to a CRM record. */
|
|
259
523
|
crm_user_id?: string | null;
|
|
524
|
+
/** Arbitrary JSON metadata from CRM integration. `null` if no metadata set. */
|
|
260
525
|
crm_metadata?: Record<string, unknown> | null;
|
|
261
|
-
/** Present when queried as global superadmin */
|
|
526
|
+
/** Present when queried as global superadmin — contains tenant details. */
|
|
262
527
|
tenants?: TenantInfo;
|
|
263
528
|
}
|
|
529
|
+
/**
|
|
530
|
+
* Parameters for creating a new SIP extension.
|
|
531
|
+
*
|
|
532
|
+
* At minimum, provide `extension`, `password`, and `displayName`.
|
|
533
|
+
* All other fields are optional with sensible defaults.
|
|
534
|
+
*
|
|
535
|
+
* @example
|
|
536
|
+
* ```ts
|
|
537
|
+
* // Create a basic extension with voicemail PIN
|
|
538
|
+
* const { extension: ext } = await voip.createExtension({
|
|
539
|
+
* extension: '2001',
|
|
540
|
+
* password: 'secure123',
|
|
541
|
+
* displayName: 'Alice Jones',
|
|
542
|
+
* voicemailEnabled: true,
|
|
543
|
+
* voicemailPin: '1234',
|
|
544
|
+
* outboundCallerId: '+17868392727',
|
|
545
|
+
* }, { tenantId: 'tenant-uuid' });
|
|
546
|
+
* ```
|
|
547
|
+
*/
|
|
264
548
|
export interface CreateExtensionParams {
|
|
549
|
+
/** Extension number (3-6 digits). Must be unique within the tenant. Example: `"2001"`. */
|
|
265
550
|
extension: string;
|
|
551
|
+
/** SIP password for registration. Min 6 characters. Used by desk phones and WebRTC softphones to authenticate. Example: `"secure123"`. */
|
|
266
552
|
password: string;
|
|
553
|
+
/** Human-readable display name. Shown to other callers via caller ID name. Example: `"Alice Jones"`. */
|
|
267
554
|
displayName: string;
|
|
555
|
+
/** Enable voicemail for this extension. Default: `true`. */
|
|
268
556
|
voicemailEnabled?: boolean;
|
|
269
|
-
/** 4-6 digit PIN required to check voicemail via *97. If not set, voicemail has no PIN protection. */
|
|
557
|
+
/** 4-6 digit PIN required to check voicemail via *97. If not set, voicemail has no PIN protection. Example: `"1234"`. */
|
|
270
558
|
voicemailPin?: string;
|
|
559
|
+
/** Initial Do Not Disturb state. Default: `false`. */
|
|
271
560
|
doNotDisturb?: boolean;
|
|
272
561
|
/**
|
|
273
562
|
* Whether to record all calls for this extension.
|
|
@@ -292,13 +581,38 @@ export interface CreateExtensionParams {
|
|
|
292
581
|
*/
|
|
293
582
|
outboundCallerId?: string | null;
|
|
294
583
|
}
|
|
584
|
+
/**
|
|
585
|
+
* Parameters for updating an existing SIP extension.
|
|
586
|
+
*
|
|
587
|
+
* All fields are optional — only include fields you want to change.
|
|
588
|
+
* Send `null` for string fields (like `voicemailPin`, `outboundCallerId`, `crmUserId`) to clear them.
|
|
589
|
+
*
|
|
590
|
+
* @example
|
|
591
|
+
* ```ts
|
|
592
|
+
* // Rename extension and enable DND
|
|
593
|
+
* await voip.updateExtension(extId, {
|
|
594
|
+
* displayName: 'Alice J.',
|
|
595
|
+
* doNotDisturb: true,
|
|
596
|
+
* });
|
|
597
|
+
*
|
|
598
|
+
* // Clear the outbound caller ID (revert to tenant default)
|
|
599
|
+
* await voip.updateExtension(extId, {
|
|
600
|
+
* outboundCallerId: null,
|
|
601
|
+
* });
|
|
602
|
+
* ```
|
|
603
|
+
*/
|
|
295
604
|
export interface UpdateExtensionParams {
|
|
605
|
+
/** New display name. Example: `"Alice Jones-Smith"`. */
|
|
296
606
|
displayName?: string;
|
|
607
|
+
/** New SIP password. Min 6 characters. */
|
|
297
608
|
password?: string;
|
|
609
|
+
/** Enable or disable voicemail. */
|
|
298
610
|
voicemailEnabled?: boolean;
|
|
299
611
|
/** 4-6 digit PIN for voicemail access. Set to null to remove PIN protection. */
|
|
300
612
|
voicemailPin?: string | null;
|
|
613
|
+
/** Enable or disable Do Not Disturb. When true, calls go straight to voicemail. */
|
|
301
614
|
doNotDisturb?: boolean;
|
|
615
|
+
/** Set extension status: `'active'` (can register/call) or `'disabled'` (blocked). */
|
|
302
616
|
status?: 'active' | 'disabled';
|
|
303
617
|
/**
|
|
304
618
|
* Enable or disable call recording for this extension.
|
|
@@ -319,7 +633,9 @@ export interface UpdateExtensionParams {
|
|
|
319
633
|
* Set to `null` to clear (calls will fall back to the tenant's first active DID).
|
|
320
634
|
*/
|
|
321
635
|
outboundCallerId?: string | null;
|
|
636
|
+
/** CRM user ID for integration mapping. Set to `null` to unlink. */
|
|
322
637
|
crmUserId?: string | null;
|
|
638
|
+
/** Arbitrary JSON metadata from CRM. Set to `null` to clear. */
|
|
323
639
|
crmMetadata?: Record<string, unknown> | null;
|
|
324
640
|
}
|
|
325
641
|
export interface Tenant {
|
|
@@ -743,12 +1059,21 @@ export interface RecordingUrlResponse {
|
|
|
743
1059
|
/** Always `null` — CDN URLs and local URLs don't expire. */
|
|
744
1060
|
expiresIn: number | null;
|
|
745
1061
|
}
|
|
1062
|
+
/**
|
|
1063
|
+
* Filtering/pagination params for `listRecordings()`.
|
|
1064
|
+
*
|
|
1065
|
+
* All fields optional. Omit a field to skip that filter.
|
|
1066
|
+
*/
|
|
746
1067
|
export interface RecordingListParams {
|
|
1068
|
+
/** Page number (1-indexed). Default: `1`. */
|
|
747
1069
|
page?: number;
|
|
1070
|
+
/** Items per page. Default: `50`. */
|
|
748
1071
|
limit?: number;
|
|
1072
|
+
/** ISO date string — recordings after this date. Example: `"2025-06-01T00:00:00.000Z"`. */
|
|
749
1073
|
dateFrom?: string;
|
|
1074
|
+
/** ISO date string — recordings before this date. Example: `"2025-06-04T23:59:59.999Z"`. */
|
|
750
1075
|
dateTo?: string;
|
|
751
|
-
/** Filter by direction */
|
|
1076
|
+
/** Filter by direction. `'inbound'` for incoming call recordings, `'outbound'` for outgoing. */
|
|
752
1077
|
direction?: 'inbound' | 'outbound';
|
|
753
1078
|
}
|
|
754
1079
|
export interface RecordingListResponse {
|
|
@@ -756,6 +1081,25 @@ export interface RecordingListResponse {
|
|
|
756
1081
|
pagination: PaginationInfo;
|
|
757
1082
|
}
|
|
758
1083
|
export type PresenceStatus = 'available' | 'registered' | 'on_call' | 'busy' | 'ringing' | 'dnd' | 'idle' | 'offline';
|
|
1084
|
+
/**
|
|
1085
|
+
* Map of extension numbers to their current presence status.
|
|
1086
|
+
*
|
|
1087
|
+
* Keys are extension numbers (e.g. `"1001"`), values are presence status strings.
|
|
1088
|
+
* Use this for a quick presence overview — iterate keys and show status badges.
|
|
1089
|
+
*
|
|
1090
|
+
* For detailed presence (with call UUID, caller info, direction, timestamps),
|
|
1091
|
+
* use `listPresenceSubscriptions()` which returns `PresenceDetailMap`.
|
|
1092
|
+
*
|
|
1093
|
+
* @example
|
|
1094
|
+
* ```ts
|
|
1095
|
+
* const presence = await voip.getPresence();
|
|
1096
|
+
* // presence = { "1001": "on_call", "1002": "available", "1003": "offline" }
|
|
1097
|
+
* Object.entries(presence).forEach(([ext, status]) => {
|
|
1098
|
+
* const color = status === 'on_call' ? 'green' : status === 'offline' ? 'gray' : 'blue';
|
|
1099
|
+
* renderBadge(ext, status, color);
|
|
1100
|
+
* });
|
|
1101
|
+
* ```
|
|
1102
|
+
*/
|
|
759
1103
|
export interface PresenceMap {
|
|
760
1104
|
[extension: string]: PresenceStatus | string;
|
|
761
1105
|
}
|
|
@@ -887,16 +1231,75 @@ export interface WebRTCConfig {
|
|
|
887
1231
|
*/
|
|
888
1232
|
jwtToken?: string;
|
|
889
1233
|
}
|
|
1234
|
+
/**
|
|
1235
|
+
* Information about an active WebRTC call managed by the SIP.js softphone.
|
|
1236
|
+
*
|
|
1237
|
+
* ## CRITICAL: `id` vs `fsChannelUuid` — these are NOT the same thing
|
|
1238
|
+
*
|
|
1239
|
+
* | Field | What it is | When populated | Used for |
|
|
1240
|
+
* |-------|-----------|---------------|----------|
|
|
1241
|
+
* | `id` | sip.js session ID (local, client-generated) | Immediately (ringing) | Answer, reject, hold, mute, DTMF, hangup |
|
|
1242
|
+
* | `fsChannelUuid` | FreeSWITCH channel UUID (server-side) | AFTER connect (`state: 'established'`) | Three-way operations (`addCallParticipant`, `mergeCalls`) |
|
|
1243
|
+
*
|
|
1244
|
+
* **Never pass `id` to three-way methods.** Always use `fsChannelUuid` for
|
|
1245
|
+
* server-side operations. `id` is a sip.js internal identifier and has no meaning
|
|
1246
|
+
* on the FreeSWITCH server.
|
|
1247
|
+
*
|
|
1248
|
+
* ## Lifecycle
|
|
1249
|
+
*
|
|
1250
|
+
* ```
|
|
1251
|
+
* idle → connecting → ringing → established → terminating → terminated
|
|
1252
|
+
* ↕
|
|
1253
|
+
* held
|
|
1254
|
+
* ```
|
|
1255
|
+
*
|
|
1256
|
+
* - `idle`: No active call. Phone ready.
|
|
1257
|
+
* - `connecting`: Outbound call — sending INVITE, waiting for provisional response.
|
|
1258
|
+
* - `ringing`: Outbound — receiving 180 Ringing. Inbound — incoming call, waiting for answer.
|
|
1259
|
+
* - `established`: Call is connected, audio flows. `fsChannelUuid` becomes non-null here.
|
|
1260
|
+
* - `held`: Call is on hold (re-INVITE with sendonly). Music-on-hold plays to remote party.
|
|
1261
|
+
* - `terminating`: BYE sent or received, waiting for final ACK.
|
|
1262
|
+
* - `terminated`: Call ended. Resources released.
|
|
1263
|
+
*
|
|
1264
|
+
* ## UI guidelines
|
|
1265
|
+
*
|
|
1266
|
+
* - Show DTMF dialpad when `state === 'established'` and NOT `held`.
|
|
1267
|
+
* - Grey out hold button during `connecting` and `ringing` — hold is only available when established.
|
|
1268
|
+
* - Show "Calling..." during `connecting`, "Ringing..." during `ringing`, timer during `established`.
|
|
1269
|
+
* - If `isPaging === true`, auto-answer and route audio to speaker (no earpiece).
|
|
1270
|
+
* - Use `pagingGroup` and `pagingInitiator` to display "Paging: Sales Floor by 1001" in the UI.
|
|
1271
|
+
* - Use `callType` to show "WhatsApp Call" badge in the call screen.
|
|
1272
|
+
*/
|
|
890
1273
|
export interface WebRTCCallInfo {
|
|
1274
|
+
/**
|
|
1275
|
+
* sip.js session ID — a locally generated string (e.g. `"abc123"`).
|
|
1276
|
+
*
|
|
1277
|
+
* **This is NOT the FreeSWITCH UUID.** Use this for client-side operations only:
|
|
1278
|
+
* `answer()`, `reject()`, `hold()`, `mute()`, `sendDtmf()`, `hangup()`.
|
|
1279
|
+
*
|
|
1280
|
+
* Available immediately when the call is created (during `ringing` state).
|
|
1281
|
+
*
|
|
1282
|
+
* **DO NOT** pass this to `addCallParticipant()`, `mergeCalls()`, or any other
|
|
1283
|
+
* server-side method — those require `fsChannelUuid`.
|
|
1284
|
+
*/
|
|
891
1285
|
id: string;
|
|
1286
|
+
/** Call direction relative to this phone: `'inbound'` (someone called us) or `'outbound'` (we called someone). */
|
|
892
1287
|
direction: 'inbound' | 'outbound';
|
|
1288
|
+
/** Remote party's phone number. For inbound calls this is the caller's number. For outbound calls this is the dialed number. Example: `"+17865551234"`. Initially `"unknown"` during very early ringing. */
|
|
893
1289
|
remoteIdentity: string;
|
|
1290
|
+
/** Remote party's display name from SIP header. Example: `"John Doe"`. May be empty string if not provided. */
|
|
894
1291
|
remoteDisplayName: string;
|
|
1292
|
+
/** Current state in the call lifecycle. See the type-level docs for the full state machine. */
|
|
895
1293
|
state: WebRTCCallState;
|
|
1294
|
+
/** `Date` object when the call started (outbound INVITE sent or inbound INVITE received). `null` when `state === 'idle'`. */
|
|
896
1295
|
startTime: Date | null;
|
|
1296
|
+
/** `Date` object when the call was answered (200 OK received/sent). `null` until `state === 'established'`. */
|
|
897
1297
|
answerTime: Date | null;
|
|
1298
|
+
/** Whether the local user has placed this call on hold. `true` only during `held` state. */
|
|
898
1299
|
held: boolean;
|
|
1300
|
+
/** Whether the local microphone is muted. Toggle via `phone.mute()`. The remote party hears silence but the call stays active. */
|
|
899
1301
|
muted: boolean;
|
|
1302
|
+
/** String of DTMF digits sent during this call. Example: `""` (none sent), `"123"` (digits 1, 2, 3 sent). Accumulates over the call life. */
|
|
900
1303
|
dtmfSent: string;
|
|
901
1304
|
/**
|
|
902
1305
|
* Channel type of the inbound call.
|
|
@@ -918,6 +1321,8 @@ export interface WebRTCCallInfo {
|
|
|
918
1321
|
/**
|
|
919
1322
|
* Whether this is a paging/intercom broadcast call.
|
|
920
1323
|
* When `true`, the phone should auto-answer and play through the speaker (bocina).
|
|
1324
|
+
* The SDK handles auto-answer automatically via the `autoAnswer` config and the
|
|
1325
|
+
* `pagingCall` event on `WebRTCEventMap`.
|
|
921
1326
|
*/
|
|
922
1327
|
isPaging?: boolean;
|
|
923
1328
|
/**
|
|
@@ -940,6 +1345,10 @@ export interface WebRTCCallInfo {
|
|
|
940
1345
|
*
|
|
941
1346
|
* **Populated in `state: 'established'`** — `null` during ringing/connecting.
|
|
942
1347
|
*
|
|
1348
|
+
* **Critical:** Do NOT confuse this with `id` (the sip.js session ID).
|
|
1349
|
+
* `fsChannelUuid` is the FreeSWITCH channel UUID needed for server-side operations.
|
|
1350
|
+
* `id` is the local sip.js session ID for client-side operations.
|
|
1351
|
+
*
|
|
943
1352
|
* @example "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
|
|
944
1353
|
*/
|
|
945
1354
|
fsChannelUuid: string | null;
|
|
@@ -968,40 +1377,104 @@ export interface WebRTCEventMap {
|
|
|
968
1377
|
}) => void;
|
|
969
1378
|
error: (error: Error) => void;
|
|
970
1379
|
}
|
|
1380
|
+
/**
|
|
1381
|
+
* A participant in a conference room.
|
|
1382
|
+
*
|
|
1383
|
+
* Each member has a FreeSWITCH channel UUID (`uuid`) and a conference-specific
|
|
1384
|
+
* member ID (`id`). Use `id` for conference operations like mute/kick/deaf.
|
|
1385
|
+
*/
|
|
971
1386
|
export interface ConferenceMember {
|
|
1387
|
+
/** Conference member ID (integer). Used for mute/kick/deaf operations within the conference. Example: `"1"`. */
|
|
972
1388
|
id: string;
|
|
1389
|
+
/** FreeSWITCH channel UUID for this member's call leg. Example: `"a1b2c3d4-e5f6-7890-abcd-ef1234567890"`. */
|
|
973
1390
|
uuid: string;
|
|
1391
|
+
/** Caller ID name for this participant. Example: `"John Smith"`. */
|
|
974
1392
|
callerIdName: string;
|
|
1393
|
+
/** Caller ID number for this participant. Example: `"+17865551234"` or `"1001"`. */
|
|
975
1394
|
callerIdNumber: string;
|
|
1395
|
+
/** Whether this member is muted (cannot speak into conference). */
|
|
976
1396
|
muted: boolean;
|
|
1397
|
+
/** Whether this member is deafened (cannot hear conference). */
|
|
977
1398
|
deaf: boolean;
|
|
1399
|
+
/** ISO 8601 timestamp when this member joined the conference. Example: `"2025-06-04T14:30:00Z"`. */
|
|
978
1400
|
joinTime: string;
|
|
979
1401
|
}
|
|
1402
|
+
/**
|
|
1403
|
+
* An active conference room on the FreeSWITCH server.
|
|
1404
|
+
*
|
|
1405
|
+
* Returned by `listConferences()`. Shows the conference name, number of members,
|
|
1406
|
+
* lock status, runtime, and full member list with mute/deaf state.
|
|
1407
|
+
*
|
|
1408
|
+
* @example
|
|
1409
|
+
* ```ts
|
|
1410
|
+
* const { conferences } = await voip.listConferences();
|
|
1411
|
+
* conferences.forEach(conf => {
|
|
1412
|
+
* console.log(`${conf.name}: ${conf.memberCount} members, ${conf.locked ? 'locked' : 'open'}`);
|
|
1413
|
+
* conf.members.forEach(m => {
|
|
1414
|
+
* console.log(` ${m.callerIdNumber} muted=${m.muted} deaf=${m.deaf}`);
|
|
1415
|
+
* });
|
|
1416
|
+
* });
|
|
1417
|
+
* ```
|
|
1418
|
+
*/
|
|
980
1419
|
export interface Conference {
|
|
1420
|
+
/** Conference room name (e.g. `"conf_<uuid>"` or a custom name). */
|
|
981
1421
|
name: string;
|
|
1422
|
+
/** Number of active participants currently in the room. */
|
|
982
1423
|
memberCount: number;
|
|
1424
|
+
/** Whether the conference is locked (no new members can join). */
|
|
983
1425
|
locked: boolean;
|
|
1426
|
+
/** Human-readable runtime string (e.g. `"0:05:23"` for 5 minutes, 23 seconds). */
|
|
984
1427
|
runTime: string;
|
|
1428
|
+
/** List of all active participants with their mute/deaf state. */
|
|
985
1429
|
members: ConferenceMember[];
|
|
986
1430
|
}
|
|
1431
|
+
/**
|
|
1432
|
+
* A member (extension) within a ring group.
|
|
1433
|
+
*
|
|
1434
|
+
* Each member has a priority (for sequential strategy) and a delay before ringing.
|
|
1435
|
+
*/
|
|
987
1436
|
export interface RingGroupMember {
|
|
1437
|
+
/** Database UUID of this member entry. */
|
|
988
1438
|
id: string;
|
|
1439
|
+
/** Extension number (e.g. `"1001"`). */
|
|
989
1440
|
extension: string;
|
|
1441
|
+
/** Ring priority for sequential strategy. Lower numbers ring first. `1`-based. */
|
|
990
1442
|
priority: number;
|
|
1443
|
+
/** Seconds to wait before ringing this member (applies to sequential strategy). Default: `0`. */
|
|
991
1444
|
delay_seconds: number;
|
|
992
1445
|
}
|
|
1446
|
+
/**
|
|
1447
|
+
* A ring group — rings multiple extensions when a call arrives.
|
|
1448
|
+
*
|
|
1449
|
+
* Strategies:
|
|
1450
|
+
* - `simultaneous`: Ring all members at once. First to answer gets the call.
|
|
1451
|
+
* - `sequential`: Ring members one at a time in priority order. Move to next after `ring_timeout`.
|
|
1452
|
+
* - `random`: Ring a random member.
|
|
1453
|
+
*
|
|
1454
|
+
* If no one answers within `ring_timeout`, execute `no_answer_action` on `no_answer_target`.
|
|
1455
|
+
*/
|
|
993
1456
|
export interface RingGroup {
|
|
1457
|
+
/** Database UUID of the ring group. */
|
|
994
1458
|
id: string;
|
|
1459
|
+
/** Tenant UUID. Present for tenant-scoped queries. */
|
|
995
1460
|
tenant_id?: string;
|
|
1461
|
+
/** Human-readable ring group name. Example: `"Sales Team"`. */
|
|
996
1462
|
name: string;
|
|
1463
|
+
/** Ring strategy: `'simultaneous'`, `'sequential'`, or `'random'`. */
|
|
997
1464
|
strategy: string;
|
|
1465
|
+
/** Total ring time in seconds before executing `no_answer_action`. Example: `30`. */
|
|
998
1466
|
ring_timeout: number;
|
|
1467
|
+
/** Action when no one answers: `'voicemail'`, `'ivr'`, `'extension'`, `'hangup'`, `'ai_agent'`. */
|
|
999
1468
|
no_answer_action: string;
|
|
1469
|
+
/** Target for `no_answer_action` (extension number, IVR UUID, etc.). `null` when action is `'hangup'`. */
|
|
1000
1470
|
no_answer_target: string | null;
|
|
1471
|
+
/** Status: `'active'` or `'disabled'`. */
|
|
1001
1472
|
status: string;
|
|
1473
|
+
/** ISO 8601 timestamp of creation. */
|
|
1002
1474
|
created_at: string;
|
|
1475
|
+
/** Ordered list of ring group members. */
|
|
1003
1476
|
members: RingGroupMember[];
|
|
1004
|
-
/** Present when queried as global superadmin */
|
|
1477
|
+
/** Present when queried as global superadmin. */
|
|
1005
1478
|
tenant?: TenantInfo;
|
|
1006
1479
|
}
|
|
1007
1480
|
export interface CreateRingGroupParams {
|
|
@@ -1016,33 +1489,75 @@ export interface CreateRingGroupParams {
|
|
|
1016
1489
|
delaySeconds?: number;
|
|
1017
1490
|
}>;
|
|
1018
1491
|
}
|
|
1492
|
+
/**
|
|
1493
|
+
* An agent (extension) assigned to a call queue.
|
|
1494
|
+
*
|
|
1495
|
+
* Agents receive calls distributed by the queue strategy.
|
|
1496
|
+
* Queue managers (ext 6000) can add/remove themselves via `*45`/`*46`.
|
|
1497
|
+
*/
|
|
1019
1498
|
export interface QueueAgent {
|
|
1499
|
+
/** Database UUID of this agent assignment. */
|
|
1020
1500
|
id: string;
|
|
1501
|
+
/** Extension number assigned to the queue. Example: `"1001"`. */
|
|
1021
1502
|
extension: string;
|
|
1503
|
+
/** Agent tier/priority. Lower numbers = higher priority (gets calls first). Default: `5`. */
|
|
1022
1504
|
priority: number;
|
|
1505
|
+
/** Agent penalty (post-call wrap-up delay). Higher = longer delay before next call. Default: `0`. */
|
|
1023
1506
|
penalty: number;
|
|
1507
|
+
/** Agent status: `'available'`, `'on_call'`, `'paused'`, `'logged_out'`. */
|
|
1024
1508
|
status: string;
|
|
1025
1509
|
}
|
|
1510
|
+
/**
|
|
1511
|
+
* A call queue — distributes incoming calls among agents based on a strategy.
|
|
1512
|
+
*
|
|
1513
|
+
* Callers hear music-on-hold while waiting for an available agent.
|
|
1514
|
+
* Queue managers can log in/log out, pause, and monitor via FreeSWITCH codes.
|
|
1515
|
+
*
|
|
1516
|
+
* Strategies:
|
|
1517
|
+
* - `round-robin`: Cycle through agents in fixed order.
|
|
1518
|
+
* - `longest-idle`: Agent idle the longest gets the next call.
|
|
1519
|
+
* - `ring-all`: Ring all available agents simultaneously.
|
|
1520
|
+
* - `least-calls`: Agent with fewest calls today gets the next.
|
|
1521
|
+
* - `random`: Pick a random available agent.
|
|
1522
|
+
*/
|
|
1026
1523
|
export interface CallQueue {
|
|
1524
|
+
/** Database UUID of the queue. */
|
|
1027
1525
|
id: string;
|
|
1526
|
+
/** Tenant UUID. */
|
|
1028
1527
|
tenant_id?: string;
|
|
1528
|
+
/** Queue name displayed in dashboards and reports. Example: `"Support Queue"`. */
|
|
1029
1529
|
name: string;
|
|
1530
|
+
/** Distribution strategy: `'round-robin'`, `'longest-idle'`, `'ring-all'`, `'least-calls'`, `'random'`. */
|
|
1030
1531
|
strategy: string;
|
|
1532
|
+
/** Music-on-hold sound file to play while caller waits. Example: `"default"` or custom audio file name. */
|
|
1031
1533
|
moh_sound: string;
|
|
1534
|
+
/** Announcement audio played to callers on entry (position in queue, estimated wait). `null` if disabled. */
|
|
1032
1535
|
announce_sound: string | null;
|
|
1536
|
+
/** How often (seconds) to replay the announcement to waiting callers. Example: `60`. */
|
|
1033
1537
|
announce_frequency: number;
|
|
1538
|
+
/** Maximum wait time in seconds before caller times out. Example: `300` (5 min). */
|
|
1034
1539
|
max_wait_time: number;
|
|
1540
|
+
/** Maximum number of simultaneous callers allowed in the queue. Example: `20`. */
|
|
1035
1541
|
max_callers: number;
|
|
1542
|
+
/** Seconds each agent's phone rings before moving to next agent. Example: `30`. */
|
|
1036
1543
|
ring_timeout: number;
|
|
1544
|
+
/** Seconds after a call ends before the agent gets the next call (post-call work). Example: `10`. */
|
|
1037
1545
|
wrap_up_time: number;
|
|
1546
|
+
/** Action when no agents are logged in: `'voicemail'`, `'ivr'`, `'extension'`, `'hangup'`, `'ai_agent'`. */
|
|
1038
1547
|
no_agent_action: string;
|
|
1548
|
+
/** Target for `no_agent_action`. `null` when action is `'hangup'`. */
|
|
1039
1549
|
no_agent_target: string | null;
|
|
1550
|
+
/** Action when caller times out (exceeds `max_wait_time`): `'voicemail'`, `'ivr'`, `'extension'`, `'hangup'`, `'ai_agent'`. */
|
|
1040
1551
|
timeout_action: string;
|
|
1552
|
+
/** Target for `timeout_action`. `null` when action is `'hangup'`. */
|
|
1041
1553
|
timeout_target: string | null;
|
|
1554
|
+
/** Queue status: `'active'` or `'disabled'`. */
|
|
1042
1555
|
status: string;
|
|
1556
|
+
/** ISO 8601 timestamp of creation. */
|
|
1043
1557
|
created_at: string;
|
|
1558
|
+
/** List of agents assigned to this queue. */
|
|
1044
1559
|
agents: QueueAgent[];
|
|
1045
|
-
/** Present when queried as global superadmin */
|
|
1560
|
+
/** Present when queried as global superadmin. */
|
|
1046
1561
|
tenant?: TenantInfo;
|
|
1047
1562
|
}
|
|
1048
1563
|
export interface CreateQueueParams {
|
|
@@ -1065,18 +1580,43 @@ export interface CreateQueueParams {
|
|
|
1065
1580
|
penalty?: number;
|
|
1066
1581
|
}>;
|
|
1067
1582
|
}
|
|
1583
|
+
/**
|
|
1584
|
+
* A webhook subscription that sends call events to an external URL.
|
|
1585
|
+
*
|
|
1586
|
+
* Webhooks fire on call lifecycle events (`call.started`, `call.ended`, etc.),
|
|
1587
|
+
* voicemail events, and extension registration changes.
|
|
1588
|
+
* Each delivery is retried up to `maxRetries` times with exponential backoff.
|
|
1589
|
+
*
|
|
1590
|
+
* @example
|
|
1591
|
+
* ```ts
|
|
1592
|
+
* const { webhooks } = await voip.listWebhooks();
|
|
1593
|
+
* webhooks.forEach(w => {
|
|
1594
|
+
* console.log(`${w.name} → ${w.url} [${w.events.join(',')}] ${w.active ? 'ACTIVE' : 'PAUSED'}`);
|
|
1595
|
+
* });
|
|
1596
|
+
* ```
|
|
1597
|
+
*/
|
|
1068
1598
|
export interface Webhook {
|
|
1599
|
+
/** Database UUID of the webhook subscription. */
|
|
1069
1600
|
id: string;
|
|
1601
|
+
/** Human-readable name for this webhook. Example: `"CRM Call Logger"`. */
|
|
1070
1602
|
name: string;
|
|
1603
|
+
/** Destination URL where HTTP POST requests are sent. Must be HTTPS. Example: `"https://my-crm.example.com/api/webhooks/voip"`. */
|
|
1071
1604
|
url: string;
|
|
1605
|
+
/** Array of event types this webhook listens to. Example: `["call.started", "call.ended", "call.answered"]`. */
|
|
1072
1606
|
events: string[];
|
|
1607
|
+
/** Whether this webhook is actively sending events. `false` means paused. */
|
|
1073
1608
|
active: boolean;
|
|
1609
|
+
/** Whether a signing secret is configured. Always `false` in GET responses — the secret is never returned. */
|
|
1074
1610
|
hasSecret: boolean;
|
|
1611
|
+
/** Custom HTTP headers included in each delivery. `null` if none. Example: `{"X-Custom-Auth": "token123"}`. */
|
|
1075
1612
|
headers: Record<string, string> | null;
|
|
1613
|
+
/** Maximum retry attempts for failed deliveries. Default: `3`. After exhausting retries, the delivery is marked as failed. */
|
|
1076
1614
|
maxRetries?: number;
|
|
1615
|
+
/** Base delay in seconds between retries (exponential backoff). Default: `10`. Delays: 10s, 20s, 40s, ... */
|
|
1077
1616
|
retryDelaySeconds?: number;
|
|
1617
|
+
/** ISO 8601 timestamp of webhook creation. */
|
|
1078
1618
|
createdAt: string;
|
|
1079
|
-
/** Present when queried as global superadmin */
|
|
1619
|
+
/** Present when queried as global superadmin. */
|
|
1080
1620
|
tenant?: TenantInfo;
|
|
1081
1621
|
}
|
|
1082
1622
|
export interface WebhookDelivery {
|
|
@@ -1090,13 +1630,36 @@ export interface WebhookDelivery {
|
|
|
1090
1630
|
error: string | null;
|
|
1091
1631
|
deliveredAt: string;
|
|
1092
1632
|
}
|
|
1633
|
+
/**
|
|
1634
|
+
* Parameters for creating a new webhook subscription.
|
|
1635
|
+
*
|
|
1636
|
+
* At minimum, provide `name`, `url`, and `events`. The server validates the URL
|
|
1637
|
+
* is HTTPS (non-negotiable for security) and tests connectivity before saving.
|
|
1638
|
+
*
|
|
1639
|
+
* @example
|
|
1640
|
+
* ```ts
|
|
1641
|
+
* await voip.createWebhook({
|
|
1642
|
+
* name: 'CRM Call Logger',
|
|
1643
|
+
* url: 'https://my-crm.example.com/api/webhooks/voip',
|
|
1644
|
+
* events: ['call.started', 'call.answered', 'call.ended', 'voicemail.new'],
|
|
1645
|
+
* secret: 'whsec_my-signing-secret',
|
|
1646
|
+
* });
|
|
1647
|
+
* ```
|
|
1648
|
+
*/
|
|
1093
1649
|
export interface CreateWebhookParams {
|
|
1650
|
+
/** Human-readable name for this webhook. Example: `"CRM Call Logger"`. */
|
|
1094
1651
|
name: string;
|
|
1652
|
+
/** Destination HTTPS URL. Must be reachable from the server. Example: `"https://my-crm.example.com/webhook"`. */
|
|
1095
1653
|
url: string;
|
|
1654
|
+
/** Array of event types to subscribe to. Full list: see `WebhookEventType`. Example: `["call.started", "call.ended"]`. */
|
|
1096
1655
|
events: string[];
|
|
1656
|
+
/** Signing secret for HMAC payload verification. The server includes `X-Webhook-Signature` header. Optional but recommended. */
|
|
1097
1657
|
secret?: string;
|
|
1658
|
+
/** Custom HTTP headers to include in each delivery. Example: `{"X-API-Key": "mykey"}`. */
|
|
1098
1659
|
headers?: Record<string, string>;
|
|
1660
|
+
/** Maximum retry attempts for failed deliveries. Default: `3`. */
|
|
1099
1661
|
maxRetries?: number;
|
|
1662
|
+
/** Base delay in seconds between retries (exponential: delay * 2^attempt). Default: `10`. */
|
|
1100
1663
|
retryDelaySeconds?: number;
|
|
1101
1664
|
}
|
|
1102
1665
|
/** Supported webhook event names */
|
|
@@ -1237,23 +1800,55 @@ export interface VoicemailCallInfo {
|
|
|
1237
1800
|
audio_url: string | null;
|
|
1238
1801
|
started_at: string | null;
|
|
1239
1802
|
}
|
|
1803
|
+
/**
|
|
1804
|
+
* A voicemail message left by a caller.
|
|
1805
|
+
*
|
|
1806
|
+
* Returned by `listVoicemails()`. Each message includes the caller's info,
|
|
1807
|
+
* duration, read/urgent flags, an audio URL, and optionally a linked call record.
|
|
1808
|
+
*
|
|
1809
|
+
* ## Playback
|
|
1810
|
+
*
|
|
1811
|
+
* Use `audio_url` with `voip.buildUrl()` to append the API key for browser playback:
|
|
1812
|
+
* ```html
|
|
1813
|
+
* <audio src={voip.buildUrl(message.audio_url)} controls />
|
|
1814
|
+
* ```
|
|
1815
|
+
*
|
|
1816
|
+
* @example
|
|
1817
|
+
* ```ts
|
|
1818
|
+
* const { messages, unread } = await voip.listVoicemails({ unreadOnly: true });
|
|
1819
|
+
* messages.forEach(msg => {
|
|
1820
|
+
* console.log(`From ${msg.caller_id}: ${msg.duration_seconds}s ${msg.is_urgent ? 'URGENT' : ''}`);
|
|
1821
|
+
* });
|
|
1822
|
+
* ```
|
|
1823
|
+
*/
|
|
1240
1824
|
export interface VoicemailMessage {
|
|
1825
|
+
/** Database UUID of the voicemail message. */
|
|
1241
1826
|
id: string;
|
|
1827
|
+
/** Tenant UUID this message belongs to. */
|
|
1242
1828
|
tenant_id: string;
|
|
1829
|
+
/** Extension number that received the voicemail. Example: `"1001"`. */
|
|
1243
1830
|
extension: string;
|
|
1831
|
+
/** Caller's phone number. Example: `"+17865551234"`. */
|
|
1244
1832
|
caller_id: string;
|
|
1833
|
+
/** Caller's display name. `null` if not provided by carrier. Example: `"John Doe"`. */
|
|
1245
1834
|
caller_name: string | null;
|
|
1835
|
+
/** Duration of the voicemail recording in seconds. Example: `42`. */
|
|
1246
1836
|
duration_seconds: number;
|
|
1837
|
+
/** Whether the voicemail has been listened to. */
|
|
1247
1838
|
is_read: boolean;
|
|
1839
|
+
/** Whether this voicemail was marked as urgent by the caller (pressed * during recording). */
|
|
1248
1840
|
is_urgent: boolean;
|
|
1841
|
+
/** ISO 8601 timestamp when the voicemail was left. Example: `"2025-06-04T15:30:00.000Z"`. */
|
|
1249
1842
|
created_at: string;
|
|
1843
|
+
/** ISO 8601 timestamp when the voicemail was read. `null` if unread. */
|
|
1250
1844
|
read_at: string | null;
|
|
1251
|
-
/** Direct URL to stream this voicemail's audio. Append `?apiKey=...` for browser playback. */
|
|
1845
|
+
/** Direct URL to stream this voicemail's audio. Append `?apiKey=...` for browser playback. Example: `"/api/voicemail/abc123/audio"`. */
|
|
1252
1846
|
audio_url: string;
|
|
1253
|
-
/** Linked call record with status, recording, etc. (null if no matching call found) */
|
|
1847
|
+
/** Linked call record with status, recording, etc. (null if no matching call found). Available since SDK 1.55.4. */
|
|
1254
1848
|
call: VoicemailCallInfo | null;
|
|
1255
|
-
/** Present when queried as global superadmin */
|
|
1849
|
+
/** Present when queried as global superadmin. Tenant company name. */
|
|
1256
1850
|
company_name?: string;
|
|
1851
|
+
/** Present when queried as global superadmin. Tenant subdomain. */
|
|
1257
1852
|
subdomain?: string;
|
|
1258
1853
|
}
|
|
1259
1854
|
export interface VoicemailListParams {
|
|
@@ -1333,11 +1928,28 @@ export interface PresenceDetail {
|
|
|
1333
1928
|
extension?: string;
|
|
1334
1929
|
}
|
|
1335
1930
|
export type PresenceDetailMap = Record<string, PresenceDetail>;
|
|
1931
|
+
/**
|
|
1932
|
+
* Dashboard summary counters for the current tenant.
|
|
1933
|
+
*
|
|
1934
|
+
* Returned by `getDashboardStats()`. Use for summary cards/badges at the top
|
|
1935
|
+
* of a CRM dashboard showing: total extensions, active DIDs, calls today, and calls this month.
|
|
1936
|
+
*
|
|
1937
|
+
* @example
|
|
1938
|
+
* ```ts
|
|
1939
|
+
* const { dashboard } = await voip.getDashboardStats();
|
|
1940
|
+
* console.log(`Extensions: ${dashboard.extensions}, DIDs: ${dashboard.dids}`);
|
|
1941
|
+
* console.log(`Calls today: ${dashboard.callsToday}, This month: ${dashboard.callsThisMonth}`);
|
|
1942
|
+
* ```
|
|
1943
|
+
*/
|
|
1336
1944
|
export interface DashboardStats {
|
|
1337
1945
|
dashboard: {
|
|
1946
|
+
/** Total number of extensions configured in this tenant. */
|
|
1338
1947
|
extensions: number;
|
|
1948
|
+
/** Total number of active DID phone numbers. */
|
|
1339
1949
|
dids: number;
|
|
1950
|
+
/** Number of calls made/received today (midnight to now). */
|
|
1340
1951
|
callsToday: number;
|
|
1952
|
+
/** Number of calls made/received this calendar month. */
|
|
1341
1953
|
callsThisMonth: number;
|
|
1342
1954
|
};
|
|
1343
1955
|
}
|
|
@@ -1359,19 +1971,46 @@ export interface TopExtension {
|
|
|
1359
1971
|
export interface TopExtensionsResponse {
|
|
1360
1972
|
topExtensions: TopExtension[];
|
|
1361
1973
|
}
|
|
1974
|
+
/**
|
|
1975
|
+
* A blocked phone number in the tenant's blocklist.
|
|
1976
|
+
*
|
|
1977
|
+
* Calls to/from blocked numbers are automatically rejected by FreeSWITCH.
|
|
1978
|
+
* Works for both inbound and outbound directions.
|
|
1979
|
+
*/
|
|
1362
1980
|
export interface BlockedNumber {
|
|
1981
|
+
/** Database UUID of the blocklist entry. */
|
|
1363
1982
|
id: string;
|
|
1983
|
+
/** Tenant UUID. */
|
|
1364
1984
|
tenant_id: string;
|
|
1985
|
+
/** Blocked phone number in E.164 format. Example: `"+17865559999"`. */
|
|
1365
1986
|
number: string;
|
|
1987
|
+
/** Reason for blocking. `null` if no reason was provided. Example: `"Spam caller"`. */
|
|
1366
1988
|
reason: string | null;
|
|
1989
|
+
/** Direction this block applies to: `'inbound'`, `'outbound'`, `'both'`. `null` = `'both'`. */
|
|
1367
1990
|
direction: string | null;
|
|
1991
|
+
/** ISO 8601 timestamp when this number was blocked. `null` for legacy entries. */
|
|
1368
1992
|
created_at: string | null;
|
|
1369
|
-
/** Present when queried as global superadmin */
|
|
1993
|
+
/** Present when queried as global superadmin. */
|
|
1370
1994
|
tenants?: TenantInfo;
|
|
1371
1995
|
}
|
|
1996
|
+
/**
|
|
1997
|
+
* Parameters for adding a number to the blocklist.
|
|
1998
|
+
*
|
|
1999
|
+
* @example
|
|
2000
|
+
* ```ts
|
|
2001
|
+
* await voip.blockNumber({
|
|
2002
|
+
* number: '+17865559999',
|
|
2003
|
+
* reason: 'Repeated spam calls',
|
|
2004
|
+
* direction: 'inbound',
|
|
2005
|
+
* });
|
|
2006
|
+
* ```
|
|
2007
|
+
*/
|
|
1372
2008
|
export interface CreateBlockedNumberParams {
|
|
2009
|
+
/** E.164 phone number to block. Example: `"+17865559999"`. */
|
|
1373
2010
|
number: string;
|
|
2011
|
+
/** Optional reason (shown in dashboard). Example: `"Spam caller"`. */
|
|
1374
2012
|
reason?: string;
|
|
2013
|
+
/** Which direction to block: `'inbound'` (calls FROM this number), `'outbound'` (calls TO this number), `'both'`. Default: `'both'`. */
|
|
1375
2014
|
direction?: 'inbound' | 'outbound' | 'both';
|
|
1376
2015
|
}
|
|
1377
2016
|
export interface BlocklistCheckResponse {
|
|
@@ -1388,27 +2027,81 @@ export interface Holiday {
|
|
|
1388
2027
|
date: string;
|
|
1389
2028
|
name?: string;
|
|
1390
2029
|
}
|
|
2030
|
+
/**
|
|
2031
|
+
* A business hours schedule for a tenant.
|
|
2032
|
+
*
|
|
2033
|
+
* Defines which days/times the business is open. When a call arrives outside
|
|
2034
|
+
* business hours, the `after_hours_action` is executed (e.g. send to voicemail).
|
|
2035
|
+
*
|
|
2036
|
+
* Includes weekly `schedules` (day of week + start/end time) and `holidays`
|
|
2037
|
+
* (specific dates when the business is closed regardless of weekly schedule).
|
|
2038
|
+
*
|
|
2039
|
+
* @example
|
|
2040
|
+
* ```ts
|
|
2041
|
+
* const { schedules } = await voip.listSchedules();
|
|
2042
|
+
* schedules.forEach(s => {
|
|
2043
|
+
* const status = await voip.checkScheduleStatus(s.id);
|
|
2044
|
+
* console.log(`${s.name}: ${status.isOpen ? 'OPEN' : 'CLOSED'}`);
|
|
2045
|
+
* });
|
|
2046
|
+
* ```
|
|
2047
|
+
*/
|
|
1391
2048
|
export interface BusinessSchedule {
|
|
2049
|
+
/** Database UUID of the schedule. */
|
|
1392
2050
|
id: string;
|
|
2051
|
+
/** Tenant UUID. */
|
|
1393
2052
|
tenant_id: string;
|
|
2053
|
+
/** Human-readable schedule name. Example: `"Standard Business Hours"`. */
|
|
1394
2054
|
name: string;
|
|
1395
|
-
/** Present when queried as global superadmin */
|
|
2055
|
+
/** Present when queried as global superadmin. */
|
|
1396
2056
|
tenants?: TenantInfo;
|
|
2057
|
+
/** IANA timezone for this schedule. `null` = tenant default. Example: `"America/New_York"`. */
|
|
1397
2058
|
timezone: string | null;
|
|
2059
|
+
/** Weekly day schedule array. Each entry defines open hours for one day. `null` if not configured. */
|
|
1398
2060
|
schedules: DaySchedule[] | null;
|
|
2061
|
+
/** Holiday list — specific dates the business is closed. `null` if no holidays configured. */
|
|
1399
2062
|
holidays: Holiday[] | null;
|
|
2063
|
+
/** Action when a call arrives outside business hours: `'voicemail'`, `'ivr'`, `'extension'`, `'hangup'`, `'external'`, `'ai_agent'`. `null` if not configured. */
|
|
1400
2064
|
after_hours_action: string | null;
|
|
2065
|
+
/** Target for `after_hours_action`. `null` when action is `'hangup'` or not configured. */
|
|
1401
2066
|
after_hours_target: string | null;
|
|
2067
|
+
/** Schedule status: `'active'` or `'disabled'`. `null` for legacy entries. */
|
|
1402
2068
|
status: string | null;
|
|
2069
|
+
/** ISO 8601 timestamp of creation. `null` for legacy entries. */
|
|
1403
2070
|
created_at: string | null;
|
|
2071
|
+
/** ISO 8601 timestamp of last update. `null` for legacy entries. */
|
|
1404
2072
|
updated_at: string | null;
|
|
1405
2073
|
}
|
|
2074
|
+
/**
|
|
2075
|
+
* Parameters for creating a business hours schedule.
|
|
2076
|
+
*
|
|
2077
|
+
* @example
|
|
2078
|
+
* ```ts
|
|
2079
|
+
* await voip.createSchedule({
|
|
2080
|
+
* name: 'Standard Business Hours',
|
|
2081
|
+
* timezone: 'America/New_York',
|
|
2082
|
+
* schedules: [
|
|
2083
|
+
* { day: 'monday', enabled: true, startTime: '09:00', endTime: '17:00' },
|
|
2084
|
+
* { day: 'tuesday', enabled: true, startTime: '09:00', endTime: '17:00' },
|
|
2085
|
+
* { day: 'saturday', enabled: false },
|
|
2086
|
+
* { day: 'sunday', enabled: false },
|
|
2087
|
+
* ],
|
|
2088
|
+
* afterHoursAction: 'voicemail',
|
|
2089
|
+
* afterHoursTarget: '1001',
|
|
2090
|
+
* });
|
|
2091
|
+
* ```
|
|
2092
|
+
*/
|
|
1406
2093
|
export interface CreateScheduleParams {
|
|
2094
|
+
/** Human-readable name. Example: `"Standard Business Hours"`. */
|
|
1407
2095
|
name: string;
|
|
2096
|
+
/** IANA timezone. Default: tenant's configured timezone or `"America/New_York"`. */
|
|
1408
2097
|
timezone?: string;
|
|
2098
|
+
/** Weekly day schedule array. Each entry specifies open hours for a single day. Example: `[{ day: 'monday', enabled: true, startTime: '09:00', endTime: '17:00' }]`. */
|
|
1409
2099
|
schedules?: DaySchedule[];
|
|
2100
|
+
/** Specific dates the business is closed. Example: `[{ date: '2025-12-25', name: 'Christmas' }]`. */
|
|
1410
2101
|
holidays?: Holiday[];
|
|
2102
|
+
/** Action when a call arrives outside business hours. Defaults to no special handling. */
|
|
1411
2103
|
afterHoursAction?: 'voicemail' | 'ivr' | 'extension' | 'hangup' | 'external' | 'ai_agent';
|
|
2104
|
+
/** Target for `afterHoursAction` (extension number, IVR UUID, phone number, etc.). */
|
|
1412
2105
|
afterHoursTarget?: string;
|
|
1413
2106
|
}
|
|
1414
2107
|
export interface ScheduleStatusResponse {
|
|
@@ -1417,15 +2110,104 @@ export interface ScheduleStatusResponse {
|
|
|
1417
2110
|
timezone: string;
|
|
1418
2111
|
currentTime: string;
|
|
1419
2112
|
}
|
|
2113
|
+
/**
|
|
2114
|
+
* Live gateway status reported by FreeSWITCH for a SIP trunk.
|
|
2115
|
+
*
|
|
2116
|
+
* Included in `SipTrunk` responses when the gateway is registered and available.
|
|
2117
|
+
* Shows the current call count, failures, and uptime.
|
|
2118
|
+
*/
|
|
1420
2119
|
export interface GatewayStatus {
|
|
2120
|
+
/** Gateway state: `'UP'` or `'DOWN'`. */
|
|
1421
2121
|
state: string;
|
|
2122
|
+
/** Registration status: `'REGED'` (registered), `'UNREG'` (unregistered), `'TRYING'`. */
|
|
1422
2123
|
status: string;
|
|
2124
|
+
/** Number of active inbound calls on this trunk. */
|
|
1423
2125
|
callsIn: number;
|
|
2126
|
+
/** Number of active outbound calls on this trunk. */
|
|
1424
2127
|
callsOut: number;
|
|
2128
|
+
/** Cumulative failed inbound calls. */
|
|
1425
2129
|
failedIn?: number;
|
|
2130
|
+
/** Cumulative failed outbound calls. */
|
|
1426
2131
|
failedOut?: number;
|
|
2132
|
+
/** Human-readable uptime string (e.g. `"3d 12h 45m"`). */
|
|
1427
2133
|
uptime?: string;
|
|
1428
2134
|
}
|
|
2135
|
+
/**
|
|
2136
|
+
* A SIP trunk gateway connecting the platform to an external telephony provider
|
|
2137
|
+
* (Twilio, Telnyx, Vonage, etc.).
|
|
2138
|
+
*
|
|
2139
|
+
* SIP trunks handle PSTN connectivity — outbound calls go through trunks to reach
|
|
2140
|
+
* phone numbers; inbound calls from phone numbers arrive via trunks.
|
|
2141
|
+
*
|
|
2142
|
+
* Global trunks (`tenant_id = null`) are shared across all tenants.
|
|
2143
|
+
* Tenant-specific trunks are only usable by that tenant.
|
|
2144
|
+
*/
|
|
2145
|
+
export interface SipTrunk {
|
|
2146
|
+
/** Database UUID of the trunk. */
|
|
2147
|
+
id: string;
|
|
2148
|
+
/** NULL for global trunks (shared, not tied to any tenant). */
|
|
2149
|
+
tenant_id: string | null;
|
|
2150
|
+
/** Present when queried as global superadmin. */
|
|
2151
|
+
tenants?: TenantInfo;
|
|
2152
|
+
/** Human-readable trunk name. Example: `"Twilio Primary"`. */
|
|
2153
|
+
name: string;
|
|
2154
|
+
/** Provider name: `'twilio'`, `'telnyx'`, `'vonage'`, etc. `null` for custom/unspecified. */
|
|
2155
|
+
provider: string | null;
|
|
2156
|
+
/** Gateway IP or hostname. Example: `"sip.twilio.com"`. */
|
|
2157
|
+
gateway: string;
|
|
2158
|
+
/** SIP username for registration/auth. `null` for IP-based auth trunks. */
|
|
2159
|
+
username: string | null;
|
|
2160
|
+
/** SIP password (masked in API responses — always `"****"` except on create). `null` for IP-auth. */
|
|
2161
|
+
password: string | null;
|
|
2162
|
+
/** Authentication type: `'ip'`, `'registration'`, `'both'`. `null` for legacy entries. */
|
|
2163
|
+
auth_type: string | null;
|
|
2164
|
+
/** Whether outbound calling is enabled through this trunk. `null` = disabled. */
|
|
2165
|
+
outbound_enabled: boolean | null;
|
|
2166
|
+
/** Whether inbound calling is accepted from this trunk. `null` = disabled. */
|
|
2167
|
+
inbound_enabled: boolean | null;
|
|
2168
|
+
/** Priority for outbound routing. Lower = preferred. Example: `10`. */
|
|
2169
|
+
priority: number | null;
|
|
2170
|
+
/** Maximum simultaneous channels. `null` = unlimited. */
|
|
2171
|
+
max_channels: number | null;
|
|
2172
|
+
/** Trunk status: `'active'` or `'inactive'`. `null` = `'inactive'`. */
|
|
2173
|
+
status: string | null;
|
|
2174
|
+
/** SIP realm for authentication. `null` = auto. */
|
|
2175
|
+
realm: string | null;
|
|
2176
|
+
/** Outbound proxy address. `null` = direct to gateway. */
|
|
2177
|
+
proxy: string | null;
|
|
2178
|
+
/** Whether FreeSWITCH registers with the trunk provider. `null` = false. */
|
|
2179
|
+
register: boolean | null;
|
|
2180
|
+
/** From: username for SIP requests. `null` = use `username`. */
|
|
2181
|
+
from_user: string | null;
|
|
2182
|
+
/** From: domain for SIP requests. `null` = use gateway. */
|
|
2183
|
+
from_domain: string | null;
|
|
2184
|
+
/** SIP transport protocol: `'udp'`, `'tcp'`, `'tls'`. `null` = `'udp'`. */
|
|
2185
|
+
transport: string | null;
|
|
2186
|
+
/** Preferred codec list (comma-separated). `null` = platform default. Example: `"PCMU,PCMA"`. */
|
|
2187
|
+
codec_prefs: string | null;
|
|
2188
|
+
/** Whether to include caller ID in From: header. `null` = true. */
|
|
2189
|
+
caller_id_in_from: boolean | null;
|
|
2190
|
+
/** SIP OPTIONS ping interval in seconds. `null` = no ping. */
|
|
2191
|
+
ping: number | null;
|
|
2192
|
+
/** Seconds between registration retries. `null` = default. */
|
|
2193
|
+
retry_seconds: number | null;
|
|
2194
|
+
/** Registration expiry in seconds. `null` = default (3600). */
|
|
2195
|
+
expire_seconds: number | null;
|
|
2196
|
+
/** Separate proxy for REGISTER requests. `null` = use `proxy` or `gateway`. */
|
|
2197
|
+
register_proxy: string | null;
|
|
2198
|
+
/** Extra SIP contact header parameters. `null` = none. */
|
|
2199
|
+
contact_params: string | null;
|
|
2200
|
+
/** Whether this is a global trunk (usable by all tenants). `null` = false. */
|
|
2201
|
+
is_global: boolean | null;
|
|
2202
|
+
/** FreeSWITCH gateway profile name. `null` = auto-generated from name. */
|
|
2203
|
+
gateway_name: string | null;
|
|
2204
|
+
/** Live gateway status from FreeSWITCH (when available). Shows state, calls, failures, uptime. */
|
|
2205
|
+
gatewayStatus?: GatewayStatus | null;
|
|
2206
|
+
/** ISO 8601 timestamp of creation. `null` for legacy entries. */
|
|
2207
|
+
created_at: string | null;
|
|
2208
|
+
/** ISO 8601 timestamp of last update. `null` for legacy entries. */
|
|
2209
|
+
updated_at: string | null;
|
|
2210
|
+
}
|
|
1429
2211
|
export interface SipTrunk {
|
|
1430
2212
|
id: string;
|
|
1431
2213
|
/** NULL for global trunks (shared, not tied to any tenant) */
|
|
@@ -1490,21 +2272,48 @@ export interface CreateTrunkParams {
|
|
|
1490
2272
|
contactParams?: string;
|
|
1491
2273
|
isGlobal?: boolean;
|
|
1492
2274
|
}
|
|
2275
|
+
/**
|
|
2276
|
+
* Real-time and today's statistics for a single call queue.
|
|
2277
|
+
*
|
|
2278
|
+
* Returned by `getQueueStats()`. Shows agent availability, today's call metrics,
|
|
2279
|
+
* and service level percentage. Use for queue wallboards and agent dashboards.
|
|
2280
|
+
*
|
|
2281
|
+
* @example
|
|
2282
|
+
* ```ts
|
|
2283
|
+
* const stats = await voip.getQueueStats('queue-uuid');
|
|
2284
|
+
* console.log(`${stats.queueName}: ${stats.today.answered}/${stats.today.totalCalls} answered`);
|
|
2285
|
+
* console.log(`Agents: ${stats.agents.available} available, ${stats.agents.busy} busy`);
|
|
2286
|
+
* ```
|
|
2287
|
+
*/
|
|
1493
2288
|
export interface QueueStats {
|
|
2289
|
+
/** Queue name. Example: `"Support Queue"`. */
|
|
1494
2290
|
queueName: string;
|
|
2291
|
+
/** Distribution strategy. Example: `"longest-idle"`. */
|
|
1495
2292
|
strategy: string;
|
|
2293
|
+
/** Agent availability breakdown. */
|
|
1496
2294
|
agents: {
|
|
2295
|
+
/** Total number of agents assigned to this queue. */
|
|
1497
2296
|
total: number;
|
|
2297
|
+
/** Agents currently available to take calls. */
|
|
1498
2298
|
available: number;
|
|
2299
|
+
/** Agents who are paused (taking a break). */
|
|
1499
2300
|
paused: number;
|
|
2301
|
+
/** Agents currently on a call. */
|
|
1500
2302
|
busy: number;
|
|
2303
|
+
/** Agents who are logged out. */
|
|
1501
2304
|
loggedOut: number;
|
|
1502
2305
|
};
|
|
2306
|
+
/** Today's call statistics (from midnight). */
|
|
1503
2307
|
today: {
|
|
2308
|
+
/** Total calls offered to the queue today. */
|
|
1504
2309
|
totalCalls: number;
|
|
2310
|
+
/** Calls successfully answered by an agent today. */
|
|
1505
2311
|
answered: number;
|
|
2312
|
+
/** Calls abandoned by the caller before reaching an agent. */
|
|
1506
2313
|
abandoned: number;
|
|
2314
|
+
/** Service level: percentage of calls answered within the SLA (default 20 seconds). Range 0-100. */
|
|
1507
2315
|
serviceLevel: number;
|
|
2316
|
+
/** Average call duration in seconds for answered calls today. */
|
|
1508
2317
|
avgDuration: number;
|
|
1509
2318
|
};
|
|
1510
2319
|
}
|
|
@@ -1514,38 +2323,118 @@ export interface ExportCallsParams {
|
|
|
1514
2323
|
direction?: 'inbound' | 'outbound' | 'internal' | 'all';
|
|
1515
2324
|
limit?: number;
|
|
1516
2325
|
}
|
|
2326
|
+
/**
|
|
2327
|
+
* SIP registration credentials for WebRTC softphone authentication.
|
|
2328
|
+
*
|
|
2329
|
+
* Returned by `getSipCredentials()` when creating an extension or manually.
|
|
2330
|
+
* Pass these to the `WebRTCPhone` constructor for SIP registration.
|
|
2331
|
+
*
|
|
2332
|
+
* @example
|
|
2333
|
+
* ```ts
|
|
2334
|
+
* const creds = await voip.getSipCredentials('1001');
|
|
2335
|
+
* const phone = new WebRTCPhone({
|
|
2336
|
+
* extension: creds.extension,
|
|
2337
|
+
* password: creds.password,
|
|
2338
|
+
* displayName: creds.displayName,
|
|
2339
|
+
* sipDomain: creds.sipDomain,
|
|
2340
|
+
* wsUri: creds.wsUri,
|
|
2341
|
+
* });
|
|
2342
|
+
* ```
|
|
2343
|
+
*/
|
|
1517
2344
|
export interface SipCredentials {
|
|
2345
|
+
/** Extension number used as SIP username. Example: `"1001"`. */
|
|
1518
2346
|
extension: string;
|
|
2347
|
+
/** Display name for caller ID. Example: `"John Smith"`. */
|
|
1519
2348
|
displayName: string;
|
|
2349
|
+
/** SIP password for registration. */
|
|
1520
2350
|
password: string;
|
|
2351
|
+
/** SIP domain the phone should register to. Example: `"demo.sip.cemscale.com"`. */
|
|
1521
2352
|
sipDomain: string;
|
|
2353
|
+
/** WebSocket URI for SIP signaling. Example: `"wss://sip.cemscale.com/ws"`. */
|
|
1522
2354
|
wsUri: string;
|
|
2355
|
+
/** SIP registrar address (same as sipDomain but explicit for sip.js config). Example: `"sip.cemscale.com"`. */
|
|
1523
2356
|
registrar: string;
|
|
1524
2357
|
}
|
|
2358
|
+
/**
|
|
2359
|
+
* An API key for authenticating API requests.
|
|
2360
|
+
*
|
|
2361
|
+
* API keys are the recommended way to authenticate SDK requests in production
|
|
2362
|
+
* (server-side integrations, CRMs, automation scripts). They never expire by
|
|
2363
|
+
* default and have role-based scopes.
|
|
2364
|
+
*
|
|
2365
|
+
* **CRITICAL:** The full key is only returned on `createApiKey()` and
|
|
2366
|
+
* `regenerateApiKey()` responses. After that, only `keyPreview` is shown.
|
|
2367
|
+
* Store the full key securely — it cannot be retrieved again.
|
|
2368
|
+
*
|
|
2369
|
+
* @example
|
|
2370
|
+
* ```ts
|
|
2371
|
+
* const { apiKey } = await voip.createApiKey({
|
|
2372
|
+
* name: 'CRM Integration',
|
|
2373
|
+
* role: 'admin',
|
|
2374
|
+
* });
|
|
2375
|
+
* console.log(apiKey.key); // "csk_live_abc123def456..." — STORE THIS NOW
|
|
2376
|
+
* console.log(apiKey.keyPreview); // "csk_live_••••••••def456"
|
|
2377
|
+
* ```
|
|
2378
|
+
*/
|
|
1525
2379
|
export interface ApiKey {
|
|
2380
|
+
/** Database UUID of the API key. */
|
|
1526
2381
|
id: string;
|
|
2382
|
+
/** Human-readable name for this key. Example: `"CRM Integration"`. */
|
|
1527
2383
|
name: string;
|
|
1528
|
-
/** Full raw key — only present on create and regenerate responses */
|
|
2384
|
+
/** Full raw key — only present on create and regenerate responses. Format: `"csk_live_..."`. **Store securely.** Will be `undefined` in list/get responses. */
|
|
1529
2385
|
key?: string;
|
|
1530
|
-
/** Masked preview: csk_live_••••••••abcd1234 */
|
|
2386
|
+
/** Masked preview: csk_live_••••••••abcd1234. Safe to display in UI. Always present. */
|
|
1531
2387
|
keyPreview: string;
|
|
2388
|
+
/** Role determining permissions: `'admin'`, `'readonly'`, `'user'`, `'superadmin'`. */
|
|
1532
2389
|
role: string;
|
|
2390
|
+
/** API permission scopes. Example: `["read:calls", "write:extensions"]`. */
|
|
1533
2391
|
scopes: string[];
|
|
2392
|
+
/** ISO 8601 timestamp of last usage. `null` if never used. */
|
|
1534
2393
|
lastUsedAt: string | null;
|
|
2394
|
+
/** ISO 8601 timestamp when this key expires. `null` if never expires. */
|
|
1535
2395
|
expiresAt: string | null;
|
|
2396
|
+
/** Key status: `'active'` or `'revoked'`. */
|
|
1536
2397
|
status: string;
|
|
2398
|
+
/** Who created this key (email or user ID). `null` for legacy keys. */
|
|
1537
2399
|
createdBy: string | null;
|
|
2400
|
+
/** ISO 8601 timestamp of creation. `null` for legacy keys. */
|
|
1538
2401
|
createdAt: string | null;
|
|
2402
|
+
/** ISO 8601 timestamp when this key was revoked. `null` if active. */
|
|
1539
2403
|
revokedAt?: string | null;
|
|
1540
2404
|
}
|
|
2405
|
+
/**
|
|
2406
|
+
* Parameters for creating a new API key.
|
|
2407
|
+
*
|
|
2408
|
+
* At minimum, provide a `name`. The role defaults to `'admin'`.
|
|
2409
|
+
* Use `scopes` for fine-grained permission control.
|
|
2410
|
+
*
|
|
2411
|
+
* Superadmin-only fields (`global`, `tenantId`) allow creating keys
|
|
2412
|
+
* that span tenants or target specific tenants.
|
|
2413
|
+
*
|
|
2414
|
+
* @example
|
|
2415
|
+
* ```ts
|
|
2416
|
+
* // Admin key with full CRUD
|
|
2417
|
+
* const { apiKey } = await voip.createApiKey({ name: 'CRM Admin', role: 'admin' });
|
|
2418
|
+
*
|
|
2419
|
+
* // Read-only key for reporting
|
|
2420
|
+
* const { apiKey } = await voip.createApiKey({ name: 'Reports', role: 'readonly' });
|
|
2421
|
+
*
|
|
2422
|
+
* // Superadmin: create global key for all tenants
|
|
2423
|
+
* const { apiKey } = await voip.createApiKey({ name: 'Global Ops', role: 'superadmin', global: true });
|
|
2424
|
+
* ```
|
|
2425
|
+
*/
|
|
1541
2426
|
export interface CreateApiKeyParams {
|
|
2427
|
+
/** Human-readable name. Example: `"CRM Integration"`. */
|
|
1542
2428
|
name: string;
|
|
2429
|
+
/** Role for permission level: `'admin'` (full CRUD), `'readonly'` (GET only), `'user'` (limited), `'superadmin'` (full PBX). Default: `'admin'`. */
|
|
1543
2430
|
role?: 'admin' | 'readonly' | 'user' | 'superadmin';
|
|
2431
|
+
/** API permission scopes for fine-grained control. Example: `["read:calls", "write:extensions", "read:recordings"]`. */
|
|
1544
2432
|
scopes?: string[];
|
|
2433
|
+
/** ISO 8601 expiration date. `null` (omit) = never expires. Example: `"2026-12-31T23:59:59Z"`. */
|
|
1545
2434
|
expiresAt?: string;
|
|
1546
|
-
/** Superadmin only: create a global API key with no tenant (full PBX control) */
|
|
2435
|
+
/** Superadmin only: create a global API key with no tenant (full PBX control). */
|
|
1547
2436
|
global?: boolean;
|
|
1548
|
-
/** Superadmin only: specify which tenant this key belongs to */
|
|
2437
|
+
/** Superadmin only: specify which tenant this key belongs to. */
|
|
1549
2438
|
tenantId?: string;
|
|
1550
2439
|
}
|
|
1551
2440
|
export interface UpdateApiKeyParams {
|
|
@@ -1607,17 +2496,201 @@ export interface VoIPClientConfig {
|
|
|
1607
2496
|
/** Request timeout in ms (default 15000) */
|
|
1608
2497
|
timeout?: number;
|
|
1609
2498
|
}
|
|
2499
|
+
/**
|
|
2500
|
+
* A participant in a three-way conference.
|
|
2501
|
+
*
|
|
2502
|
+
* Each participant is identified by their FreeSWITCH channel UUID (`uuid`)
|
|
2503
|
+
* and their conference member ID (`memberId`). Use `memberId` for mute/kick
|
|
2504
|
+
* operations, and `uuid` for swap/merge operations.
|
|
2505
|
+
*
|
|
2506
|
+
* **Status:** `'active'` = in conference and talking. `'held'` = kicked out
|
|
2507
|
+
* of the conference and placed on hold (hears music). Swapping toggles these.
|
|
2508
|
+
*/
|
|
1610
2509
|
export interface ThreeWayParticipant {
|
|
1611
|
-
/** FreeSWITCH channel UUID of this leg */
|
|
2510
|
+
/** FreeSWITCH channel UUID of this leg. Use for swap operations (`keepUuid`/`holdUuid` in `swapParticipant()`). Example: `"a1b2c3d4-..."`. */
|
|
1612
2511
|
uuid: string;
|
|
1613
|
-
/** FreeSWITCH conference member ID (
|
|
2512
|
+
/** FreeSWITCH conference member ID (integer). Use for mute/kick operations within the conference. Example: `"1"`. */
|
|
1614
2513
|
memberId: string;
|
|
2514
|
+
/** Caller ID number of this participant. Example: `"+17865551234"` or `"1002"`. */
|
|
1615
2515
|
callerIdNumber: string;
|
|
2516
|
+
/** Caller ID name of this participant. Example: `"John Smith"`. */
|
|
1616
2517
|
callerIdName: string;
|
|
2518
|
+
/** Whether this participant is muted in the conference. */
|
|
1617
2519
|
muted: boolean;
|
|
1618
|
-
/** 'active' = in conference, 'held' = kicked out and on hold */
|
|
2520
|
+
/** `'active'` = in conference, `'held'` = kicked out and on hold (hears music). */
|
|
1619
2521
|
status: 'active' | 'held';
|
|
1620
2522
|
}
|
|
2523
|
+
/**
|
|
2524
|
+
* State machine for a three-way call session.
|
|
2525
|
+
*
|
|
2526
|
+
* ## Lifecycle
|
|
2527
|
+
*
|
|
2528
|
+
* ```
|
|
2529
|
+
* [Call A active] → addCallParticipant(...)
|
|
2530
|
+
* → adding (hold A, dialing B, waiting for answer)
|
|
2531
|
+
* → [B answers] → mergeCalls(...)
|
|
2532
|
+
* → active (all three in conference)
|
|
2533
|
+
* → swapParticipant(keep, hold) → swapping → active
|
|
2534
|
+
* → kickParticipant(...)
|
|
2535
|
+
* → [caller hangs up] → conference auto-destroys
|
|
2536
|
+
* ```
|
|
2537
|
+
*
|
|
2538
|
+
* ## Key fields
|
|
2539
|
+
*
|
|
2540
|
+
* - `conferenceName`: The FreeSWITCH conference room name. Needed for swap/kick operations.
|
|
2541
|
+
* - `state`: Current phase of the three-way call.
|
|
2542
|
+
* - `pendingUuid`: UUID of Person B's leg while dialing (before merge). `null` after merge.
|
|
2543
|
+
* - `originalBridgedLeg`: UUID of Person A's PSTN bridge leg. Needed to merge correctly.
|
|
2544
|
+
*
|
|
2545
|
+
* @example
|
|
2546
|
+
* ```ts
|
|
2547
|
+
* // Listen for three-way session state
|
|
2548
|
+
* voip.on('threeWayUpdate', (session: ThreeWaySession) => {
|
|
2549
|
+
* if (session.state === 'active') {
|
|
2550
|
+
* console.log('Three-way conference active:', session.conferenceName);
|
|
2551
|
+
* session.participants.forEach(p => {
|
|
2552
|
+
* console.log(` ${p.callerIdNumber} (${p.status}) muted=${p.muted}`);
|
|
2553
|
+
* });
|
|
2554
|
+
* }
|
|
2555
|
+
* });
|
|
2556
|
+
* ```
|
|
2557
|
+
*/
|
|
2558
|
+
export interface ThreeWaySession {
|
|
2559
|
+
/** FreeSWITCH conference room name. Pass to `swapParticipant()`, `kickParticipant()`, `endConference()`. Example: `"conf_abc123"`. */
|
|
2560
|
+
conferenceName: string;
|
|
2561
|
+
/** Current state of the three-way session. Use for UI state: show "Adding participant..." during `'adding'`, show participant list during `'active'`. */
|
|
2562
|
+
state: ThreeWayState;
|
|
2563
|
+
/** List of participants currently in the conference. */
|
|
2564
|
+
participants: ThreeWayParticipant[];
|
|
2565
|
+
/** UUID of the second call leg while dialing (before merge). `null` after successful merge or if no pending dial. */
|
|
2566
|
+
pendingUuid?: string;
|
|
2567
|
+
/** UUID of the bridged PSTN leg of the original call. Required for correct merge — returned by `addCallParticipant()`. `null` if the original call had no bridged PSTN leg. */
|
|
2568
|
+
originalBridgedLeg?: string;
|
|
2569
|
+
}
|
|
2570
|
+
/**
|
|
2571
|
+
* Parameters for adding a participant to an active call (first step of three-way calling).
|
|
2572
|
+
*
|
|
2573
|
+
* Provide either `toNumber` (external PSTN) or `toExtension` (internal extension),
|
|
2574
|
+
* but not both. The active call is placed on hold while dialing the new party.
|
|
2575
|
+
*
|
|
2576
|
+
* On success, you receive `newCallUuid` (the new leg's UUID) and `originalBridgedLeg`
|
|
2577
|
+
* (the original call's bridged PSTN leg UUID). Pass both to `mergeCalls()`.
|
|
2578
|
+
*
|
|
2579
|
+
* @example
|
|
2580
|
+
* ```ts
|
|
2581
|
+
* // Add external participant
|
|
2582
|
+
* const { newCallUuid, originalBridgedLeg } = await voip.addCallParticipant(callUuid, {
|
|
2583
|
+
* toNumber: '+17865559999',
|
|
2584
|
+
* });
|
|
2585
|
+
*
|
|
2586
|
+
* // Add internal extension
|
|
2587
|
+
* const { newCallUuid } = await voip.addCallParticipant(callUuid, {
|
|
2588
|
+
* toExtension: '1002',
|
|
2589
|
+
* });
|
|
2590
|
+
* ```
|
|
2591
|
+
*/
|
|
2592
|
+
export interface AddParticipantParams {
|
|
2593
|
+
/** PSTN number to call in E.164 format. Example: `"+17865559999"`. */
|
|
2594
|
+
toNumber?: string;
|
|
2595
|
+
/** Internal extension to add. Example: `"1002"`. */
|
|
2596
|
+
toExtension?: string;
|
|
2597
|
+
}
|
|
2598
|
+
/**
|
|
2599
|
+
* Response from `addCallParticipant()`.
|
|
2600
|
+
*
|
|
2601
|
+
* Use `newCallUuid` and `originalBridgedLeg` in the subsequent `mergeCalls()` call
|
|
2602
|
+
* to join all three parties into a conference.
|
|
2603
|
+
*/
|
|
2604
|
+
export interface AddParticipantResponse {
|
|
2605
|
+
/** Human-readable message. Example: `"Second call (UUID xxx) established — ready to merge"`. */
|
|
2606
|
+
message: string;
|
|
2607
|
+
/** FreeSWITCH channel UUID of the new call leg (Person B). Pass as `callUuidB` to `mergeCalls()`. */
|
|
2608
|
+
newCallUuid: string;
|
|
2609
|
+
/** FreeSWITCH channel UUID of the original call's bridged PSTN leg. Pass as `bridgedLegA` to `mergeCalls()` for correct merging. */
|
|
2610
|
+
originalBridgedLeg: string;
|
|
2611
|
+
}
|
|
2612
|
+
/**
|
|
2613
|
+
* Parameters for merging two calls into a three-way conference (second step).
|
|
2614
|
+
*
|
|
2615
|
+
* After `addCallParticipant()` succeeds, call `mergeCalls()` with the UUIDs to
|
|
2616
|
+
* join Person A, Person B, and the original PSTN caller into one conference.
|
|
2617
|
+
*
|
|
2618
|
+
* @example
|
|
2619
|
+
* ```ts
|
|
2620
|
+
* const result = await voip.mergeCalls({
|
|
2621
|
+
* callUuidA: activeCall.uuid, // User's WebRTC session
|
|
2622
|
+
* callUuidB: addResult.newCallUuid, // New call leg from addCallParticipant
|
|
2623
|
+
* bridgedLegA: addResult.originalBridgedLeg, // Original PSTN leg
|
|
2624
|
+
* });
|
|
2625
|
+
* console.log('Conference created:', result.conferenceName);
|
|
2626
|
+
* ```
|
|
2627
|
+
*/
|
|
2628
|
+
export interface MergeCallsParams {
|
|
2629
|
+
/** UUID of the user's WebRTC session (first call). Use `WebRTCCallInfo.fsChannelUuid`. */
|
|
2630
|
+
callUuidA: string;
|
|
2631
|
+
/** UUID returned by addCallParticipant (Person B's direct channel). */
|
|
2632
|
+
callUuidB: string;
|
|
2633
|
+
/**
|
|
2634
|
+
* Person A's PSTN leg UUID — returned as `originalBridgedLeg` by addCallParticipant.
|
|
2635
|
+
* Passing this avoids an extra ESL lookup and ensures the correct leg is used.
|
|
2636
|
+
*/
|
|
2637
|
+
bridgedLegA?: string;
|
|
2638
|
+
/** Optional custom conference name — auto-generated if omitted. */
|
|
2639
|
+
conferenceName?: string;
|
|
2640
|
+
}
|
|
2641
|
+
/**
|
|
2642
|
+
* Response from `mergeCalls()`.
|
|
2643
|
+
*
|
|
2644
|
+
* Contains the conference name (needed for swap/kick/end operations) and the
|
|
2645
|
+
* full participant list with UUIDs, caller IDs, and mute/held status.
|
|
2646
|
+
*/
|
|
2647
|
+
export interface MergeCallsResponse {
|
|
2648
|
+
/** Human-readable message. Example: `"Calls merged into conference conf_abc123"`. */
|
|
2649
|
+
message: string;
|
|
2650
|
+
/** FreeSWITCH conference room name. Store this for subsequent swap/kick/end operations. */
|
|
2651
|
+
conferenceName: string;
|
|
2652
|
+
/** List of all participants now in the conference. Use for rendering participant cards in the UI. */
|
|
2653
|
+
participants: ThreeWayParticipant[];
|
|
2654
|
+
}
|
|
2655
|
+
/**
|
|
2656
|
+
* Parameters for directly merging two active WebRTC calls (no PSTN party).
|
|
2657
|
+
*
|
|
2658
|
+
* Use this when the user has two WebRTC calls active simultaneously (e.g.
|
|
2659
|
+
* call on line 1 and line 2) and wants to merge them directly.
|
|
2660
|
+
*
|
|
2661
|
+
* Unlike `addCallParticipant` → `mergeCalls`, this doesn't need a bridged leg UUID
|
|
2662
|
+
* because both calls are WebRTC (no PSTN bridge).
|
|
2663
|
+
*
|
|
2664
|
+
* @example
|
|
2665
|
+
* ```ts
|
|
2666
|
+
* const result = await voip.mergeDirectCalls({
|
|
2667
|
+
* callUuidA: call1.fsChannelUuid,
|
|
2668
|
+
* callUuidB: call2.fsChannelUuid,
|
|
2669
|
+
* });
|
|
2670
|
+
* ```
|
|
2671
|
+
*/
|
|
2672
|
+
export interface MergeDirectParams {
|
|
2673
|
+
/** UUID of the first call (WebRTC leg). Use `WebRTCCallInfo.fsChannelUuid`. */
|
|
2674
|
+
callUuidA: string;
|
|
2675
|
+
/** UUID of the second call to merge (WebRTC leg). Use `WebRTCCallInfo.fsChannelUuid`. */
|
|
2676
|
+
callUuidB: string;
|
|
2677
|
+
/** Optional custom conference name — auto-generated if omitted. */
|
|
2678
|
+
conferenceName?: string;
|
|
2679
|
+
}
|
|
2680
|
+
/**
|
|
2681
|
+
* Response from `mergeDirectCalls()`.
|
|
2682
|
+
*
|
|
2683
|
+
* Same structure as `MergeCallsResponse`. All participants are now in the
|
|
2684
|
+
* named conference and can be swapped/kicked independently.
|
|
2685
|
+
*/
|
|
2686
|
+
export interface MergeDirectResponse {
|
|
2687
|
+
/** Human-readable message. Example: `"Calls merged into conference conf_abc123"`. */
|
|
2688
|
+
message: string;
|
|
2689
|
+
/** FreeSWITCH conference room name. Store for subsequent operations. */
|
|
2690
|
+
conferenceName: string;
|
|
2691
|
+
/** List of all participants now in the conference. */
|
|
2692
|
+
participants: ThreeWayParticipant[];
|
|
2693
|
+
}
|
|
1621
2694
|
export type ThreeWayState = 'adding' | 'active' | 'swapping';
|
|
1622
2695
|
export interface ThreeWaySession {
|
|
1623
2696
|
conferenceName: string;
|
|
@@ -1740,7 +2813,25 @@ export interface AiAgentListResponse {
|
|
|
1740
2813
|
agents: AiAgent[];
|
|
1741
2814
|
total: number;
|
|
1742
2815
|
}
|
|
2816
|
+
/**
|
|
2817
|
+
* Response containing a single AI agent.
|
|
2818
|
+
*
|
|
2819
|
+
* Returned by `createAiAgent()`, `getAiAgent()`, and `updateAiAgent()`.
|
|
2820
|
+
* The `agent` field contains the full agent configuration from the AI Bridge.
|
|
2821
|
+
*
|
|
2822
|
+
* @example
|
|
2823
|
+
* ```ts
|
|
2824
|
+
* const { agent } = await voip.createAiAgent({
|
|
2825
|
+
* agent_id: 'acme-sales',
|
|
2826
|
+
* display_name: 'Sofia',
|
|
2827
|
+
* voice: 'Aoede',
|
|
2828
|
+
* tools: ['transfer_to_human', 'end_call'],
|
|
2829
|
+
* });
|
|
2830
|
+
* console.log(`Agent "${agent.display_name}" (${agent.agent_id}) created`);
|
|
2831
|
+
* ```
|
|
2832
|
+
*/
|
|
1743
2833
|
export interface AiAgentResponse {
|
|
2834
|
+
/** The full AI agent object from the AI Bridge. */
|
|
1744
2835
|
agent: AiAgent;
|
|
1745
2836
|
}
|
|
1746
2837
|
export interface AiBridgeHealthResponse {
|
|
@@ -1920,32 +3011,81 @@ export interface AiCallHistoryResponse {
|
|
|
1920
3011
|
calls: AiCallRecord[];
|
|
1921
3012
|
total: number;
|
|
1922
3013
|
}
|
|
3014
|
+
/**
|
|
3015
|
+
* A paging group for one-way audio broadcast (intercom/PA system).
|
|
3016
|
+
*
|
|
3017
|
+
* When someone dials `extension_code` (e.g. `*801`), all online members auto-answer
|
|
3018
|
+
* and hear the caller through their speaker. This is a one-way broadcast — members
|
|
3019
|
+
* hear the caller but cannot speak back.
|
|
3020
|
+
*
|
|
3021
|
+
* @example
|
|
3022
|
+
* ```ts
|
|
3023
|
+
* const { pagingGroups } = await voip.listPagingGroups();
|
|
3024
|
+
* pagingGroups.forEach(pg => {
|
|
3025
|
+
* console.log(`${pg.name} (${pg.extension_code}): ${pg.members.length} members`);
|
|
3026
|
+
* });
|
|
3027
|
+
* ```
|
|
3028
|
+
*/
|
|
1923
3029
|
export interface PagingGroup {
|
|
3030
|
+
/** Database UUID of the paging group. */
|
|
1924
3031
|
id: string;
|
|
3032
|
+
/** Tenant UUID. */
|
|
1925
3033
|
tenant_id: string;
|
|
3034
|
+
/** Human-readable name. Example: `"All users"`. */
|
|
1926
3035
|
name: string;
|
|
3036
|
+
/** Optional description. `null` if not set. */
|
|
1927
3037
|
description: string | null;
|
|
3038
|
+
/** Dial code to trigger paging (e.g. `"*801"`). Must start with `*8`. Unique per tenant. */
|
|
1928
3039
|
extension_code: string;
|
|
3040
|
+
/** Group status: `'active'` or `'disabled'`. */
|
|
1929
3041
|
status: string;
|
|
3042
|
+
/** ISO 8601 timestamp of creation. */
|
|
1930
3043
|
created_at: string;
|
|
3044
|
+
/** ISO 8601 timestamp of last update. */
|
|
1931
3045
|
updated_at: string;
|
|
3046
|
+
/** List of extension numbers that are members of this paging group. */
|
|
1932
3047
|
members: PagingGroupMember[];
|
|
3048
|
+
/** Tenant summary — present when queried as global superadmin. */
|
|
1933
3049
|
tenant?: {
|
|
1934
3050
|
id: string;
|
|
1935
3051
|
company_name: string;
|
|
1936
3052
|
subdomain: string;
|
|
1937
3053
|
};
|
|
1938
3054
|
}
|
|
3055
|
+
/**
|
|
3056
|
+
* A member extension within a paging group.
|
|
3057
|
+
*/
|
|
1939
3058
|
export interface PagingGroupMember {
|
|
3059
|
+
/** Database UUID of this member entry. */
|
|
1940
3060
|
id: string;
|
|
3061
|
+
/** Parent paging group UUID. */
|
|
1941
3062
|
paging_group_id: string;
|
|
3063
|
+
/** Extension number. Example: `"1001"`. */
|
|
1942
3064
|
extension: string;
|
|
3065
|
+
/** ISO 8601 timestamp when this member was added. */
|
|
1943
3066
|
created_at: string;
|
|
1944
3067
|
}
|
|
3068
|
+
/**
|
|
3069
|
+
* Parameters for creating a new paging group with members.
|
|
3070
|
+
*
|
|
3071
|
+
* @example
|
|
3072
|
+
* ```ts
|
|
3073
|
+
* await voip.createPagingGroup({
|
|
3074
|
+
* name: 'Sales Floor',
|
|
3075
|
+
* description: 'Broadcast to all sales agents',
|
|
3076
|
+
* extensionCode: '*802',
|
|
3077
|
+
* members: [{ extension: '1001' }, { extension: '1002' }, { extension: '1005' }],
|
|
3078
|
+
* });
|
|
3079
|
+
* ```
|
|
3080
|
+
*/
|
|
1945
3081
|
export interface CreatePagingGroupParams {
|
|
3082
|
+
/** Human-readable group name. Example: `"Sales Floor"`. Must be unique within the tenant. */
|
|
1946
3083
|
name: string;
|
|
3084
|
+
/** Optional description of the group's purpose. */
|
|
1947
3085
|
description?: string;
|
|
3086
|
+
/** Dial code to activate paging (e.g. `"*802"`). Must start with `*8` and be unique within the tenant. */
|
|
1948
3087
|
extensionCode: string;
|
|
3088
|
+
/** Array of extensions to include as members. Each entry requires `extension` field. */
|
|
1949
3089
|
members: {
|
|
1950
3090
|
extension: string;
|
|
1951
3091
|
}[];
|