@signalhousellc/sdk 1.0.67 → 1.0.69

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.
Files changed (40) hide show
  1. package/README.md +0 -10
  2. package/package.json +11 -3
  3. package/skills/VENDORED.json +8 -8
  4. package/skills/signalhouse-10dlc/SKILL.md +5 -9
  5. package/skills/signalhouse-10dlc/references/tcr-rejection-causes.md +5 -12
  6. package/skills/signalhouse-advisor/SKILL.md +3 -3
  7. package/skills/signalhouse-numbers/SKILL.md +1 -2
  8. package/skills/signalhouse-setup/SKILL.md +41 -11
  9. package/skills/signalhouse-sms/SKILL.md +4 -4
  10. package/skills/signalhouse-webhooks/SKILL.md +76 -56
  11. package/src/SignalHouseSDK.js +26 -13
  12. package/src/domains/Agents.js +204 -55
  13. package/src/domains/Auth.js +30 -24
  14. package/src/domains/Billing.js +32 -26
  15. package/src/domains/Brands.js +45 -34
  16. package/src/domains/Campaigns.js +106 -47
  17. package/src/domains/Dnc.js +168 -0
  18. package/src/domains/Groups.js +53 -16
  19. package/src/domains/Landings.js +36 -30
  20. package/src/domains/Messages.js +110 -65
  21. package/src/domains/Notifications.js +12 -6
  22. package/src/domains/Numbers.js +58 -52
  23. package/src/domains/Onboarding.js +14 -8
  24. package/src/domains/Shortlinks.js +10 -4
  25. package/src/domains/Subgroups.js +16 -10
  26. package/src/domains/Subscriptions.js +22 -16
  27. package/src/domains/Tickets.js +18 -12
  28. package/src/domains/Users.js +32 -22
  29. package/src/domains/Webhooks.js +45 -13
  30. package/src/domains/voice/Analytics.js +8 -2
  31. package/src/domains/voice/CallLogs.js +14 -8
  32. package/src/domains/voice/Calls.js +14 -8
  33. package/src/domains/voice/GlobalVoiceSettings.js +10 -4
  34. package/src/domains/voice/ProgrammableVoiceProfiles.js +22 -16
  35. package/src/domains/voice/SipProfiles.js +24 -18
  36. package/src/domains/voice/SipTrunks.js +26 -20
  37. package/src/domains/voice/Tokens.js +10 -4
  38. package/src/domains/voice/browser/Call.js +2 -0
  39. package/src/domains/voice/browser/Device.js +23 -11
  40. package/src/webhooks/verifySignature.js +66 -0
@@ -1,3 +1,9 @@
1
+ /** @typedef {import('../SignalHouseSDK.js').RequestOptions} RequestOptions */
2
+ /**
3
+ * @template T
4
+ * @typedef {import('../SignalHouseSDK.js').SdkResponse<T>} SdkResponse
5
+ */
6
+
1
7
  /**
2
8
  * @typedef {Object} CreateCampaignData
3
9
  * @property {string} brandId - The ID of the brand associated with the campaign (required)
@@ -148,9 +154,9 @@ export class Campaigns {
148
154
  * @roles signalhouse
149
155
  * @param {Object} params - The parameters for approving the campaign
150
156
  * @param {string} params.campaignId - The ID of the campaign to approve
151
- * @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
157
+ * @param {RequestOptions} [params.options] - Additional options for the request
152
158
  * @throws {Error} Throws an error if the campaignId parameter is missing
153
- * @returns {Promise<Object>} The response from the server
159
+ * @returns {Promise<SdkResponse<any>>} The response from the server
154
160
  */
155
161
  approveCampaign: async ({ campaignId, options = {} }) => {
156
162
  this.client._require({ campaignId });
@@ -163,9 +169,9 @@ export class Campaigns {
163
169
  * @roles signalhouse
164
170
  * @param {Object} params - The parameters for rejecting the campaign
165
171
  * @param {string} params.campaignId - The ID of the campaign to reject
166
- * @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request (body should include { rejectionReason })
172
+ * @param {RequestOptions} [params.options] - Additional options for the request (body should include { rejectionReason })
167
173
  * @throws {Error} Throws an error if the campaignId parameter is missing
168
- * @returns {Promise<Object>} The response from the server
174
+ * @returns {Promise<SdkResponse<any>>} The response from the server
169
175
  */
170
176
  rejectCampaign: async ({ campaignId, options = {} }) => {
171
177
  this.client._require({ campaignId });
@@ -177,8 +183,8 @@ export class Campaigns {
177
183
  * @async
178
184
  * @roles signalhouse
179
185
  * @param {Object} params - The parameters for retrieving CNP campaigns
180
- * @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
181
- * @returns {Promise<Array>} The response from the server
186
+ * @param {RequestOptions} [params.options] - Additional options for the request
187
+ * @returns {Promise<SdkResponse<Array>>} The response from the server
182
188
  */
183
189
  getCNPCampaigns: async ({ options = {} } = {}) => {
184
190
  return this.client(`/campaign/cnp`, { method: 'GET', ...options });
@@ -194,9 +200,9 @@ export class Campaigns {
194
200
  * @param {string} params.campaignId - The ID of the campaign to transition
195
201
  * @param {string} params.status - The target status: "PENDING_REVIEW", "REJECTED", "PENDING_DCA_APPROVAL", "DCA_REJECTED", or "ACTIVE". "PENDING_DCA_APPROVAL" requires a Signal House-approved Short Code brand, issued code, and captured opt-in proof.
196
202
  * @param {string} [params.rejectionReason] - Required, nonblank reason for "REJECTED"/"DCA_REJECTED" (max 1024 characters)
197
- * @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
203
+ * @param {RequestOptions} [params.options] - Additional options for the request
198
204
  * @throws {Error} Throws an error if the campaignId or status parameter is missing
199
- * @returns {Promise<Object>} The updated campaign
205
+ * @returns {Promise<SdkResponse<any>>} The updated campaign
200
206
  */
201
207
  updateShortCodeCampaignStatus: async ({ campaignId, status, rejectionReason, options = {} }) => {
202
208
  this.client._require({ campaignId, status });
@@ -216,8 +222,8 @@ export class Campaigns {
216
222
  * @param {string} params.actualCode - Issued five- or six-digit Short Code.
217
223
  * @param {string} params.leaseEndDate - Fixed future lease end date. A YYYY-MM-DD value expires at 23:59:59 UTC; timestamps retain their supplied time.
218
224
  * @param {string} [params.internalNotes] - Staff-only fulfillment notes.
219
- * @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options.
220
- * @returns {Promise<Object>} The updated campaign.
225
+ * @param {RequestOptions} [params.options] - Additional options.
226
+ * @returns {Promise<SdkResponse<any>>} The updated campaign.
221
227
  */
222
228
  fulfillShortCodeCampaign: async ({ campaignId, actualCode, leaseEndDate, internalNotes, options = {} }) => {
223
229
  this.client._require({ campaignId, actualCode, leaseEndDate });
@@ -234,8 +240,8 @@ export class Campaigns {
234
240
  * @roles signalhouse
235
241
  * @param {Object} params - Submission parameters.
236
242
  * @param {string} params.campaignId - Campaign identifier.
237
- * @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options.
238
- * @returns {Promise<Object>} The updated campaign.
243
+ * @param {RequestOptions} [params.options] - Additional options.
244
+ * @returns {Promise<SdkResponse<any>>} The updated campaign.
239
245
  */
240
246
  submitShortCodeCampaignToCarrier: async ({ campaignId, options = {} }) => {
241
247
  this.client._require({ campaignId });
@@ -245,7 +251,16 @@ export class Campaigns {
245
251
  ...options,
246
252
  });
247
253
  },
248
- /** Confirm Registry offboarding and complete a pending Short Code cancellation. */
254
+ /**
255
+ * Confirm Registry offboarding and complete a pending Short Code cancellation.
256
+ * @async
257
+ * @param {Object} params - Request parameters.
258
+ * @param {string} params.campaignId - Campaign identifier.
259
+ * @param {string} params.requestId - The pending cancellation request to complete.
260
+ * @param {string} [params.note] - Operator note recorded with the completion.
261
+ * @param {RequestOptions} [params.options] - Additional options.
262
+ * @returns {Promise<SdkResponse<any>>} The updated campaign.
263
+ */
249
264
  completeShortCodeCancellation: async ({ campaignId, requestId, note, options = {} }) => {
250
265
  this.client._require({ campaignId, requestId });
251
266
  const safeCampaignId = encodeURIComponent(campaignId);
@@ -255,7 +270,16 @@ export class Campaigns {
255
270
  ...options,
256
271
  });
257
272
  },
258
- /** Dismiss a pending Short Code cancellation and restore its prior lifecycle state. */
273
+ /**
274
+ * Dismiss a pending Short Code cancellation and restore its prior lifecycle state.
275
+ * @async
276
+ * @param {Object} params - Request parameters.
277
+ * @param {string} params.campaignId - Campaign identifier.
278
+ * @param {string} params.requestId - The pending cancellation request to dismiss.
279
+ * @param {string} [params.note] - Operator note recorded with the dismissal.
280
+ * @param {RequestOptions} [params.options] - Additional options.
281
+ * @returns {Promise<SdkResponse<any>>} The updated campaign.
282
+ */
259
283
  dismissShortCodeCancellation: async ({ campaignId, requestId, note, options = {} }) => {
260
284
  this.client._require({ campaignId, requestId });
261
285
  const safeCampaignId = encodeURIComponent(campaignId);
@@ -265,12 +289,28 @@ export class Campaigns {
265
289
  ...options,
266
290
  });
267
291
  },
268
- /** Read expired Short Code leases awaiting manual Registry offboarding. */
292
+ /**
293
+ * Read expired Short Code leases awaiting manual Registry offboarding.
294
+ * @async
295
+ * @param {Object} [params] - Request parameters.
296
+ * @param {number} [params.page] - Page number for pagination.
297
+ * @param {number} [params.limit] - Results per page.
298
+ * @param {RequestOptions} [params.options] - Additional options.
299
+ * @returns {Promise<SdkResponse<any>>} The expired leases page.
300
+ */
269
301
  getExpiredShortCodeLeases: async ({ page, limit, options = {} } = {}) => {
270
302
  const query = this.client._getQueryString({ page, limit });
271
303
  return this.client(`/campaign/short-code/expired-leases${query}`, { method: 'GET', ...options });
272
304
  },
273
- /** Confirm Registry offboarding and mark an expired Short Code released. */
305
+ /**
306
+ * Confirm Registry offboarding and mark an expired Short Code released.
307
+ * @async
308
+ * @param {Object} params - Request parameters.
309
+ * @param {string} params.campaignId - Campaign identifier.
310
+ * @param {string} [params.note] - Operator note recorded with the release.
311
+ * @param {RequestOptions} [params.options] - Additional options.
312
+ * @returns {Promise<SdkResponse<any>>} The updated campaign.
313
+ */
274
314
  releaseExpiredShortCodeLease: async ({ campaignId, note, options = {} }) => {
275
315
  this.client._require({ campaignId });
276
316
  const safeCampaignId = encodeURIComponent(campaignId);
@@ -298,7 +338,7 @@ export class Campaigns {
298
338
  * @param {string} [params.sortBy] - Field to sort by (e.g. "createdAt", "campaignId", "brandId", "groupId", "subgroupId", "usecase", "status")
299
339
  * @param {string} [params.sortOrder] - Sort direction ("asc" or "desc")
300
340
  * @param {string} [params.registrationType] - Filter by registration type ("TEN_DLC", "TOLL_FREE", or "SHORT_CODE")
301
- * @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
341
+ * @param {RequestOptions} [params.options] - Additional options for the request
302
342
  *
303
343
  * Every record carries a `sentiment` object -- trailing 7-day and 30-day inbound reply sentiment,
304
344
  * refreshed periodically from analytics rather than computed per request: `{ sevenDay, thirtyDay,
@@ -316,7 +356,7 @@ export class Campaigns {
316
356
  * in the window; the volumes say how much traffic sits behind it. A campaign's figure is scored from the
317
357
  * campaign's own summed counters, never averaged from its numbers. For a live figure use GET /number/health
318
358
  * or GET /campaign/health.
319
- * @returns {Promise<Array|Object>} The response from the server - array when unpaginated, or { data, total, page, limit, totalPages } when paginated
359
+ * @returns {Promise<SdkResponse<Array|Object>>} The response from the server - array when unpaginated, or { data, total, page, limit, totalPages } when paginated
320
360
  */
321
361
  async getCampaigns({
322
362
  id,
@@ -356,8 +396,8 @@ export class Campaigns {
356
396
  * @param {Object} params - Parameters for reading campaign health
357
397
  * @param {string} params.campaignId - Campaign identifier
358
398
  * @param {boolean} [params.includeNumbers=false] - When true, include per-number health entries
359
- * @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional request options
360
- * @returns {Promise<Object>} A promise that resolves to `{ campaignId, sevenDay, thirtyDay, numbers? }`
399
+ * @param {RequestOptions} [params.options] - Additional request options
400
+ * @returns {Promise<SdkResponse<any>>} A promise that resolves to `{ campaignId, sevenDay, thirtyDay, numbers? }`
361
401
  */
362
402
  async getCampaignHealth({ campaignId, includeNumbers = false, options = {} }) {
363
403
  this.client._require({ campaignId });
@@ -365,15 +405,34 @@ export class Campaigns {
365
405
  return this.client(`/campaign/health${queryString}`, { method: 'GET', ...options });
366
406
  }
367
407
 
408
+ /**
409
+ * Get the carrier throughput ceilings a campaign is currently sending under: the AT&T per-minute limit
410
+ * (per campaign, held 10% under the published ceiling) and the T-Mobile daily cap (per brand), each with
411
+ * its current tier and the next rung on the ladder, plus today's T-Mobile usage. Resolved from the same
412
+ * brand status / brand score rules the send path enforces with.
413
+ * @async
414
+ * @roles api, admin, developer, billing, user
415
+ * @param {Object} params - Parameters for reading campaign throughput limits
416
+ * @param {string} params.campaignId - Campaign identifier
417
+ * @param {RequestOptions} [params.options] - Additional request options
418
+ * @throws {Error} Throws an error if the campaignId parameter is missing
419
+ * @returns {Promise<SdkResponse<any>>} A promise that resolves to `{ campaignId, brandId, usecase, brand: { status, brandScore, entityType }, att: { tier, scope, unit, sms: { limit }, mms: { limit }, marginPercent, nextTier }, tmobile: { tier, scope, unit, dailyLimit, thresholds, nextTier, usedToday: { date, segments, resetsAt } | null } }`. A null tier/limit means the carrier ladder does not apply (unverified brand, GOVERNMENT entity, PUBLIC_SAFETY_RESTRICTED usecase); a null nextTier means the top rung or a usecase-capped (LOW_VOLUME) campaign.
420
+ */
421
+ async getCampaignThroughputLimits({ campaignId, options = {} }) {
422
+ this.client._require({ campaignId });
423
+ const queryString = this.client._getQueryString({ campaignId });
424
+ return this.client(`/campaign/throughput-limits${queryString}`, { method: 'GET', ...options });
425
+ }
426
+
368
427
  /**
369
428
  * Create a new campaign
370
429
  * @async
371
430
  * @roles api, admin, developer, billing, user
372
431
  * @param {Object} params - The parameters for creating the campaign (see CreateCampaignData typedef for details)
373
432
  * @param {CreateCampaignData} params.campaignData - The data for the campaign to be created (see CreateCampaignData typedef for details)
374
- * @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
433
+ * @param {RequestOptions} [params.options] - Additional options for the request
375
434
  * @throws {Error} Throws an error if the campaignData parameter is missing or if required fields in campaignData are missing
376
- * @returns {Promise<Object>} The response from the server
435
+ * @returns {Promise<SdkResponse<any>>} The response from the server
377
436
  */
378
437
  async createCampaign({ campaignData, options = {} }) {
379
438
  this.client._require({ campaignData: campaignData });
@@ -386,9 +445,9 @@ export class Campaigns {
386
445
  * @roles api, admin, developer, user
387
446
  * @param {Object} params - The parameters for creating the toll-free campaign
388
447
  * @param {CreateTollFreeCampaignData} params.campaignData - The data for the toll-free campaign to be created (see CreateTollFreeCampaignData typedef for details)
389
- * @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
448
+ * @param {RequestOptions} [params.options] - Additional options for the request
390
449
  * @throws {Error} Throws an error if the campaignData parameter is missing
391
- * @returns {Promise<Object>} The response from the server
450
+ * @returns {Promise<SdkResponse<any>>} The response from the server
392
451
  */
393
452
  async createTollFreeCampaign({ campaignData, options = {} }) {
394
453
  this.client._require({ campaignData });
@@ -404,9 +463,9 @@ export class Campaigns {
404
463
  * @roles api, admin, developer, user
405
464
  * @param {Object} params - The parameters for creating the Short Code campaign
406
465
  * @param {CreateShortCodeCampaignData} params.campaignData - The Short Code campaign data (see CreateShortCodeCampaignData typedef for details)
407
- * @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
466
+ * @param {RequestOptions} [params.options] - Additional options for the request
408
467
  * @throws {Error} Throws an error if the campaignData parameter is missing
409
- * @returns {Promise<Object>} The response from the server
468
+ * @returns {Promise<SdkResponse<any>>} The response from the server
410
469
  */
411
470
  async createShortCodeCampaign({ campaignData, options = {} }) {
412
471
  this.client._require({ campaignData });
@@ -423,9 +482,9 @@ export class Campaigns {
423
482
  * @param {Object} params - The parameters for updating the Short Code campaign
424
483
  * @param {string} params.campaignId - The ID of the campaign to update
425
484
  * @param {Object} params.updateData - The fields to update (top-level campaign fields plus an optional `shortCode` object of editable Short Code fields; pass a new `uploadOptInImage` URL as `shortCode.screenshotUrl` to replace the opt-in proof)
426
- * @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
485
+ * @param {RequestOptions} [params.options] - Additional options for the request
427
486
  * @throws {Error} Throws an error if the campaignId parameter is missing
428
- * @returns {Promise<Object>} The updated campaign
487
+ * @returns {Promise<SdkResponse<any>>} The updated campaign
429
488
  */
430
489
  async updateShortCodeCampaign({ campaignId, updateData, options = {} }) {
431
490
  this.client._require({ campaignId });
@@ -441,9 +500,9 @@ export class Campaigns {
441
500
  * @roles api, admin, developer, user
442
501
  * @param {Object} params - The parameters for cancelling the campaign
443
502
  * @param {string} params.campaignId - The ID of the campaign to cancel
444
- * @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
503
+ * @param {RequestOptions} [params.options] - Additional options for the request
445
504
  * @throws {Error} Throws an error if the campaignId parameter is missing
446
- * @returns {Promise<Object>} The cancelled campaign
505
+ * @returns {Promise<SdkResponse<any>>} The cancelled campaign
447
506
  */
448
507
  async cancelShortCodeCampaign({ campaignId, options = {} }) {
449
508
  this.client._require({ campaignId });
@@ -460,9 +519,9 @@ export class Campaigns {
460
519
  * @roles api, admin, developer, user
461
520
  * @param {Object} params - The parameters for downloading the artifact
462
521
  * @param {string} params.artifactId - The receipt identifier from `numberSource.externalLease.receiptArtifactId`
463
- * @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
522
+ * @param {RequestOptions} [params.options] - Additional options for the request
464
523
  * @throws {Error} Throws an error if the artifactId parameter is missing
465
- * @returns {Promise<Object>} The response from the server (raw file bytes as `data` when a binary responseType is used)
524
+ * @returns {Promise<SdkResponse<any>>} The response from the server (raw file bytes as `data` when a binary responseType is used)
466
525
  */
467
526
  async readCampaignArtifact({ artifactId, options = {} }) {
468
527
  this.client._require({ artifactId });
@@ -476,10 +535,10 @@ export class Campaigns {
476
535
  * @async
477
536
  * @roles api, admin, developer, user
478
537
  * @param {Object} params - The parameters for uploading the opt-in image
479
- * @param {Buffer|Blob|File} params.file - The image file to upload, provided as a Buffer/Blob/File
480
- * @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
538
+ * @param {Blob|File} params.file - The image file to upload, provided as a Blob/File
539
+ * @param {RequestOptions} [params.options] - Additional options for the request
481
540
  * @throws {Error} Throws an error if the file parameter is missing
482
- * @returns {Promise<Object>} The response from the server containing the hosted image's id and URL
541
+ * @returns {Promise<SdkResponse<any>>} The response from the server containing the hosted image's id and URL
483
542
  */
484
543
  async uploadOptInImage({ file, options = {} }) {
485
544
  this.client._require({ file });
@@ -498,9 +557,9 @@ export class Campaigns {
498
557
  * @param {string} [params.landingId] - The specific page to capture. Required for Toll-Free brands, which have
499
558
  * one page per campaign — omitted, the request is refused rather than guessing which page to shoot. A 10DLC
500
559
  * brand has a single page, so it may be omitted there
501
- * @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
560
+ * @param {RequestOptions} [params.options] - Additional options for the request
502
561
  * @throws {Error} Throws an error if the brandId parameter is missing
503
- * @returns {Promise<Object>} The response from the server containing the hosted image's id and URL
562
+ * @returns {Promise<SdkResponse<any>>} The response from the server containing the hosted image's id and URL
504
563
  */
505
564
  async captureOptInImageFromLanding({ brandId, landingId, options = {} }) {
506
565
  this.client._require({ brandId });
@@ -516,9 +575,9 @@ export class Campaigns {
516
575
  * @param {Object} params - The parameters for updating the campaign (see UpdateCampaignData typedef for details)
517
576
  * @param {string} params.campaignId - The ID of the campaign to update
518
577
  * @param {UpdateCampaignData} params.campaignData - The data for the campaign to be updated (see UpdateCampaignData typedef for details)
519
- * @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
578
+ * @param {RequestOptions} [params.options] - Additional options for the request
520
579
  * @throws {Error} Throws an error if the campaignId parameter is missing or if required fields in campaignData are missing
521
- * @returns {Promise<Object>} The response from the server
580
+ * @returns {Promise<SdkResponse<any>>} The response from the server
522
581
  */
523
582
  async updateCampaign({ campaignId, campaignData, options = {} }) {
524
583
  this.client._require({ campaignId: campaignId });
@@ -533,9 +592,9 @@ export class Campaigns {
533
592
  * @param {Object} params - The parameters for adding the comment
534
593
  * @param {string} params.campaignId - The ID of the campaign
535
594
  * @param {string} params.comment - The comment/note text
536
- * @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
595
+ * @param {RequestOptions} [params.options] - Additional options for the request
537
596
  * @throws {Error} Throws an error if the campaignId or comment parameter is missing
538
- * @returns {Promise<Object>} The updated campaign object
597
+ * @returns {Promise<SdkResponse<any>>} The updated campaign object
539
598
  */
540
599
  async addCampaignComment({ campaignId, comment, options = {} }) {
541
600
  this.client._require({ campaignId, comment });
@@ -549,9 +608,9 @@ export class Campaigns {
549
608
  * @roles api, admin, developer, billing, user
550
609
  * @param {Object} params - The parameters for deleting the campaign
551
610
  * @param {string} params.campaignId - The ID of the campaign to delete
552
- * @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
611
+ * @param {RequestOptions} [params.options] - Additional options for the request
553
612
  * @throws {Error} Throws an error if the campaignId parameter is missing
554
- * @returns {Promise<Object>} The response from the server
613
+ * @returns {Promise<SdkResponse<any>>} The response from the server
555
614
  */
556
615
  async deleteCampaign({ campaignId, options = {} }) {
557
616
  this.client._require({ campaignId: campaignId });
@@ -565,9 +624,9 @@ export class Campaigns {
565
624
  * @roles api, admin, developer, billing, user
566
625
  * @param {Object} params - The parameters for appealing the campaign rejection
567
626
  * @param {string} params.campaignId - The ID of the campaign to appeal
568
- * @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request (body should include { reason })
627
+ * @param {RequestOptions} [params.options] - Additional options for the request (body should include { reason })
569
628
  * @throws {Error} Throws an error if the campaignId parameter is missing
570
- * @returns {Promise<Object>} The response from the server
629
+ * @returns {Promise<SdkResponse<any>>} The response from the server
571
630
  */
572
631
  async appealDcaRejection({ campaignId, options = {} }) {
573
632
  this.client._require({ campaignId: campaignId });
@@ -581,9 +640,9 @@ export class Campaigns {
581
640
  * @roles api, admin, developer, billing, user
582
641
  * @param {Object} params - The parameters for nudging the campaign
583
642
  * @param {string} params.campaignId - The ID of the campaign to nudge
584
- * @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
643
+ * @param {RequestOptions} [params.options] - Additional options for the request
585
644
  * @throws {Error} Throws an error if the campaignId parameter is missing
586
- * @returns {Promise<Object>} The response from the server
645
+ * @returns {Promise<SdkResponse<any>>} The response from the server
587
646
  */
588
647
  async nudgeDcaForCampaign({ campaignId, options = {} }) {
589
648
  this.client._require({ campaignId: campaignId });
@@ -0,0 +1,168 @@
1
+ /** @typedef {import('../SignalHouseSDK.js').RequestOptions} RequestOptions */
2
+ /**
3
+ * @template T
4
+ * @typedef {import('../SignalHouseSDK.js').SdkResponse<T>} SdkResponse
5
+ */
6
+
7
+ /**
8
+ * Do Not Contact domain: the attested "Disable Automated Opt-Out" account setting. Signal House
9
+ * suppresses sends to recipients who opted out of the sending campaign by default; an account may
10
+ * disable that only by having an officer read and e-sign the Opt-Out Handling Attestation inside a
11
+ * Signal House app: the portal (a customer login signs for its own account) or one of our apps running
12
+ * as signalhouse_api (GHL, Shopify), which signs for the account it names on behalf of the customer user
13
+ * it authenticated. Every method therefore lives under the admin namespace (present only when the SDK is
14
+ * created with `enableAdmin: true`), and the API refuses the customer "api" (API key) role on the signing
15
+ * routes, so attestation can never be performed by a third-party integration.
16
+ */
17
+ export class Dnc {
18
+ constructor(client, enableAdmin) {
19
+ this.client = client;
20
+ this.enableAdmin = enableAdmin;
21
+
22
+ // Hidden Admin namespace INSIDE the domain
23
+ if (enableAdmin) {
24
+ this.admin = {
25
+ /**
26
+ * Get the current Opt-Out Handling Attestation text for the session's account with every placeholder
27
+ * filled (account values, the session's email and role, blanks in the signature block for what only
28
+ * signing supplies), plus the version and template hash a signature must echo back. The app must
29
+ * render this text; it never ships its own copy.
30
+ * @async
31
+ * @roles admin, developer, billing (portal logins); signalhouse_* with groupId
32
+ * @param {Object} [params] - Optional parameters
33
+ * @param {string} [params.groupId] - Group to render for (apps and staff; customers always get their active group)
34
+ * @param {RequestOptions} [params.options] - Additional options for the request
35
+ * @returns {Promise<SdkResponse<any>>} - `{ version, templateSha256, text, checkboxText, groupId, accountName, customerLegalName }`
36
+ */
37
+ getCurrentAttestation: async ({ groupId, options = {} } = {}) => {
38
+ const queryString = this.client._getQueryString({ groupId });
39
+ return this.client(`/dnc/attestation/current${queryString}`, { method: "GET", ...options });
40
+ },
41
+
42
+ /**
43
+ * Sign the attestation and disable automated opt-out suppression for the account and every subgroup,
44
+ * effective within about a minute on every API instance. Two callers: a portal login signs for its own
45
+ * account and the signer identity is taken from the session; a Signal House app running as
46
+ * signalhouse_api (GHL, Shopify) signs for the `groupId` it names and supplies the identity of the
47
+ * customer user it authenticated (`signerEmail`, optional `signerUserId`, `signedVia`, and the end
48
+ * user's `signerIpAddress` / `signerUserAgent`, which otherwise default to the app server's). Resolves
49
+ * 201 when this call created the record and 200 with the existing record on a repeat or concurrent
50
+ * call. A stale version or hash is refused with 409 and `details.code === "ATTESTATION_VERSION_MISMATCH"`;
51
+ * an unchecked box or blank field with 400. Human staff roles and customer API-key sessions are refused.
52
+ * @async
53
+ * @roles admin, developer, billing (portal logins); signalhouse_api (apps, with groupId)
54
+ * @param {Object} params
55
+ * @param {string} params.version - The version returned by getCurrentAttestation
56
+ * @param {string} params.templateSha256 - The template hash returned by getCurrentAttestation
57
+ * @param {boolean} params.checkboxAcknowledged - Must be true
58
+ * @param {boolean} params.scrolledToEnd - Must be true
59
+ * @param {string} params.customerLegalName - Company legal name
60
+ * @param {string} params.signerName - Signer's typed full legal name (the electronic signature)
61
+ * @param {string} params.signerTitle - Signer's title
62
+ * @param {string} [params.groupId] - App callers: the account being attested
63
+ * @param {string} [params.signerEmail] - App callers (required): the signer's email as authenticated by the app
64
+ * @param {string} [params.signerUserId] - App callers: the app's id for the signer
65
+ * @param {string} [params.signedVia] - App callers: the app name, e.g. "ghl" or "shopify"
66
+ * @param {string} [params.signerIpAddress] - App callers: the end user's IP address
67
+ * @param {string} [params.signerUserAgent] - App callers: the end user's user agent
68
+ * @param {RequestOptions} [params.options] - Additional options for the request
69
+ * @throws {Error} Throws an error if a required parameter is missing
70
+ * @returns {Promise<SdkResponse<any>>} - `{ attestation, created }`
71
+ */
72
+ signAttestation: async ({ version, templateSha256, checkboxAcknowledged, scrolledToEnd, customerLegalName, signerName, signerTitle, groupId, signerEmail, signerUserId, signedVia, signerIpAddress, signerUserAgent, options = {} }) => {
73
+ this.client._require({ version, templateSha256, customerLegalName, signerName, signerTitle });
74
+ const appFields = Object.fromEntries(Object.entries({ groupId, signerEmail, signerUserId, signedVia, signerIpAddress, signerUserAgent }).filter(([, value]) => value !== undefined));
75
+ return this.client(`/dnc/attestation`, {
76
+ method: "POST",
77
+ body: { version, templateSha256, checkboxAcknowledged, scrolledToEnd, customerLegalName, signerName, signerTitle, ...appFields },
78
+ ...options,
79
+ });
80
+ },
81
+
82
+ /**
83
+ * Revoke the active attestation and re-enable automated opt-out suppression, effective within about a
84
+ * minute: a portal login for its own account, or an app (signalhouse_api) for the `groupId` it names.
85
+ * The record is retained as "revoked". 404 when nothing is active.
86
+ * @async
87
+ * @roles admin, developer, billing (portal logins); signalhouse_api (apps, with groupId)
88
+ * @param {Object} [params] - Optional parameters
89
+ * @param {string} [params.groupId] - App callers: the account
90
+ * @param {RequestOptions} [params.options] - Additional options for the request
91
+ * @returns {Promise<SdkResponse<any>>} - `{ attestation }`
92
+ */
93
+ revokeAttestation: async ({ groupId, options = {} } = {}) => {
94
+ return this.client(`/dnc/attestation/revoke`, { method: "POST", ...(groupId ? { body: { groupId } } : {}), ...options });
95
+ },
96
+
97
+ /**
98
+ * Read an account's attestation state: whether automated opt-out is disabled, the active record
99
+ * (full stored text included), the full history, and whether the active record predates the
100
+ * current template and must be re-signed by `resignDeadline`.
101
+ * @async
102
+ * @roles admin, developer, billing (portal logins); signalhouse_* with groupId
103
+ * @param {Object} [params] - Optional parameters
104
+ * @param {string} [params.groupId] - Group to read (apps and staff; customers always get their active group)
105
+ * @param {RequestOptions} [params.options] - Additional options for the request
106
+ * @returns {Promise<SdkResponse<any>>} - `{ groupId, automatedOptOutDisabled, currentVersion, currentTemplateSha256, requiresResign, resignDeadline, active, history }`
107
+ */
108
+ getAttestation: async ({ groupId, options = {} } = {}) => {
109
+ const queryString = this.client._getQueryString({ groupId });
110
+ return this.client(`/dnc/attestation${queryString}`, { method: "GET", ...options });
111
+ },
112
+
113
+ /**
114
+ * List opt-out attestations across every account, newest first, with each group's trailing
115
+ * would-have-suppressed counts (7 and 30 days, recorded while attested) and 7-day opt-out count.
116
+ * The full attestation text is omitted from list rows. Staff-only.
117
+ * @async
118
+ * @roles signalhouse
119
+ * @param {Object} [params] - Optional parameters
120
+ * @param {("active"|"revoked"|"superseded")} [params.status] - Filter by status
121
+ * @param {string} [params.groupId] - Filter by group
122
+ * @param {number} [params.page] - Page number (default 1)
123
+ * @param {number} [params.limit] - Rows per page (default 50, max 500)
124
+ * @param {RequestOptions} [params.options] - Additional options for the request
125
+ * @returns {Promise<SdkResponse<any>>} - `{ rows, totalCount, page, limit }`
126
+ */
127
+ listAttestations: async ({ status, groupId, page, limit, options = {} } = {}) => {
128
+ const queryString = this.client._getQueryString({ status, groupId, page, limit });
129
+ return this.client(`/dnc/attestations${queryString}`, { method: "GET", ...options });
130
+ },
131
+
132
+ /**
133
+ * Read one attestation with its stored text, hashes, signer identity, IP and user agent, plus
134
+ * the group's full attestation history. Staff-only.
135
+ * @async
136
+ * @roles signalhouse
137
+ * @param {Object} params
138
+ * @param {string} params.id - The attestation id
139
+ * @param {RequestOptions} [params.options] - Additional options for the request
140
+ * @throws {Error} Throws an error if the id parameter is missing
141
+ * @returns {Promise<SdkResponse<any>>} - `{ attestation, history }`
142
+ */
143
+ getAttestationById: async ({ id, options = {} }) => {
144
+ this.client._require({ id });
145
+ return this.client(`/dnc/attestations/${encodeURIComponent(id)}`, { method: "GET", ...options });
146
+ },
147
+
148
+ /**
149
+ * Revoke an active attestation with a reason and re-enable automated opt-out for the account.
150
+ * Emails the signer and account owner. There is no staff path that creates an attestation. Staff-only.
151
+ * @async
152
+ * @roles signalhouse
153
+ * @param {Object} params
154
+ * @param {string} params.id - The attestation id
155
+ * @param {("carrier_complaint"|"regulator_inquiry"|"legal_request"|"excessive_opt_out_rate"|"customer_request"|"other")} params.reasonCode - Why it is being revoked
156
+ * @param {string} params.reason - Free-text reason shown to the customer
157
+ * @param {RequestOptions} [params.options] - Additional options for the request
158
+ * @throws {Error} Throws an error if a required parameter is missing
159
+ * @returns {Promise<SdkResponse<any>>} - `{ attestation }` (status "revoked", revokedByType "signalhouse_admin")
160
+ */
161
+ revokeAttestationById: async ({ id, reasonCode, reason, options = {} }) => {
162
+ this.client._require({ id, reasonCode, reason });
163
+ return this.client(`/dnc/attestations/${encodeURIComponent(id)}/revoke`, { method: "POST", body: { reasonCode, reason }, ...options });
164
+ },
165
+ };
166
+ }
167
+ }
168
+ }