@unboundcx/sdk 4.8.8 → 4.8.10

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/base.js CHANGED
@@ -410,37 +410,36 @@ export class BaseSDK {
410
410
  'application/json';
411
411
 
412
412
  if (!response.ok) {
413
+ // A fetch Response's `.body` is a ReadableStream, not the parsed
414
+ // payload — it must go through json()/text() or the API's
415
+ // `{ message }` envelope is lost and every error surfaces as the
416
+ // generic "API Error". Only NATS-transport responses carry a
417
+ // pre-parsed `.body`.
413
418
  let errorBody;
414
- if (response?.body) {
415
- errorBody = response.body;
416
- } else if (response?.headers?.['content-type']) {
417
- try {
418
- if (
419
- typeof response?.json === 'function' ||
420
- typeof response?.text === 'function'
421
- ) {
422
- if (contentType.includes('application/json')) {
423
- errorBody = await response.json();
424
- } else if (contentType.includes('text/')) {
425
- errorBody = await response.text();
426
- }
427
- } else {
428
- if (contentType.includes('application/json')) {
429
- errorBody = this._getJsonSafely(
430
- response?.body,
431
- response?.body || {},
432
- );
433
- } else if (contentType.includes('text/')) {
434
- errorBody = response?.body || '';
435
- }
419
+ try {
420
+ if (
421
+ typeof response?.json === 'function' ||
422
+ typeof response?.text === 'function'
423
+ ) {
424
+ if (contentType.includes('application/json')) {
425
+ errorBody = await response.json();
426
+ } else if (contentType.includes('text/')) {
427
+ errorBody = await response.text();
436
428
  }
437
- if (!errorBody) {
438
- errorBody = `HTTP ${response.status} ${response.statusText}`;
429
+ } else if (response?.body) {
430
+ if (contentType.includes('application/json')) {
431
+ errorBody = this._getJsonSafely(
432
+ response?.body,
433
+ response?.body || {},
434
+ );
435
+ } else {
436
+ errorBody = response.body;
439
437
  }
440
- } catch (parseError) {
441
- errorBody = `HTTP ${response.status} ${response.statusText}`;
442
438
  }
443
- } else {
439
+ } catch (parseError) {
440
+ // fall through to the status-line fallback below
441
+ }
442
+ if (!errorBody) {
444
443
  errorBody = `HTTP ${response.status} ${response.statusText}`;
445
444
  }
446
445
 
@@ -455,7 +454,10 @@ export class BaseSDK {
455
454
  httpError.method = method;
456
455
  httpError.endpoint = endpoint;
457
456
  httpError.body = errorBody;
458
- httpError.message = errorBody?.error || errorBody?.message || 'API Error';
457
+ httpError.message =
458
+ errorBody?.error ||
459
+ errorBody?.message ||
460
+ (typeof errorBody === 'string' ? errorBody : 'API Error');
459
461
 
460
462
  // Debug logging for successful HTTP requests
461
463
  if (this.debugMode) {
package/index.js CHANGED
@@ -33,6 +33,7 @@ import { TriggersService } from './services/triggers.js';
33
33
  import { InboxService } from './services/inbox.js';
34
34
  import { SearchService } from './services/search.js';
35
35
  import { DirectoryService } from './services/directory.js';
36
+ import { ChatService } from './services/chat.js';
36
37
 
37
38
  class UnboundSDK extends BaseSDK {
38
39
  constructor(options = {}) {
@@ -107,6 +108,7 @@ class UnboundSDK extends BaseSDK {
107
108
  this.inbox = new InboxService(this);
108
109
  this.search = new SearchService(this);
109
110
  this.directory = new DirectoryService(this);
111
+ this.chat = new ChatService(this);
110
112
 
111
113
  // Add additional services that might be missing
112
114
  this._initializeAdditionalServices();
@@ -290,4 +292,5 @@ export { PermissionsService } from './services/permissions.js';
290
292
  export { InboxService } from './services/inbox.js';
291
293
  export { SearchService } from './services/search.js';
292
294
  export { DirectoryService } from './services/directory.js';
295
+ export { ChatService } from './services/chat.js';
293
296
  export { BaseSDK } from './base.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unboundcx/sdk",
3
- "version": "4.8.8",
3
+ "version": "4.8.10",
4
4
  "description": "Official JavaScript SDK for the Unbound API - A comprehensive toolkit for integrating with Unbound's communication, AI, and data management services",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -0,0 +1,851 @@
1
+ /**
2
+ * ChatService — channels, DMs, membership, unreads, DND, messages, search,
3
+ * webhooks, card actions, reports, admin review, admin export, record feeds,
4
+ * channel meet, push devices, and notifyLevel.
5
+ * Backed by /chat/* on app1-api (checkApiAuth). Incoming webhook POST
6
+ * (HMAC) is external and is not an SDK method.
7
+ */
8
+ export class ChatService {
9
+ constructor(sdk) {
10
+ this.sdk = sdk;
11
+ }
12
+
13
+ /**
14
+ * Create a channel.
15
+ * @param {Object} params
16
+ * @param {string} params.name - Channel name (required)
17
+ * @param {string} [params.topic]
18
+ * @param {'public'|'private'|'dm'|'group_dm'|'record'|'meeting'} [params.kind]
19
+ * @param {Object} [params.settings]
20
+ * @param {string[]} [params.groupIds] - Groups whose members are auto-added
21
+ * @returns {Promise<Object>} Created channel
22
+ */
23
+ async createChannel({ name, topic, kind, settings, groupIds }) {
24
+ this.sdk.validateParams(
25
+ { name, topic, kind, settings, groupIds },
26
+ {
27
+ name: { type: 'string', required: true },
28
+ topic: { type: 'string', required: false },
29
+ kind: { type: 'string', required: false },
30
+ settings: { type: 'object', required: false },
31
+ groupIds: { type: 'array', required: false },
32
+ },
33
+ );
34
+
35
+ const body = { name };
36
+ if (topic !== undefined) body.topic = topic;
37
+ if (kind !== undefined) body.kind = kind;
38
+ if (settings !== undefined) body.settings = settings;
39
+ if (groupIds !== undefined) body.groupIds = groupIds;
40
+
41
+ return this.sdk._fetch('/chat/channels', 'POST', { body });
42
+ }
43
+
44
+ /**
45
+ * List channels the current user is a member of.
46
+ * @returns {Promise<Object>}
47
+ */
48
+ async listChannels() {
49
+ return this.sdk._fetch('/chat/channels', 'GET');
50
+ }
51
+
52
+ /**
53
+ * Browse joinable (public) channels.
54
+ * @returns {Promise<Object>}
55
+ */
56
+ async browseChannels() {
57
+ return this.sdk._fetch('/chat/channels/browse', 'GET');
58
+ }
59
+
60
+ /**
61
+ * Get a channel by id.
62
+ * @param {string} id
63
+ * @returns {Promise<Object>}
64
+ */
65
+ async getChannel(id) {
66
+ this.sdk.validateParams({ id }, { id: { type: 'string', required: true } });
67
+ return this.sdk._fetch(`/chat/channels/${id}`, 'GET');
68
+ }
69
+
70
+ /**
71
+ * Update channel name/topic/settings.
72
+ * @param {string} id
73
+ * @param {Object} [params]
74
+ * @param {string} [params.name]
75
+ * @param {string} [params.topic]
76
+ * @param {Object} [params.settings]
77
+ * @returns {Promise<Object>}
78
+ */
79
+ async updateChannel(id, { name, topic, settings } = {}) {
80
+ this.sdk.validateParams(
81
+ { id, name, topic, settings },
82
+ {
83
+ id: { type: 'string', required: true },
84
+ name: { type: 'string', required: false },
85
+ topic: { type: 'string', required: false },
86
+ settings: { type: 'object', required: false },
87
+ },
88
+ );
89
+
90
+ const body = {};
91
+ if (name !== undefined) body.name = name;
92
+ if (topic !== undefined) body.topic = topic;
93
+ if (settings !== undefined) body.settings = settings;
94
+
95
+ return this.sdk._fetch(`/chat/channels/${id}`, 'PATCH', { body });
96
+ }
97
+
98
+ /**
99
+ * Archive a channel (reversible; hard delete is not supported).
100
+ * @param {string} id
101
+ * @returns {Promise<Object>}
102
+ */
103
+ async archiveChannel(id) {
104
+ this.sdk.validateParams({ id }, { id: { type: 'string', required: true } });
105
+ return this.sdk._fetch(`/chat/channels/${id}/archive`, 'POST', {
106
+ body: {},
107
+ });
108
+ }
109
+
110
+ /**
111
+ * Unarchive a channel.
112
+ * @param {string} id
113
+ * @returns {Promise<Object>}
114
+ */
115
+ async unarchiveChannel(id) {
116
+ this.sdk.validateParams({ id }, { id: { type: 'string', required: true } });
117
+ return this.sdk._fetch(`/chat/channels/${id}/unarchive`, 'POST', {
118
+ body: {},
119
+ });
120
+ }
121
+
122
+ /**
123
+ * Join a public channel.
124
+ * @param {string} id
125
+ * @returns {Promise<Object>}
126
+ */
127
+ async joinChannel(id) {
128
+ this.sdk.validateParams({ id }, { id: { type: 'string', required: true } });
129
+ return this.sdk._fetch(`/chat/channels/${id}/join`, 'POST', { body: {} });
130
+ }
131
+
132
+ /**
133
+ * Leave a channel.
134
+ * @param {string} id
135
+ * @returns {Promise<Object>}
136
+ */
137
+ async leaveChannel(id) {
138
+ this.sdk.validateParams({ id }, { id: { type: 'string', required: true } });
139
+ return this.sdk._fetch(`/chat/channels/${id}/leave`, 'POST', { body: {} });
140
+ }
141
+
142
+ /**
143
+ * List members of a channel.
144
+ * @param {string} id
145
+ * @returns {Promise<Object>}
146
+ */
147
+ async listMembers(id) {
148
+ this.sdk.validateParams({ id }, { id: { type: 'string', required: true } });
149
+ return this.sdk._fetch(`/chat/channels/${id}/members`, 'GET');
150
+ }
151
+
152
+ /**
153
+ * Add a member to a channel.
154
+ * @param {string} id
155
+ * @param {Object} params
156
+ * @param {string} params.userId
157
+ * @param {'owner'|'moderator'|'member'} [params.role]
158
+ * @returns {Promise<Object>}
159
+ */
160
+ async addMember(id, { userId, role } = {}) {
161
+ this.sdk.validateParams(
162
+ { id, userId, role },
163
+ {
164
+ id: { type: 'string', required: true },
165
+ userId: { type: 'string', required: true },
166
+ role: { type: 'string', required: false },
167
+ },
168
+ );
169
+
170
+ const body = { userId };
171
+ if (role !== undefined) body.role = role;
172
+
173
+ return this.sdk._fetch(`/chat/channels/${id}/members`, 'POST', { body });
174
+ }
175
+
176
+ /**
177
+ * Remove a member from a channel.
178
+ * @param {string} id
179
+ * @param {string} userId
180
+ * @returns {Promise<Object>}
181
+ */
182
+ async removeMember(id, userId) {
183
+ this.sdk.validateParams(
184
+ { id, userId },
185
+ {
186
+ id: { type: 'string', required: true },
187
+ userId: { type: 'string', required: true },
188
+ },
189
+ );
190
+ return this.sdk._fetch(`/chat/channels/${id}/members/${userId}`, 'DELETE');
191
+ }
192
+
193
+ /**
194
+ * Get group-default membership links for a channel.
195
+ * @param {string} id
196
+ * @returns {Promise<Object>}
197
+ */
198
+ async getGroupDefaults(id) {
199
+ this.sdk.validateParams({ id }, { id: { type: 'string', required: true } });
200
+ return this.sdk._fetch(`/chat/channels/${id}/group-defaults`, 'GET');
201
+ }
202
+
203
+ /**
204
+ * Replace group-default membership links for a channel.
205
+ * @param {string} id
206
+ * @param {Object} params
207
+ * @param {string[]} params.groupIds
208
+ * @returns {Promise<Object>}
209
+ */
210
+ async setGroupDefaults(id, { groupIds } = {}) {
211
+ this.sdk.validateParams(
212
+ { id, groupIds },
213
+ {
214
+ id: { type: 'string', required: true },
215
+ groupIds: { type: 'array', required: true },
216
+ },
217
+ );
218
+ return this.sdk._fetch(`/chat/channels/${id}/group-defaults`, 'PUT', {
219
+ body: { groupIds },
220
+ });
221
+ }
222
+
223
+ /**
224
+ * Find-or-create a 1:1 or group DM.
225
+ * @param {Object} params
226
+ * @param {string[]} params.userIds
227
+ * @returns {Promise<Object>}
228
+ */
229
+ async openDm({ userIds }) {
230
+ this.sdk.validateParams(
231
+ { userIds },
232
+ { userIds: { type: 'array', required: true } },
233
+ );
234
+ return this.sdk._fetch('/chat/dms', 'POST', { body: { userIds } });
235
+ }
236
+
237
+ /**
238
+ * Sidebar unread snapshot (channels + previews + counters).
239
+ * @returns {Promise<Object>}
240
+ */
241
+ async getUnreads() {
242
+ return this.sdk._fetch('/chat/unreads', 'GET');
243
+ }
244
+
245
+ /**
246
+ * Get the caller's Do Not Disturb state.
247
+ * @returns {Promise<Object>}
248
+ */
249
+ async getDnd() {
250
+ return this.sdk._fetch('/chat/dnd', 'GET');
251
+ }
252
+
253
+ /**
254
+ * Set the caller's Do Not Disturb state.
255
+ * @param {Object} params
256
+ * @param {boolean} params.enabled
257
+ * @returns {Promise<Object>}
258
+ */
259
+ async setDnd({ enabled } = {}) {
260
+ this.sdk.validateParams(
261
+ { enabled },
262
+ { enabled: { type: 'boolean', required: true } },
263
+ );
264
+ return this.sdk._fetch('/chat/dnd', 'PATCH', { body: { enabled } });
265
+ }
266
+
267
+ /**
268
+ * Advance the read watermark and recompute unread counters.
269
+ * @param {string} channelId
270
+ * @param {string} messageId
271
+ * @returns {Promise<Object>}
272
+ */
273
+ async markRead(channelId, messageId) {
274
+ this.sdk.validateParams(
275
+ { channelId, messageId },
276
+ {
277
+ channelId: { type: 'string', required: true },
278
+ messageId: { type: 'string', required: true },
279
+ },
280
+ );
281
+ return this.sdk._fetch(`/chat/channels/${channelId}/read`, 'POST', {
282
+ body: { messageId },
283
+ });
284
+ }
285
+
286
+ /**
287
+ * Set the watermark to the message before `messageId` (mark as unread).
288
+ * @param {string} channelId
289
+ * @param {string} messageId
290
+ * @returns {Promise<Object>}
291
+ */
292
+ async markUnread(channelId, messageId) {
293
+ this.sdk.validateParams(
294
+ { channelId, messageId },
295
+ {
296
+ channelId: { type: 'string', required: true },
297
+ messageId: { type: 'string', required: true },
298
+ },
299
+ );
300
+ return this.sdk._fetch(`/chat/channels/${channelId}/unread`, 'POST', {
301
+ body: { messageId },
302
+ });
303
+ }
304
+
305
+ /**
306
+ * Channels linked to a group via defaults (remove-from-group prompt).
307
+ * @param {Object} params
308
+ * @param {string} params.groupId
309
+ * @param {string} params.userId
310
+ * @returns {Promise<Object>}
311
+ */
312
+ async getLinkedChannels({ groupId, userId }) {
313
+ this.sdk.validateParams(
314
+ { groupId, userId },
315
+ {
316
+ groupId: { type: 'string', required: true },
317
+ userId: { type: 'string', required: true },
318
+ },
319
+ );
320
+ return this.sdk._fetch(`/chat/groups/${groupId}/linked-channels`, 'GET', {
321
+ query: { userId },
322
+ });
323
+ }
324
+
325
+ /**
326
+ * List messages in a channel (cursor pagination).
327
+ * @param {string} channelId
328
+ * @param {Object} [params]
329
+ * @param {string} [params.before]
330
+ * @param {string} [params.after]
331
+ * @param {number} [params.limit]
332
+ * @returns {Promise<Object>}
333
+ */
334
+ async listMessages(channelId, { before, after, limit } = {}) {
335
+ this.sdk.validateParams(
336
+ { channelId, before, after, limit },
337
+ {
338
+ channelId: { type: 'string', required: true },
339
+ before: { type: 'string', required: false },
340
+ after: { type: 'string', required: false },
341
+ limit: { type: 'number', required: false },
342
+ },
343
+ );
344
+
345
+ const query = {};
346
+ if (before !== undefined) query.before = before;
347
+ if (after !== undefined) query.after = after;
348
+ if (limit !== undefined) query.limit = limit;
349
+
350
+ return this.sdk._fetch(`/chat/channels/${channelId}/messages`, 'GET', {
351
+ query,
352
+ });
353
+ }
354
+
355
+ /**
356
+ * Send a message to a channel.
357
+ * @param {string} channelId
358
+ * @param {Object} params
359
+ * @param {Object} params.message - ProseMirror JSON (required)
360
+ * @param {string} [params.threadRootId]
361
+ * @param {boolean} [params.alsoSendToChannel]
362
+ * @param {string[]} [params.storageIds]
363
+ * @returns {Promise<Object>} Created message
364
+ */
365
+ async sendMessage(
366
+ channelId,
367
+ { message, threadRootId, alsoSendToChannel, storageIds } = {},
368
+ ) {
369
+ this.sdk.validateParams(
370
+ { channelId, message, threadRootId, alsoSendToChannel, storageIds },
371
+ {
372
+ channelId: { type: 'string', required: true },
373
+ message: { type: 'object', required: true },
374
+ threadRootId: { type: 'string', required: false },
375
+ alsoSendToChannel: { type: 'boolean', required: false },
376
+ storageIds: { type: 'array', required: false },
377
+ },
378
+ );
379
+
380
+ const body = { message };
381
+ if (threadRootId !== undefined) body.threadRootId = threadRootId;
382
+ if (alsoSendToChannel !== undefined) {
383
+ body.alsoSendToChannel = alsoSendToChannel;
384
+ }
385
+ if (storageIds !== undefined) body.storageIds = storageIds;
386
+
387
+ return this.sdk._fetch(`/chat/channels/${channelId}/messages`, 'POST', {
388
+ body,
389
+ });
390
+ }
391
+
392
+ /**
393
+ * Edit a message body (ProseMirror JSON).
394
+ * @param {string} id
395
+ * @param {Object} params
396
+ * @param {Object} params.message - ProseMirror JSON (required)
397
+ * @returns {Promise<Object>}
398
+ */
399
+ async editMessage(id, { message } = {}) {
400
+ this.sdk.validateParams(
401
+ { id, message },
402
+ {
403
+ id: { type: 'string', required: true },
404
+ message: { type: 'object', required: true },
405
+ },
406
+ );
407
+ return this.sdk._fetch(`/chat/messages/${id}`, 'PATCH', {
408
+ body: { message },
409
+ });
410
+ }
411
+
412
+ /**
413
+ * Delete a message (tombstone).
414
+ * @param {string} id
415
+ * @returns {Promise<Object>}
416
+ */
417
+ async deleteMessage(id) {
418
+ this.sdk.validateParams({ id }, { id: { type: 'string', required: true } });
419
+ return this.sdk._fetch(`/chat/messages/${id}`, 'DELETE');
420
+ }
421
+
422
+ /**
423
+ * Add an emoji reaction to a message.
424
+ * @param {string} id
425
+ * @param {Object} params
426
+ * @param {string} params.emoji
427
+ * @returns {Promise<Object>}
428
+ */
429
+ async addReaction(id, { emoji } = {}) {
430
+ this.sdk.validateParams(
431
+ { id, emoji },
432
+ {
433
+ id: { type: 'string', required: true },
434
+ emoji: { type: 'string', required: true },
435
+ },
436
+ );
437
+ return this.sdk._fetch(`/chat/messages/${id}/reactions`, 'POST', {
438
+ body: { emoji },
439
+ });
440
+ }
441
+
442
+ /**
443
+ * Remove an emoji reaction from a message.
444
+ * @param {string} id
445
+ * @param {Object} params
446
+ * @param {string} params.emoji
447
+ * @returns {Promise<Object>}
448
+ */
449
+ async removeReaction(id, { emoji } = {}) {
450
+ this.sdk.validateParams(
451
+ { id, emoji },
452
+ {
453
+ id: { type: 'string', required: true },
454
+ emoji: { type: 'string', required: true },
455
+ },
456
+ );
457
+ return this.sdk._fetch(`/chat/messages/${id}/reactions`, 'DELETE', {
458
+ body: { emoji },
459
+ });
460
+ }
461
+
462
+ /**
463
+ * Get a thread (root + replies) for a channel message.
464
+ * @param {string} channelId
465
+ * @param {string} rootId
466
+ * @returns {Promise<Object>}
467
+ */
468
+ async getThread(channelId, rootId) {
469
+ this.sdk.validateParams(
470
+ { channelId, rootId },
471
+ {
472
+ channelId: { type: 'string', required: true },
473
+ rootId: { type: 'string', required: true },
474
+ },
475
+ );
476
+ return this.sdk._fetch(
477
+ `/chat/channels/${channelId}/messages/${rootId}/thread`,
478
+ 'GET',
479
+ );
480
+ }
481
+
482
+ /**
483
+ * Search messages the current user can read.
484
+ * @param {Object} params
485
+ * @param {string} params.q - Search term (required)
486
+ * @param {string} [params.channelId]
487
+ * @param {string} [params.fromUserId]
488
+ * @param {string} [params.before]
489
+ * @param {string} [params.after]
490
+ * @param {'public'|'private'|'dm'|'group_dm'|'record'|'meeting'} [params.kind]
491
+ * @param {string} [params.nextId]
492
+ * @param {number} [params.limit]
493
+ * @returns {Promise<Object>}
494
+ */
495
+ async search({
496
+ q,
497
+ channelId,
498
+ fromUserId,
499
+ before,
500
+ after,
501
+ kind,
502
+ nextId,
503
+ limit,
504
+ } = {}) {
505
+ this.sdk.validateParams(
506
+ { q, channelId, fromUserId, before, after, kind, nextId, limit },
507
+ {
508
+ q: { type: 'string', required: true },
509
+ channelId: { type: 'string', required: false },
510
+ fromUserId: { type: 'string', required: false },
511
+ before: { type: 'string', required: false },
512
+ after: { type: 'string', required: false },
513
+ kind: { type: 'string', required: false },
514
+ nextId: { type: 'string', required: false },
515
+ limit: { type: 'number', required: false },
516
+ },
517
+ );
518
+
519
+ const query = { q };
520
+ if (channelId !== undefined) query.channelId = channelId;
521
+ if (fromUserId !== undefined) query.fromUserId = fromUserId;
522
+ if (before !== undefined) query.before = before;
523
+ if (after !== undefined) query.after = after;
524
+ if (kind !== undefined) query.kind = kind;
525
+ if (nextId !== undefined) query.nextId = nextId;
526
+ if (limit !== undefined) query.limit = limit;
527
+
528
+ return this.sdk._fetch('/chat/search', 'GET', { query });
529
+ }
530
+
531
+ /**
532
+ * Create a channel incoming webhook (signing secret returned once).
533
+ * Button callback URLs are registered here — never taken from message payloads.
534
+ * @param {string} channelId
535
+ * @param {Object} params
536
+ * @param {string} params.name - Display name (required)
537
+ * @param {string} [params.avatar]
538
+ * @param {string} [params.callbackUrl] - Admin-registered button callback URL
539
+ * @returns {Promise<Object>} Created webhook (includes signingSecret once)
540
+ */
541
+ async createWebhook(channelId, { name, avatar, callbackUrl } = {}) {
542
+ this.sdk.validateParams(
543
+ { channelId, name, avatar, callbackUrl },
544
+ {
545
+ channelId: { type: 'string', required: true },
546
+ name: { type: 'string', required: true },
547
+ avatar: { type: 'string', required: false },
548
+ callbackUrl: { type: 'string', required: false },
549
+ },
550
+ );
551
+
552
+ const body = { name };
553
+ if (avatar !== undefined) body.avatar = avatar;
554
+ if (callbackUrl !== undefined) body.callbackUrl = callbackUrl;
555
+
556
+ return this.sdk._fetch(`/chat/channels/${channelId}/webhooks`, 'POST', {
557
+ body,
558
+ });
559
+ }
560
+
561
+ /**
562
+ * List webhooks for a channel.
563
+ * @param {string} channelId
564
+ * @returns {Promise<Object>}
565
+ */
566
+ async listWebhooks(channelId) {
567
+ this.sdk.validateParams(
568
+ { channelId },
569
+ { channelId: { type: 'string', required: true } },
570
+ );
571
+ return this.sdk._fetch(`/chat/channels/${channelId}/webhooks`, 'GET');
572
+ }
573
+
574
+ /**
575
+ * Revoke a channel webhook.
576
+ * @param {string} channelId
577
+ * @param {string} webhookId
578
+ * @returns {Promise<Object>}
579
+ */
580
+ async revokeWebhook(channelId, webhookId) {
581
+ this.sdk.validateParams(
582
+ { channelId, webhookId },
583
+ {
584
+ channelId: { type: 'string', required: true },
585
+ webhookId: { type: 'string', required: true },
586
+ },
587
+ );
588
+ return this.sdk._fetch(
589
+ `/chat/channels/${channelId}/webhooks/${webhookId}`,
590
+ 'DELETE',
591
+ );
592
+ }
593
+
594
+ /**
595
+ * Click a card action button on a message. Acting principal is the caller.
596
+ * @param {string} messageId
597
+ * @param {Object} params
598
+ * @param {string} params.actionId
599
+ * @param {string} [params.value]
600
+ * @returns {Promise<Object>}
601
+ */
602
+ async clickAction(messageId, { actionId, value } = {}) {
603
+ this.sdk.validateParams(
604
+ { messageId, actionId, value },
605
+ {
606
+ messageId: { type: 'string', required: true },
607
+ actionId: { type: 'string', required: true },
608
+ value: { type: 'string', required: false },
609
+ },
610
+ );
611
+
612
+ const body = { actionId };
613
+ if (value !== undefined) body.value = value;
614
+
615
+ return this.sdk._fetch(`/chat/messages/${messageId}/actions`, 'POST', {
616
+ body,
617
+ });
618
+ }
619
+
620
+ /**
621
+ * Report a message.
622
+ * @param {string} id
623
+ * @param {Object} params
624
+ * @param {string} params.reason
625
+ * @returns {Promise<Object>}
626
+ */
627
+ async reportMessage(id, { reason } = {}) {
628
+ this.sdk.validateParams(
629
+ { id, reason },
630
+ {
631
+ id: { type: 'string', required: true },
632
+ reason: { type: 'string', required: true },
633
+ },
634
+ );
635
+ return this.sdk._fetch(`/chat/messages/${id}/report`, 'POST', {
636
+ body: { reason },
637
+ });
638
+ }
639
+
640
+ /**
641
+ * Admin: list all channels (optional search/kind filter).
642
+ * @param {Object} [params]
643
+ * @param {string} [params.q]
644
+ * @param {'public'|'private'|'dm'|'group_dm'|'record'|'meeting'} [params.kind]
645
+ * @returns {Promise<Object>}
646
+ */
647
+ async adminListChannels({ q, kind } = {}) {
648
+ this.sdk.validateParams(
649
+ { q, kind },
650
+ {
651
+ q: { type: 'string', required: false },
652
+ kind: { type: 'string', required: false },
653
+ },
654
+ );
655
+
656
+ const query = {};
657
+ if (q !== undefined) query.q = q;
658
+ if (kind !== undefined) query.kind = kind;
659
+
660
+ return this.sdk._fetch('/chat/admin/channels', 'GET', { query });
661
+ }
662
+
663
+ /**
664
+ * Admin: get a channel by id (no membership required).
665
+ * @param {string} id
666
+ * @returns {Promise<Object>}
667
+ */
668
+ async adminGetChannel(id) {
669
+ this.sdk.validateParams({ id }, { id: { type: 'string', required: true } });
670
+ return this.sdk._fetch(`/chat/admin/channels/${id}`, 'GET');
671
+ }
672
+
673
+ /**
674
+ * Admin: export a channel (messages + members).
675
+ * @param {string} id
676
+ * @returns {Promise<Object>}
677
+ */
678
+ async adminExportChannel(id) {
679
+ this.sdk.validateParams({ id }, { id: { type: 'string', required: true } });
680
+ return this.sdk._fetch(`/chat/admin/channels/${id}/export`, 'GET');
681
+ }
682
+
683
+ /**
684
+ * Admin: list message reports.
685
+ * @param {Object} [params]
686
+ * @param {string} [params.status]
687
+ * @returns {Promise<Object>}
688
+ */
689
+ async adminListReports({ status } = {}) {
690
+ this.sdk.validateParams(
691
+ { status },
692
+ { status: { type: 'string', required: false } },
693
+ );
694
+
695
+ const query = {};
696
+ if (status !== undefined) query.status = status;
697
+
698
+ return this.sdk._fetch('/chat/admin/reports', 'GET', { query });
699
+ }
700
+
701
+ /**
702
+ * Admin: review a message report (set status).
703
+ * @param {string} id
704
+ * @param {Object} params
705
+ * @param {string} params.status
706
+ * @returns {Promise<Object>}
707
+ */
708
+ async adminReviewReport(id, { status } = {}) {
709
+ this.sdk.validateParams(
710
+ { id, status },
711
+ {
712
+ id: { type: 'string', required: true },
713
+ status: { type: 'string', required: true },
714
+ },
715
+ );
716
+ return this.sdk._fetch(`/chat/admin/reports/${id}`, 'POST', {
717
+ body: { status },
718
+ });
719
+ }
720
+
721
+ /**
722
+ * Admin: delete a message (moderation).
723
+ * @param {string} id
724
+ * @returns {Promise<Object>}
725
+ */
726
+ async adminDeleteMessage(id) {
727
+ this.sdk.validateParams({ id }, { id: { type: 'string', required: true } });
728
+ return this.sdk._fetch(`/chat/admin/messages/${id}`, 'DELETE');
729
+ }
730
+
731
+ /**
732
+ * Admin: audit log of review actions.
733
+ * @returns {Promise<Object>}
734
+ */
735
+ async adminAudit() {
736
+ return this.sdk._fetch('/chat/admin/audit', 'GET');
737
+ }
738
+
739
+ /**
740
+ * Get (find-or-create) the record-feed channel for a related record.
741
+ * @param {string} relatedId
742
+ * @param {Object} params
743
+ * @param {string} params.recordTypeId
744
+ * @returns {Promise<Object>} Record-kind channel
745
+ */
746
+ async getRecordChannel(relatedId, { recordTypeId } = {}) {
747
+ this.sdk.validateParams(
748
+ { relatedId, recordTypeId },
749
+ {
750
+ relatedId: { type: 'string', required: true },
751
+ recordTypeId: { type: 'string', required: true },
752
+ },
753
+ );
754
+ return this.sdk._fetch(`/chat/records/${relatedId}`, 'GET', {
755
+ query: { recordTypeId },
756
+ });
757
+ }
758
+
759
+ /**
760
+ * Post a message to a record-feed channel (find-or-create).
761
+ * @param {string} relatedId
762
+ * @param {Object} params
763
+ * @param {Object} params.message - ProseMirror JSON (required)
764
+ * @param {string} params.recordTypeId
765
+ * @returns {Promise<Object>} Created message
766
+ */
767
+ async postToRecord(relatedId, { message, recordTypeId } = {}) {
768
+ this.sdk.validateParams(
769
+ { relatedId, message, recordTypeId },
770
+ {
771
+ relatedId: { type: 'string', required: true },
772
+ message: { type: 'object', required: true },
773
+ recordTypeId: { type: 'string', required: true },
774
+ },
775
+ );
776
+ return this.sdk._fetch(`/chat/records/${relatedId}/messages`, 'POST', {
777
+ body: { message, recordTypeId },
778
+ });
779
+ }
780
+
781
+ /**
782
+ * Get the Meet/Call room for a channel.
783
+ * @param {string} channelId
784
+ * @returns {Promise<Object>}
785
+ */
786
+ async getChannelMeet(channelId) {
787
+ this.sdk.validateParams(
788
+ { channelId },
789
+ { channelId: { type: 'string', required: true } },
790
+ );
791
+ return this.sdk._fetch(`/chat/channels/${channelId}/meet`, 'GET');
792
+ }
793
+
794
+ /**
795
+ * Get the VAPID public key for Web Push subscription.
796
+ * @returns {Promise<Object>}
797
+ */
798
+ async getVapidPublicKey() {
799
+ return this.sdk._fetch('/chat/push/vapidPublicKey', 'GET');
800
+ }
801
+
802
+ /**
803
+ * Register a push device (web push subscription or native FCM/APNs token).
804
+ * @param {Object} params
805
+ * @param {'webpush'|'fcm'|'apns'} params.kind
806
+ * @param {Object} params.subscription - Push subscription / token JSON
807
+ * @returns {Promise<Object>}
808
+ */
809
+ async registerPushDevice({ kind, subscription } = {}) {
810
+ this.sdk.validateParams(
811
+ { kind, subscription },
812
+ {
813
+ kind: { type: 'string', required: true },
814
+ subscription: { type: 'object', required: true },
815
+ },
816
+ );
817
+ return this.sdk._fetch('/chat/push/devices', 'POST', {
818
+ body: { kind, subscription },
819
+ });
820
+ }
821
+
822
+ /**
823
+ * Unregister a push device.
824
+ * @param {string} id
825
+ * @returns {Promise<Object>}
826
+ */
827
+ async unregisterPushDevice(id) {
828
+ this.sdk.validateParams({ id }, { id: { type: 'string', required: true } });
829
+ return this.sdk._fetch(`/chat/push/devices/${id}`, 'DELETE');
830
+ }
831
+
832
+ /**
833
+ * Set the caller's notifyLevel on a channel (all | mentions | mute).
834
+ * @param {string} channelId
835
+ * @param {Object} params
836
+ * @param {'all'|'mentions'|'mute'} params.notifyLevel
837
+ * @returns {Promise<Object>}
838
+ */
839
+ async setNotifyLevel(channelId, { notifyLevel } = {}) {
840
+ this.sdk.validateParams(
841
+ { channelId, notifyLevel },
842
+ {
843
+ channelId: { type: 'string', required: true },
844
+ notifyLevel: { type: 'string', required: true },
845
+ },
846
+ );
847
+ return this.sdk._fetch(`/chat/channels/${channelId}/notify`, 'PATCH', {
848
+ body: { notifyLevel },
849
+ });
850
+ }
851
+ }
package/services/inbox.js CHANGED
@@ -15,15 +15,53 @@ export class InboxService {
15
15
  * @param {string} [params.before] - UTC cursor 'YYYY-MM-DD HH:mm:ss';
16
16
  * only items strictly older than this are returned.
17
17
  * @param {boolean} [params.unreadOnly] - When true, only unread items.
18
+ * @param {string} [params.startDate] - Inclusive range start `YYYY-MM-DD`.
19
+ * @param {string} [params.endDate] - Inclusive range end `YYYY-MM-DD`.
20
+ * @param {string} [params.q] - Search numbers, names, previews.
21
+ * @param {string} [params.direction] - `inbound` or `outbound`.
22
+ * @param {boolean} [params.missed] - Missed inbound calls only.
23
+ * @param {boolean} [params.hasRecording] - Calls/meetings with a recording.
24
+ * @param {boolean} [params.hasTranscription] - Calls/meetings/voicemail
25
+ * with a transcript.
18
26
  * @returns {Promise<{items: Object[], nextCursor: string|null}>}
19
27
  */
20
- async list({ types, limit, before, unreadOnly } = {}) {
28
+ async list({
29
+ types,
30
+ limit,
31
+ before,
32
+ unreadOnly,
33
+ startDate,
34
+ endDate,
35
+ q,
36
+ direction,
37
+ missed,
38
+ hasRecording,
39
+ hasTranscription,
40
+ } = {}) {
21
41
  this.sdk.validateParams(
22
- { limit, before, unreadOnly },
42
+ {
43
+ limit,
44
+ before,
45
+ unreadOnly,
46
+ startDate,
47
+ endDate,
48
+ q,
49
+ direction,
50
+ missed,
51
+ hasRecording,
52
+ hasTranscription,
53
+ },
23
54
  {
24
55
  limit: { type: 'number', required: false },
25
56
  before: { type: 'string', required: false },
26
57
  unreadOnly: { type: 'boolean', required: false },
58
+ startDate: { type: 'string', required: false },
59
+ endDate: { type: 'string', required: false },
60
+ q: { type: 'string', required: false },
61
+ direction: { type: 'string', required: false },
62
+ missed: { type: 'boolean', required: false },
63
+ hasRecording: { type: 'boolean', required: false },
64
+ hasTranscription: { type: 'boolean', required: false },
27
65
  },
28
66
  );
29
67
 
@@ -42,6 +80,15 @@ export class InboxService {
42
80
  if (limit !== undefined) query.limit = limit;
43
81
  if (before !== undefined) query.before = before;
44
82
  if (unreadOnly !== undefined) query.unreadOnly = unreadOnly;
83
+ if (startDate !== undefined) query.startDate = startDate;
84
+ if (endDate !== undefined) query.endDate = endDate;
85
+ if (q !== undefined) query.q = q;
86
+ if (direction !== undefined) query.direction = direction;
87
+ if (missed !== undefined) query.missed = missed;
88
+ if (hasRecording !== undefined) query.hasRecording = hasRecording;
89
+ if (hasTranscription !== undefined) {
90
+ query.hasTranscription = hasTranscription;
91
+ }
45
92
 
46
93
  const params = { query };
47
94
 
@@ -455,4 +455,53 @@ export class EmailMailboxesService {
455
455
  );
456
456
  return result;
457
457
  }
458
+
459
+ async createFolder(mailboxId, { name, parent } = {}) {
460
+ this.sdk.validateParams(
461
+ { mailboxId, name, parent },
462
+ {
463
+ mailboxId: { type: 'string', required: true },
464
+ name: { type: 'string', required: true },
465
+ parent: { type: 'string', required: false },
466
+ },
467
+ );
468
+ const body = { name };
469
+ if (parent) body.parent = parent;
470
+ return this.sdk._fetch(
471
+ `/messaging/email/mailbox/${mailboxId}/folders`,
472
+ 'POST',
473
+ { body },
474
+ );
475
+ }
476
+
477
+ async renameFolder(mailboxId, { from, to } = {}) {
478
+ this.sdk.validateParams(
479
+ { mailboxId, from, to },
480
+ {
481
+ mailboxId: { type: 'string', required: true },
482
+ from: { type: 'string', required: true },
483
+ to: { type: 'string', required: true },
484
+ },
485
+ );
486
+ return this.sdk._fetch(
487
+ `/messaging/email/mailbox/${mailboxId}/folders`,
488
+ 'PUT',
489
+ { body: { from, to } },
490
+ );
491
+ }
492
+
493
+ async deleteFolder(mailboxId, { name } = {}) {
494
+ this.sdk.validateParams(
495
+ { mailboxId, name },
496
+ {
497
+ mailboxId: { type: 'string', required: true },
498
+ name: { type: 'string', required: true },
499
+ },
500
+ );
501
+ return this.sdk._fetch(
502
+ `/messaging/email/mailbox/${mailboxId}/folders`,
503
+ 'DELETE',
504
+ { query: { name }, body: { name } },
505
+ );
506
+ }
458
507
  }
@@ -11,7 +11,7 @@ export class CCService {
11
11
  * @returns {Promise<Object>} result
12
12
  * @returns {boolean} result.isManager - Whether the caller has queue-manager scope
13
13
  * @returns {string|null} result.workerId - The caller's own worker id, if any
14
- * @returns {Array<Object>} result.queues - Accessible queues [{id, name, slaThreshold}]
14
+ * @returns {Array<Object>} result.queues - Accessible queues [{id, name, slaThreshold, slaTargetPct, timezone}]
15
15
  *
16
16
  * @example
17
17
  * const scope = await sdk.taskRouter.cc.getScope();
@@ -30,7 +30,7 @@ export class CCService {
30
30
  * @param {string[]} [options.queueIds] - Queue ids to scope to (must be a subset of the caller's accessible queues). Omit/empty for full scope.
31
31
  * @returns {Promise<Object>} result
32
32
  * @returns {Object} result.kpis - Aggregate KPIs (inQueueNow, longestWaitSec, myHandledToday, myAvgHandleSecToday, slaTodayPct, slaTargetPct)
33
- * @returns {Array<Object>} result.queues - Per-queue summaries (id, name, waiting, longestWaitSec, agentsAvailable, agentsTotal, slaPct, health)
33
+ * @returns {Array<Object>} result.queues - Per-queue summaries (id, name, waiting, longestWaitSec, agentsAvailable, agentsTotal, slaPct, slaThreshold, slaTargetPct, timezone, health)
34
34
  * @returns {Array<Object>} result.team - Team roster with active tasks
35
35
  *
36
36
  * @example
@@ -150,7 +150,7 @@ export class CCService {
150
150
  *
151
151
  * @param {Object} options - Parameters
152
152
  * @param {string} options.queueId - Queue id to update
153
- * @param {Object} options.weights - `{sentiment, sla, volume, acceptance}` ints summing to 100
153
+ * @param {Object} options.weights - `{sentiment, aht, volume, acceptance}` ints summing to 100
154
154
  * @returns {Promise<Object>} result
155
155
  * @returns {string} result.queueId
156
156
  * @returns {Object} result.rankingWeights - The stored weights
@@ -158,7 +158,7 @@ export class CCService {
158
158
  * @example
159
159
  * await sdk.taskRouter.cc.setQueueRankingWeights({
160
160
  * queueId: 'q1',
161
- * weights: { sentiment: 35, sla: 25, volume: 20, acceptance: 20 },
161
+ * weights: { sentiment: 40, aht: 30, volume: 5, acceptance: 25 },
162
162
  * });
163
163
  */
164
164
  async setQueueRankingWeights(options = {}) {
package/services/video.js CHANGED
@@ -1065,7 +1065,10 @@ export class VideoService {
1065
1065
  },
1066
1066
  );
1067
1067
 
1068
- const result = await this.sdk._fetch(`/video/${roomId}/livePresence`, 'GET');
1068
+ const result = await this.sdk._fetch(
1069
+ `/video/${roomId}/livePresence`,
1070
+ 'GET',
1071
+ );
1069
1072
  return result;
1070
1073
  }
1071
1074
 
@@ -1282,7 +1285,11 @@ export class VideoService {
1282
1285
  },
1283
1286
  );
1284
1287
 
1285
- const result = await this.sdk._fetch(`/video/${roomId}/auto-name`, 'POST', {});
1288
+ const result = await this.sdk._fetch(
1289
+ `/video/${roomId}/auto-name`,
1290
+ 'POST',
1291
+ {},
1292
+ );
1286
1293
  return result;
1287
1294
  }
1288
1295
 
@@ -1431,10 +1438,19 @@ export class VideoService {
1431
1438
  * the meet-hub plan — this file has no existing nested-namespace
1432
1439
  * precedent, so flat matches every other method here.
1433
1440
  *
1441
+ * @param {string} [userId] - Optional target userId (admin viewing another user's room, e.g. Setup -> Users -> Meet). Defaults to the calling user.
1434
1442
  * @returns {Promise<{personalRoom: {id: string, slug: string, url: string|null, dialInPin: string, guestsCanStart: boolean}}>}
1435
1443
  */
1436
- async getPersonalRoom() {
1437
- const result = await this.sdk._fetch('/video/personal-room', 'GET');
1444
+ async getPersonalRoom(userId = null) {
1445
+ const params = { query: {} };
1446
+ if (userId) {
1447
+ this.sdk.validateParams(
1448
+ { userId },
1449
+ { userId: { type: 'string', required: true } },
1450
+ );
1451
+ params.query.userId = userId;
1452
+ }
1453
+ const result = await this.sdk._fetch('/video/personal-room', 'GET', params);
1438
1454
  return result;
1439
1455
  }
1440
1456
 
@@ -1445,9 +1461,11 @@ export class VideoService {
1445
1461
  * @param {Object} [update]
1446
1462
  * @param {string} [update.slug] - New slug (3-32 chars, lowercase/numbers/hyphens, not reserved). 409-equivalent BadRequestError on collision.
1447
1463
  * @param {boolean} [update.guestsCanStart] - Whether guests can start the room without the host present.
1464
+ * @param {string} [update.password] - New static room passcode.
1465
+ * @param {string} [update.userId] - Optional target userId (admin editing another user's room). Defaults to the calling user.
1448
1466
  * @returns {Promise<{personalRoom: {id: string, slug: string, url: string|null, dialInPin: string, guestsCanStart: boolean}}>}
1449
1467
  */
1450
- async updatePersonalRoom({ slug, guestsCanStart, password } = {}) {
1468
+ async updatePersonalRoom({ slug, guestsCanStart, password, userId } = {}) {
1451
1469
  const validationSchema = {};
1452
1470
  if (slug !== undefined) validationSchema.slug = { type: 'string' };
1453
1471
  if (guestsCanStart !== undefined)
@@ -1455,10 +1473,11 @@ export class VideoService {
1455
1473
  // Static room passcode — 4-6 digits (api-enforced); applied to every
1456
1474
  // session the room link mints.
1457
1475
  if (password !== undefined) validationSchema.password = { type: 'string' };
1476
+ if (userId !== undefined) validationSchema.userId = { type: 'string' };
1458
1477
 
1459
1478
  if (Object.keys(validationSchema).length > 0) {
1460
1479
  this.sdk.validateParams(
1461
- { slug, guestsCanStart, password },
1480
+ { slug, guestsCanStart, password, userId },
1462
1481
  validationSchema,
1463
1482
  );
1464
1483
  }
@@ -1467,26 +1486,32 @@ export class VideoService {
1467
1486
  if (slug !== undefined) body.slug = slug;
1468
1487
  if (guestsCanStart !== undefined) body.guestsCanStart = guestsCanStart;
1469
1488
  if (password !== undefined) body.password = password;
1489
+ if (userId !== undefined) body.userId = userId;
1470
1490
 
1471
1491
  const params = { body };
1472
- const result = await this.sdk._fetch(
1473
- '/video/personal-room',
1474
- 'PUT',
1475
- params,
1476
- );
1492
+ const result = await this.sdk._fetch('/video/personal-room', 'PUT', params);
1477
1493
  return result;
1478
1494
  }
1479
1495
 
1480
1496
  /**
1481
1497
  * Regenerate the dial-in PIN for the calling user's personal meeting room.
1482
1498
  *
1499
+ * @param {string} [userId] - Optional target userId (admin action). Defaults to the calling user.
1483
1500
  * @returns {Promise<{personalRoom: {id: string, dialInPin: string}}>}
1484
1501
  */
1485
- async regeneratePersonalRoomPin() {
1502
+ async regeneratePersonalRoomPin(userId = null) {
1503
+ const body = {};
1504
+ if (userId) {
1505
+ this.sdk.validateParams(
1506
+ { userId },
1507
+ { userId: { type: 'string', required: true } },
1508
+ );
1509
+ body.userId = userId;
1510
+ }
1486
1511
  const result = await this.sdk._fetch(
1487
1512
  '/video/personal-room/regenerate-pin',
1488
1513
  'POST',
1489
- {},
1514
+ { body },
1490
1515
  );
1491
1516
  return result;
1492
1517
  }
@@ -1495,17 +1520,23 @@ export class VideoService {
1495
1520
  * Live availability dry-run for a personal-room slug (settings editor).
1496
1521
  *
1497
1522
  * @param {string} slug - Candidate slug.
1523
+ * @param {string} [userId] - Optional target userId (admin action). Defaults to the calling user.
1498
1524
  * @returns {Promise<{slug: string, available: boolean, reason?: 'invalid'|'taken'}>}
1499
1525
  */
1500
- async checkPersonalRoomSlug(slug) {
1526
+ async checkPersonalRoomSlug(slug, userId = null) {
1501
1527
  this.sdk.validateParams(
1502
- { slug },
1503
- { slug: { type: 'string', required: true } },
1528
+ { slug, userId },
1529
+ {
1530
+ slug: { type: 'string', required: true },
1531
+ userId: { type: 'string', required: false },
1532
+ },
1504
1533
  );
1534
+ const query = { slug };
1535
+ if (userId) query.userId = userId;
1505
1536
  const result = await this.sdk._fetch(
1506
- `/video/personal-room/slug-available?slug=${encodeURIComponent(slug)}`,
1537
+ '/video/personal-room/slug-available',
1507
1538
  'GET',
1508
- {},
1539
+ { query },
1509
1540
  );
1510
1541
  return result;
1511
1542
  }
@@ -1515,13 +1546,22 @@ export class VideoService {
1515
1546
  * meeting room (a separate secret from the dial-in PIN). Sessions minted
1516
1547
  * after this use the new value.
1517
1548
  *
1549
+ * @param {string} [userId] - Optional target userId (admin action). Defaults to the calling user.
1518
1550
  * @returns {Promise<{personalRoom: {id: string, password: string}}>}
1519
1551
  */
1520
- async regeneratePersonalRoomPassword() {
1552
+ async regeneratePersonalRoomPassword(userId = null) {
1553
+ const body = {};
1554
+ if (userId) {
1555
+ this.sdk.validateParams(
1556
+ { userId },
1557
+ { userId: { type: 'string', required: true } },
1558
+ );
1559
+ body.userId = userId;
1560
+ }
1521
1561
  const result = await this.sdk._fetch(
1522
1562
  '/video/personal-room/regenerate-password',
1523
1563
  'POST',
1524
- {},
1564
+ { body },
1525
1565
  );
1526
1566
  return result;
1527
1567
  }
package/services/voice.js CHANGED
@@ -22,6 +22,34 @@ export class VoiceService {
22
22
  return result;
23
23
  }
24
24
 
25
+ async transcription({
26
+ cdrId,
27
+ callId,
28
+ action = 'start',
29
+ direction = 'sendrecv',
30
+ }) {
31
+ this.sdk.validateParams(
32
+ { callId, cdrId, action, direction },
33
+ {
34
+ cdrId: { type: 'string', required: false },
35
+ callId: { type: 'string', required: false },
36
+ action: { type: 'string', required: false },
37
+ direction: { type: 'string', required: false },
38
+ },
39
+ );
40
+
41
+ const params = {
42
+ body: { callId, cdrId, action, direction },
43
+ };
44
+
45
+ const result = await this.sdk._fetch(
46
+ `/voice/transcription/`,
47
+ 'POST',
48
+ params,
49
+ );
50
+ return result;
51
+ }
52
+
25
53
  async call({ to, from, destination, app, timeout, customHeaders, statusWebhook }) {
26
54
  this.sdk.validateParams(
27
55
  { to, from, destination, app, timeout, customHeaders, statusWebhook },