@unboundcx/sdk 2.8.6 → 2.8.7

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.
@@ -139,7 +139,11 @@ export class EngagementMetricsService {
139
139
  * @param {string[]} [options.userIds] - Array of user IDs to filter by
140
140
  * @returns {Promise<Object>} All metrics
141
141
  */
142
- async getDashboardMetrics({ queueIds = [], statuses = [], userIds = [] } = {}) {
142
+ async getDashboardMetrics({
143
+ queueIds = [],
144
+ statuses = [],
145
+ userIds = [],
146
+ } = {}) {
143
147
  return this.getMetrics({
144
148
  queueIds,
145
149
  statuses,
@@ -150,4 +154,4 @@ export class EngagementMetricsService {
150
154
  includeAgentPerformance: true,
151
155
  });
152
156
  }
153
- }
157
+ }
@@ -45,9 +45,13 @@ export class ObjectsService {
45
45
  }
46
46
  } else if (typeof arg1 === 'object') {
47
47
  id = arg1.id;
48
- query = { ...arg1 };
49
- if (query.id) {
50
- delete query.id;
48
+ if (arg1.query) {
49
+ query = { ...arg1.query };
50
+ } else {
51
+ query = { ...arg1 };
52
+ if (query.id) {
53
+ delete query.id;
54
+ }
51
55
  }
52
56
  }
53
57
 
@@ -63,7 +67,9 @@ export class ObjectsService {
63
67
  );
64
68
 
65
69
  const params = { query };
70
+
66
71
  const result = await this.sdk._fetch(`/object/${id}`, 'GET', params);
72
+ // console.log(`sdk.objects.byId :: params :: `, params, result);
67
73
  return result;
68
74
  }
69
75
 
@@ -97,6 +103,7 @@ export class ObjectsService {
97
103
  previousId = null,
98
104
  orderByDirection = 'DESC',
99
105
  expandDetails = false,
106
+ meta = {},
100
107
  } = args[0];
101
108
 
102
109
  this.sdk.validateParams(
@@ -109,6 +116,7 @@ export class ObjectsService {
109
116
  previousId,
110
117
  orderByDirection,
111
118
  expandDetails,
119
+ meta,
112
120
  },
113
121
  {
114
122
  object: { type: 'string', required: true },
@@ -119,6 +127,7 @@ export class ObjectsService {
119
127
  previousId: { type: 'string', required: false },
120
128
  orderByDirection: { type: 'string', required: false },
121
129
  expandDetails: { type: 'boolean', required: false },
130
+ meta: { type: 'object', required: false },
122
131
  },
123
132
  );
124
133
 
@@ -110,10 +110,21 @@ export class PhoneNumbersService {
110
110
  voiceAppMetaData,
111
111
  voiceRecordTypeId,
112
112
  messagingRecordTypeId,
113
+ recordCalls,
113
114
  },
114
115
  ) {
115
116
  this.sdk.validateParams(
116
- { id },
117
+ {
118
+ id,
119
+ messagingWebHookUrl,
120
+ voiceWebHookUrl,
121
+ voiceAppExternalUrl,
122
+ voiceAppExternalMethod,
123
+ voiceApp,
124
+ voiceRecordTypeId,
125
+ messagingRecordTypeId,
126
+ recordCalls,
127
+ },
117
128
  {
118
129
  id: { type: 'string', required: true },
119
130
  name: { type: 'string', required: false },
@@ -122,9 +133,9 @@ export class PhoneNumbersService {
122
133
  voiceAppExternalUrl: { type: 'string', required: false },
123
134
  voiceAppExternalMethod: { type: 'string', required: false },
124
135
  voiceApp: { type: 'string', required: false },
125
- voiceAppMetaData: { type: 'object', required: false },
126
136
  voiceRecordTypeId: { type: 'string', required: false },
127
137
  messagingRecordTypeId: { type: 'string', required: false },
138
+ recordCalls: { type: 'boolean', required: false },
128
139
  },
129
140
  );
130
141
 
@@ -142,6 +153,7 @@ export class PhoneNumbersService {
142
153
  if (voiceRecordTypeId) updateData.voiceRecordTypeId = voiceRecordTypeId;
143
154
  if (messagingRecordTypeId)
144
155
  updateData.messagingRecordTypeId = messagingRecordTypeId;
156
+ if (recordCalls !== undefined) updateData.recordCalls = recordCalls;
145
157
 
146
158
  const params = {
147
159
  body: updateData,
@@ -187,10 +199,83 @@ export class PhoneNumbersService {
187
199
  return result;
188
200
  }
189
201
 
190
- async getRoutingOptions() {
202
+ /**
203
+ * Get routing options for phone numbers or extensions
204
+ *
205
+ * Supports multiple query modes:
206
+ * 1. Get list of valid app types with metadata (appType: 'list')
207
+ * 2. Get all application types (default)
208
+ * 3. Get details for a specific application type
209
+ * 4. Get versions for a specific workflow
210
+ *
211
+ * @param {Object} [options] - Query options
212
+ * @param {string} [options.mode] - Context mode: 'phoneNumbers' (default) or 'extensions'
213
+ * @param {string} [options.type] - Filter by routing type: 'voice' or 'messaging'
214
+ * @param {string} [options.appType] - 'list' for metadata, or specific app type: 'workflows', 'extensions', 'voiceApps', 'users'
215
+ * @param {string} [options.workflowId] - Get versions for a specific workflow ID
216
+ * @param {string} [options.search] - Search/filter by name
217
+ * @returns {Promise<Object>} Routing options based on query parameters
218
+ * @example
219
+ * // Get metadata about available app types
220
+ * const metadata = await sdk.phoneNumbers.getRoutingOptions({ appType: 'list' });
221
+ * // Returns: { types: [{ key: 'voiceApps', label: 'Voice Applications', description: '...', ... }] }
222
+ *
223
+ * // Get all application types for phone numbers (default)
224
+ * const all = await sdk.phoneNumbers.getRoutingOptions();
225
+ * // Returns: { voiceApps: [...], workflows: [...], extensions: [...], webhooks: [...] }
226
+ *
227
+ * // Get routing options for extensions
228
+ * const extensionOptions = await sdk.phoneNumbers.getRoutingOptions({ mode: 'extensions' });
229
+ * // Returns: { voiceApps: [...], workflows: [...], users: [...] }
230
+ *
231
+ * // Get only voice routing options
232
+ * const voice = await sdk.phoneNumbers.getRoutingOptions({ type: 'voice' });
233
+ *
234
+ * // Get all workflows with their versions
235
+ * const workflows = await sdk.phoneNumbers.getRoutingOptions({ appType: 'workflows' });
236
+ *
237
+ * // Get all users (for extension routing)
238
+ * const users = await sdk.phoneNumbers.getRoutingOptions({ mode: 'extensions', appType: 'users' });
239
+ *
240
+ * // Get versions for a specific workflow
241
+ * const versions = await sdk.phoneNumbers.getRoutingOptions({ workflowId: 'wf_123' });
242
+ *
243
+ * // Search workflows by name
244
+ * const filtered = await sdk.phoneNumbers.getRoutingOptions({ appType: 'workflows', search: 'customer' });
245
+ */
246
+ async getRoutingOptions({ mode, type, appType, workflowId, search } = {}) {
247
+ const validationSchema = {};
248
+ const args = arguments[0] || {};
249
+
250
+ if ('mode' in args)
251
+ validationSchema.mode = { type: 'string', required: false };
252
+ if ('type' in args)
253
+ validationSchema.type = { type: 'string', required: false };
254
+ if ('appType' in args)
255
+ validationSchema.appType = { type: 'string', required: false };
256
+ if ('workflowId' in args)
257
+ validationSchema.workflowId = { type: 'string', required: false };
258
+ if ('search' in args)
259
+ validationSchema.search = { type: 'string', required: false };
260
+
261
+ if (Object.keys(validationSchema).length > 0) {
262
+ this.sdk.validateParams(args, validationSchema);
263
+ }
264
+
265
+ const params = {
266
+ query: {
267
+ mode,
268
+ type,
269
+ appType,
270
+ workflowId,
271
+ search,
272
+ },
273
+ };
274
+
191
275
  const result = await this.sdk._fetch(
192
276
  '/phoneNumbers/routing-options',
193
277
  'GET',
278
+ params,
194
279
  );
195
280
  return result;
196
281
  }
@@ -3,23 +3,45 @@ export class SipEndpointsService {
3
3
  this.sdk = sdk;
4
4
  }
5
5
 
6
- async create({ recordTypeId, type, userId, name }) {
6
+ /**
7
+ * Create a new SIP endpoint
8
+ * @param {Object} options - The endpoint configuration
9
+ * @param {string} options.recordTypeId - Record type ID for permissions
10
+ * @param {string} options.userId - User ID to associate with this endpoint
11
+ * @param {string} options.type - Endpoint type: 'webRtc' or 'ipPhone'
12
+ * @param {string} options.name - Endpoint name
13
+ * @param {string} options.macAddress - MAC address for ipPhone type
14
+ * @param {Object} options - Additional provisioning fields (timezone, vlanId, etc.)
15
+ * @returns {Promise<Object>} Created endpoint
16
+ */
17
+ async create(options) {
18
+ const {
19
+ recordTypeId,
20
+ userId,
21
+ type,
22
+ name,
23
+ macAddress,
24
+ useSecureCalling,
25
+ ...provisioningFields
26
+ } = options;
27
+
7
28
  this.sdk.validateParams(
8
- { recordTypeId, type, userId, name },
29
+ { type, useSecureCalling },
9
30
  {
10
- recordTypeId: { type: 'string', required: false },
11
31
  type: { type: 'string', required: true },
12
- userId: { type: 'string', required: false },
13
- name: { type: 'string', required: false },
32
+ useSecureCalling: { type: 'boolean', required: false },
14
33
  },
15
34
  );
16
35
 
17
36
  const params = {
18
37
  body: {
19
38
  recordTypeId,
20
- type,
21
39
  userId,
40
+ type,
41
+ useSecureCalling,
22
42
  name,
43
+ macAddress,
44
+ ...provisioningFields, // Include all provisioning fields
23
45
  },
24
46
  };
25
47
 
@@ -27,23 +49,53 @@ export class SipEndpointsService {
27
49
  return result;
28
50
  }
29
51
 
52
+ /**
53
+ * Get the authenticated user's WebRTC endpoint details
54
+ * @returns {Promise<Object>} WebRTC endpoint configuration
55
+ */
30
56
  async getWebRtcDetails() {
31
- const params = {};
32
- const result = await this.sdk._fetch('/sipEndpoints', 'GET', params, true);
57
+ const result = await this.sdk._fetch('/sipEndpoints/webrtc', 'GET');
33
58
  return result;
34
59
  }
35
60
 
36
- async getUsersWebRtc() {
37
- const result = await this.sdk._fetch('/sipEndpoints/users/webrtc', 'GET');
38
- return result;
39
- }
61
+ /**
62
+ * Update a SIP endpoint
63
+ * @param {string} endpointId - The endpoint ID
64
+ * @param {Object} options - The fields to update
65
+ * @param {string} options.name - Endpoint name
66
+ * @param {string} options.userId - User ID to associate with this endpoint
67
+ * * @param {string} options.useSecureCalling - provision with TLS / secure calling
68
+ * @param {string} options.macAddress - MAC address
69
+ * @param {boolean} options.useIceAccelerator - Enable/disable ICE accelerator
70
+ * @param {Object} options - Additional provisioning fields (timezone, vlanId, etc.)
71
+ * @returns {Promise<Object>} Updated endpoint
72
+ */
73
+ async update(endpointId, options) {
74
+ this.sdk.validateParams(
75
+ { endpointId },
76
+ {
77
+ endpointId: { type: 'string', required: true },
78
+ },
79
+ );
40
80
 
41
- async list() {
42
- const result = await this.sdk._fetch('/sipEndpoints/list', 'GET');
81
+ const params = {
82
+ body: { ...options }, // Pass all options through
83
+ };
84
+
85
+ const result = await this.sdk._fetch(
86
+ `/sipEndpoints/${endpointId}`,
87
+ 'PUT',
88
+ params,
89
+ );
43
90
  return result;
44
91
  }
45
92
 
46
- async get(endpointId) {
93
+ /**
94
+ * Delete a SIP endpoint
95
+ * @param {string} endpointId - The endpoint ID
96
+ * @returns {Promise<Object>} Deletion result
97
+ */
98
+ async delete(endpointId) {
47
99
  this.sdk.validateParams(
48
100
  { endpointId },
49
101
  {
@@ -51,39 +103,59 @@ export class SipEndpointsService {
51
103
  },
52
104
  );
53
105
 
54
- const result = await this.sdk._fetch(`/sipEndpoints/${endpointId}`, 'GET');
106
+ const result = await this.sdk._fetch(
107
+ `/sipEndpoints/${endpointId}`,
108
+ 'DELETE',
109
+ );
55
110
  return result;
56
111
  }
57
112
 
58
- async update(endpointId, { displayName, description, enabled }) {
113
+ /**
114
+ * Reboot a SIP endpoint (forces re-registration)
115
+ * @param {string} endpointId - The endpoint ID
116
+ * @returns {Promise<Object>} Reboot result
117
+ */
118
+ async reboot(endpointId) {
59
119
  this.sdk.validateParams(
60
120
  { endpointId },
61
121
  {
62
122
  endpointId: { type: 'string', required: true },
63
- displayName: { type: 'string', required: false },
64
- description: { type: 'string', required: false },
65
- enabled: { type: 'boolean', required: false },
66
123
  },
67
124
  );
68
125
 
69
- const updateData = {};
70
- if (displayName) updateData.displayName = displayName;
71
- if (description) updateData.description = description;
72
- if (enabled !== undefined) updateData.enabled = enabled;
126
+ const result = await this.sdk._fetch(
127
+ `/sipEndpoints/${endpointId}/reboot`,
128
+ 'POST',
129
+ );
130
+ return result;
131
+ }
73
132
 
74
- const params = {
75
- body: updateData,
76
- };
133
+ /**
134
+ * Change the access secret for a SIP endpoint
135
+ * @param {string} endpointId - The endpoint ID
136
+ * @returns {Promise<Object>} New endpoint credentials
137
+ */
138
+ async changeAccessSecret(endpointId) {
139
+ this.sdk.validateParams(
140
+ { endpointId },
141
+ {
142
+ endpointId: { type: 'string', required: true },
143
+ },
144
+ );
77
145
 
78
146
  const result = await this.sdk._fetch(
79
- `/sipEndpoints/${endpointId}`,
80
- 'PUT',
81
- params,
147
+ `/sipEndpoints/${endpointId}/secret`,
148
+ 'POST',
82
149
  );
83
150
  return result;
84
151
  }
85
152
 
86
- async delete(endpointId) {
153
+ /**
154
+ * Change the provisioning secret for a SIP endpoint
155
+ * @param {string} endpointId - The endpoint ID
156
+ * @returns {Promise<Object>} New endpoint credentials
157
+ */
158
+ async changeProvisioningSecret(endpointId) {
87
159
  this.sdk.validateParams(
88
160
  { endpointId },
89
161
  {
@@ -92,8 +164,8 @@ export class SipEndpointsService {
92
164
  );
93
165
 
94
166
  const result = await this.sdk._fetch(
95
- `/sipEndpoints/${endpointId}`,
96
- 'DELETE',
167
+ `/sipEndpoints/${endpointId}/secret/provisioning`,
168
+ 'POST',
97
169
  );
98
170
  return result;
99
171
  }
@@ -213,8 +213,25 @@ export class StorageService {
213
213
  formFields,
214
214
  endpoint = '/storage/upload',
215
215
  method = 'POST',
216
+ onProgress = null,
217
+ skipClamscan = false,
216
218
  ) {
217
219
  const isNode = typeof window === 'undefined';
220
+
221
+ // In browser with progress callback: Use XMLHttpRequest
222
+ if (!isNode && onProgress && typeof onProgress === 'function') {
223
+ return this._performUploadWithProgress(
224
+ file,
225
+ fileName,
226
+ formFields,
227
+ endpoint,
228
+ method,
229
+ onProgress,
230
+ skipClamscan,
231
+ );
232
+ }
233
+
234
+ // Default behavior: Use fetch via sdk._fetch
218
235
  let formData, headers;
219
236
 
220
237
  if (isNode) {
@@ -227,6 +244,15 @@ export class StorageService {
227
244
  headers = result.headers;
228
245
  }
229
246
 
247
+ if (process?.env?.AUTH_V3_TOKEN_TYPE_OVERRIDE) {
248
+ headers['x-token-type-override'] =
249
+ process.env.AUTH_V3_TOKEN_TYPE_OVERRIDE;
250
+ }
251
+
252
+ if (skipClamscan && process?.env?.CLAMSCAN_OVERRIDE_KEY) {
253
+ headers['x-clamscan-override-key'] = process.env.CLAMSCAN_OVERRIDE_KEY;
254
+ }
255
+
230
256
  const params = {
231
257
  body: formData,
232
258
  headers,
@@ -235,6 +261,123 @@ export class StorageService {
235
261
  return await this.sdk._fetch(endpoint, method, params, true);
236
262
  }
237
263
 
264
+ // Upload with progress tracking using XMLHttpRequest
265
+ async _performUploadWithProgress(
266
+ file,
267
+ fileName,
268
+ formFields,
269
+ endpoint,
270
+ method,
271
+ onProgress,
272
+ skipClamscan = false,
273
+ ) {
274
+ const { formData } = this._createBrowserFormData(
275
+ file,
276
+ fileName,
277
+ formFields,
278
+ );
279
+
280
+ return new Promise((resolve, reject) => {
281
+ const xhr = new XMLHttpRequest();
282
+
283
+ const startTime = Date.now();
284
+
285
+ // Progress tracking
286
+ xhr.upload.onprogress = (event) => {
287
+ if (event.lengthComputable) {
288
+ const percentComplete = (event.loaded / event.total) * 100;
289
+ const elapsed = (Date.now() - startTime) / 1000; // seconds
290
+ const speed = event.loaded / elapsed; // bytes per second
291
+
292
+ onProgress({
293
+ loaded: event.loaded,
294
+ total: event.total,
295
+ percentage: percentComplete,
296
+ speed: speed, // bytes/sec
297
+ });
298
+ }
299
+ };
300
+
301
+ xhr.onload = () => {
302
+ if (xhr.status >= 200 && xhr.status < 300) {
303
+ try {
304
+ const response = JSON.parse(xhr.responseText);
305
+ resolve(response);
306
+ } catch (e) {
307
+ reject(new Error('Invalid JSON response'));
308
+ }
309
+ } else {
310
+ try {
311
+ const errorResponse = JSON.parse(xhr.responseText);
312
+ reject(errorResponse);
313
+ } catch (e) {
314
+ reject(new Error(`Upload failed with status ${xhr.status}`));
315
+ }
316
+ }
317
+ };
318
+
319
+ xhr.onerror = () => reject(new Error('Network error during upload'));
320
+ xhr.onabort = () => reject(new Error('Upload aborted'));
321
+
322
+ // Build URL with auth headers
323
+ const url = `${this.sdk.fullUrl}${endpoint}`;
324
+ xhr.open(method, url, true);
325
+
326
+ // IMPORTANT: Include credentials (cookies) for authentication
327
+ xhr.withCredentials = true;
328
+
329
+ // Add auth headers
330
+ if (this.sdk.token) {
331
+ xhr.setRequestHeader('Authorization', `Bearer ${this.sdk.token}`);
332
+ }
333
+ if (this.sdk.fwRequestId) {
334
+ xhr.setRequestHeader('x-request-id-fw', this.sdk.fwRequestId);
335
+ }
336
+ if (this.sdk.callId) {
337
+ xhr.setRequestHeader('x-call-id', this.sdk.callId);
338
+ }
339
+
340
+ // Add environment variable override headers
341
+ if (process?.env?.AUTH_V3_TOKEN_TYPE_OVERRIDE) {
342
+ xhr.setRequestHeader(
343
+ 'x-token-type-override',
344
+ process.env.AUTH_V3_TOKEN_TYPE_OVERRIDE,
345
+ );
346
+ }
347
+ if (skipClamscan && process?.env?.CLAMSCAN_OVERRIDE_KEY) {
348
+ xhr.setRequestHeader(
349
+ 'x-clamscan-override-key',
350
+ process.env.CLAMSCAN_OVERRIDE_KEY,
351
+ );
352
+ }
353
+
354
+ xhr.send(formData);
355
+ });
356
+ }
357
+ /*
358
+
359
+
360
+ Response:
361
+ {
362
+ "uploaded": [
363
+ {
364
+ "id": "017d0120251229hvdxjod4486582468133095",
365
+ "fileName": "sip-messages-20251223T195443.txt",
366
+ "fileSize": 18979,
367
+ "url": "https://masterc.api.dev-d01.app1svc.com/storage/017d0120251229hvdxjod4486582468133095.txt",
368
+ "mimeType": "text/plain",
369
+ "s3Regions": [
370
+ "d01",
371
+ "d03"
372
+ ],
373
+ "isPublic": false
374
+ }
375
+ ],
376
+ "viruses": [],
377
+ "errors": []
378
+ }
379
+
380
+ */
238
381
  async upload({
239
382
  classification = 'generic',
240
383
  folder,
@@ -246,6 +389,8 @@ export class StorageService {
246
389
  relatedId,
247
390
  createAccessKey = false,
248
391
  accessKeyExpiresIn,
392
+ onProgress,
393
+ _options,
249
394
  }) {
250
395
  this.sdk.validateParams(
251
396
  {
@@ -270,7 +415,7 @@ export class StorageService {
270
415
  expireAfter: { type: 'string', required: false },
271
416
  relatedId: { type: 'string', required: false },
272
417
  createAccessKey: { type: 'boolean', required: false },
273
- accessKeyExpiresIn: { type: 'string', required: false },
418
+ accessKeyExpiresIn: { type: 'number', required: false },
274
419
  },
275
420
  );
276
421
 
@@ -288,11 +433,20 @@ export class StorageService {
288
433
  if (accessKeyExpiresIn)
289
434
  formFields.push(['accessKeyExpiresIn', accessKeyExpiresIn]);
290
435
 
291
- return this._performUpload(file, fileName, formFields);
436
+ return this._performUpload(
437
+ file,
438
+ fileName,
439
+ formFields,
440
+ '/storage/upload',
441
+ 'POST',
442
+ onProgress,
443
+ _options?.skipScan,
444
+ );
292
445
  }
293
446
 
294
447
  async uploadFiles(files, options = {}) {
295
- const { classification, expireAfter, isPublic, metadata } = options;
448
+ const { classification, expireAfter, isPublic, metadata, _options } =
449
+ options;
296
450
 
297
451
  // Validate files parameter
298
452
  if (!files) {
@@ -392,6 +546,10 @@ export class StorageService {
392
546
  if (metadata) formData.append('metadata', JSON.stringify(metadata));
393
547
  }
394
548
 
549
+ if (_options?.skipScan && process?.env?.CLAMSCAN_OVERRIDE_KEY) {
550
+ headers['x-clamscan-override-key'] = process.env.CLAMSCAN_OVERRIDE_KEY;
551
+ }
552
+
395
553
  const params = {
396
554
  body: formData,
397
555
  headers,
@@ -467,13 +625,19 @@ export class StorageService {
467
625
  return result;
468
626
  }
469
627
 
470
- async uploadProfileImage({ file, classification = 'user_images', fileName }) {
628
+ async uploadProfileImage({
629
+ file,
630
+ classification = 'user_images',
631
+ fileName,
632
+ userId,
633
+ }) {
471
634
  this.sdk.validateParams(
472
- { file, classification },
635
+ { file, classification, userId },
473
636
  {
474
637
  file: { type: 'object', required: true },
475
638
  classification: { type: 'string', required: true },
476
639
  fileName: { type: 'string', required: false },
640
+ userId: { type: 'string', required: false },
477
641
  },
478
642
  );
479
643
 
@@ -488,6 +652,7 @@ export class StorageService {
488
652
  // Build form fields exactly like the regular upload but only include classification
489
653
  const formFields = [];
490
654
  formFields.push(['classification', classification]);
655
+ formFields.push(['userId', userId]);
491
656
 
492
657
  // Use the correct profile image endpoint with proper FormData
493
658
  return this._performUpload(
@@ -535,12 +700,14 @@ export class StorageService {
535
700
  }
536
701
 
537
702
  async listFiles(options = {}) {
538
- const { classification, limit, offset, orderBy, orderDirection } = options;
703
+ const { classification, folder, limit, offset, orderBy, orderDirection } =
704
+ options;
539
705
 
540
706
  // Validate optional parameters
541
707
  const validationSchema = {};
542
708
  if ('classification' in options)
543
709
  validationSchema.classification = { type: 'string' };
710
+ if ('folder' in options) validationSchema.folder = { type: 'string' };
544
711
  if ('limit' in options) validationSchema.limit = { type: 'number' };
545
712
  if ('offset' in options) validationSchema.offset = { type: 'number' };
546
713
  if ('orderBy' in options) validationSchema.orderBy = { type: 'string' };
@@ -749,6 +916,7 @@ export class StorageService {
749
916
  country,
750
917
  expireAfter,
751
918
  relatedId,
919
+ _options,
752
920
  },
753
921
  ) {
754
922
  this.sdk.validateParams(
@@ -784,6 +952,8 @@ export class StorageService {
784
952
  formFields,
785
953
  `/storage/${storageId}`,
786
954
  'PUT',
955
+ null,
956
+ _options?.skipScan,
787
957
  );
788
958
  } else {
789
959
  // If only updating metadata, use JSON request