@signalhousellc/sdk 1.0.65 → 1.0.67
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -0
- package/package.json +13 -1
- package/scripts/install-skills.mjs +329 -0
- package/skills/VENDORED.json +22 -0
- package/skills/signalhouse-10dlc/SKILL.md +176 -0
- package/skills/signalhouse-10dlc/examples/brightsmile-onboarding.md +62 -0
- package/skills/signalhouse-10dlc/references/tcr-rejection-causes.md +111 -0
- package/skills/signalhouse-advisor/SKILL.md +84 -0
- package/skills/signalhouse-numbers/SKILL.md +83 -0
- package/skills/signalhouse-setup/SKILL.md +91 -0
- package/skills/signalhouse-sms/SKILL.md +81 -0
- package/skills/signalhouse-webhooks/SKILL.md +116 -0
- package/src/SignalHouseSDK.js +3 -0
- package/src/domains/Agents.js +456 -0
- package/src/domains/Campaigns.js +82 -23
- package/src/domains/Landings.js +84 -0
- package/src/domains/Messages.js +73 -36
- package/src/domains/Numbers.js +42 -21
- package/src/domains/Webhooks.js +13 -4
- package/src/domains/voice/ProgrammableVoiceProfiles.js +4 -2
package/src/domains/Campaigns.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @typedef {Object} CreateCampaignData
|
|
3
3
|
* @property {string} brandId - The ID of the brand associated with the campaign (required)
|
|
4
4
|
* @property {string} usecase - The use case for the campaign (2FA, ACCOUNT_NOTIFICATION, AGENTS_FRANCHISES, CARRIER_EXEMPT, CHARITY, CUSTOMER_CARE, DELIVERY_NOTIFICATION, EMERGENCY, FRAUD_ALERT, HIGHER_EDUCATION, K12_EDUCATION, LOW_VOLUME, M2M, MARKETING, MIXED, POLITICAL, POLLING_VOTING, PROXY, PUBLIC_SAFETY_RESTRICTED, PUBLIC_SERVICE_ANNOUNCEMENT, SECURITY_ALERT, SOCIAL, SOLE_PROPRIETOR, SWEEPSTAKE, TRIAL, UCAAS_HIGH, UCAAS_LOW)
|
|
5
|
-
* @property {Array<string>} [subUsecases] - An array of sub-use cases for the campaign (2FA, ACCOUNT_NOTIFICATION, AGENTS_FRANCHISES, CARRIER_EXEMPT, CHARITY, CUSTOMER_CARE, DELIVERY_NOTIFICATION, EMERGENCY, FRAUD_ALERT, HIGHER_EDUCATION, K12_EDUCATION, LOW_VOLUME, M2M, MARKETING, MIXED, POLITICAL, POLLING_VOTING, PROXY, PUBLIC_SAFETY_RESTRICTED, PUBLIC_SERVICE_ANNOUNCEMENT, SECURITY_ALERT,
|
|
5
|
+
* @property {Array<string>} [subUsecases] - An array of sub-use cases for the campaign (2FA, ACCOUNT_NOTIFICATION, AGENTS_FRANCHISES, CARRIER_EXEMPT, CHARITY, CUSTOMER_CARE, DELIVERY_NOTIFICATION, EMERGENCY, FRAUD_ALERT, HIGHER_EDUCATION, K12_EDUCATION, LOW_VOLUME, M2M, MARKETING, MIXED, POLITICAL, POLLING_VOTING, PROXY, PUBLIC_SAFETY_RESTRICTED, PUBLIC_SERVICE_ANNOUNCEMENT, SECURITY_ALERT, SOLE_PROPRIETOR, SWEEPSTAKE, TRIAL, UCAAS_HIGH, UCAAS_LOW — NOT SOCIAL, which TCR rejects as a sub-usecase for every parent usecase even though it is valid as the top-level `usecase`)
|
|
6
6
|
* @property {string} description - A detailed description of the campaign (required, must be between 40 and 4096 characters)
|
|
7
7
|
* @property {boolean} [embeddedLink=true] - Whether the campaign includes an embedded link (optional, defaults to true)
|
|
8
8
|
* @property {boolean} [embeddedPhone=false] - Whether the campaign includes an embedded phone number (optional, defaults to false)
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
/**
|
|
37
37
|
* @typedef {Object} UpdateCampaignData
|
|
38
38
|
* @property {string} [usecase] - The use case for the campaign (2FA, ACCOUNT_NOTIFICATION, AGENTS_FRANCHISES, CARRIER_EXEMPT, CHARITY, CUSTOMER_CARE, DELIVERY_NOTIFICATION, EMERGENCY, FRAUD_ALERT, HIGHER_EDUCATION, K12_EDUCATION, LOW_VOLUME, M2M, MARKETING, MIXED, POLITICAL, POLLING_VOTING, PROXY, PUBLIC_SAFETY_RESTRICTED, PUBLIC_SERVICE_ANNOUNCEMENT, SECURITY_ALERT, SOCIAL, SOLE_PROPRIETOR, SWEEPSTAKE, TRIAL, UCAAS_HIGH, UCAAS_LOW)
|
|
39
|
-
* @property {Array<string>} [subUsecases] - An array of sub-use cases for the campaign (2FA, ACCOUNT_NOTIFICATION, AGENTS_FRANCHISES, CARRIER_EXEMPT, CHARITY, CUSTOMER_CARE, DELIVERY_NOTIFICATION, EMERGENCY, FRAUD_ALERT, HIGHER_EDUCATION, K12_EDUCATION, LOW_VOLUME, M2M, MARKETING, MIXED, POLITICAL, POLLING_VOTING, PROXY, PUBLIC_SAFETY_RESTRICTED, PUBLIC_SERVICE_ANNOUNCEMENT, SECURITY_ALERT,
|
|
39
|
+
* @property {Array<string>} [subUsecases] - An array of sub-use cases for the campaign (2FA, ACCOUNT_NOTIFICATION, AGENTS_FRANCHISES, CARRIER_EXEMPT, CHARITY, CUSTOMER_CARE, DELIVERY_NOTIFICATION, EMERGENCY, FRAUD_ALERT, HIGHER_EDUCATION, K12_EDUCATION, LOW_VOLUME, M2M, MARKETING, MIXED, POLITICAL, POLLING_VOTING, PROXY, PUBLIC_SAFETY_RESTRICTED, PUBLIC_SERVICE_ANNOUNCEMENT, SECURITY_ALERT, SOLE_PROPRIETOR, SWEEPSTAKE, TRIAL, UCAAS_HIGH, UCAAS_LOW — NOT SOCIAL, which TCR rejects as a sub-usecase for every parent usecase even though it is valid as the top-level `usecase`)
|
|
40
40
|
* @property {string} [description] - A detailed description of the campaign (optional, must be between 40 and 4096 characters if provided)
|
|
41
41
|
* @property {boolean} [embeddedLink] - Whether the campaign includes an embedded link (optional)
|
|
42
42
|
* @property {boolean} [embeddedPhone] - Whether the campaign includes an embedded phone number (optional)
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
* @property {string} [privacyPolicyLink] - A URL linking to the privacy policy for the campaign (optional, must be at most 2048 characters if provided)
|
|
65
65
|
* @property {string} [termsAndConditionsLink] - A URL linking to the terms and conditions for the campaign (optional, must be at most 2048 characters if provided)
|
|
66
66
|
* @property {string} [embeddedLinkSample] - A sample of the embedded link used in the campaign (optional, must be at most 255 characters if provided)
|
|
67
|
-
* @property {Object} [tollFree] - Toll-Free editable fields, used when updating a Toll-Free campaign. Mirrors the CreateTollFreeCampaignData `tollFree` object with every field optional (useCase, messageVolume, programSummary (40-500), exampleMessage, customerCareEmail, optInImageURLs, optIns, multiNumberReason (≤500)). Phone numbers cannot be changed via update — Toll-Free numbers are locked to their campaign.
|
|
67
|
+
* @property {Object} [tollFree] - Toll-Free editable fields, used when updating a Toll-Free campaign. Mirrors the CreateTollFreeCampaignData `tollFree` object with every field optional (useCase, messageVolume, programSummary (40-500), exampleMessage (≤1000), customerCareEmail, optInImageURLs, optIns, multiNumberReason (≤500), useCases, channels, landingId). Phone numbers cannot be changed via update — Toll-Free numbers are locked to their campaign.
|
|
68
68
|
*/
|
|
69
69
|
|
|
70
70
|
/**
|
|
@@ -79,7 +79,7 @@
|
|
|
79
79
|
* @property {string} useCase - The Toll-Free use case (required, e.g. TWO_FA, GENERAL_MARKETING, HEALTHCARE, MIXED — one of the Toll-Free use-case values)
|
|
80
80
|
* @property {string} messageVolume - The estimated monthly message volume tier (required, one of TEN, HUNDRED, THOUSAND, TEN_THOUSAND, HUNDRED_THOUSAND, TWO_HUNDRED_FIFTY_THOUSAND, FIVE_HUNDRED_THOUSAND, SEVEN_HUNDRED_FIFTY_THOUSAND, ONE_MILLION, FIVE_MILLION, TEN_MILLION_PLUS)
|
|
81
81
|
* @property {string} programSummary - A summary of the messaging program (required, 40-500 characters)
|
|
82
|
-
* @property {string} exampleMessage - An example message (required, at most
|
|
82
|
+
* @property {string} exampleMessage - An example message (required, at most 1000 characters; holds one sample per use case, stored verbatim, no STOP/HELP appended by the server)
|
|
83
83
|
* @property {string} customerCareEmail - A customer-care contact email (required, valid email)
|
|
84
84
|
* @property {Array<string>} optInImageURLs - URLs to opt-in proof images (required, at least one, each at most 2048 characters)
|
|
85
85
|
* @property {Object} [optIns] - Opt-in method details. Each channel is optional.
|
|
@@ -88,6 +88,9 @@
|
|
|
88
88
|
* @property {TollFreeOptIn} [optIns.keyword] - Keyword opt-in details
|
|
89
89
|
* @property {TollFreeOptIn} [optIns.interactiveVoiceResponse] - IVR opt-in details
|
|
90
90
|
* @property {string} [multiNumberReason] - Internally-stored reason the customer requested more than one Toll-Free number on the campaign (optional, at most 500 characters). Required when more than one phone number is assigned; captured for Signal House review only and never sent to the carrier.
|
|
91
|
+
* @property {string[]} [useCases] - The sender's real use-case picks (optional). `useCase` above carries the single value the carrier accepts (MIXED when there is more than one); these are what a Signal House landing page renders a consent checkbox per. Never forwarded to the carrier.
|
|
92
|
+
* @property {string[]} [channels] - The channels consent covers ("SMS", "MMS", "VOICE") (optional). Never forwarded to the carrier.
|
|
93
|
+
* @property {string} [landingId] - The Signal House landing page whose consent boxes this campaign's call-to-action describes (optional). Must be an ACTIVE page owned by the same brand and group.
|
|
91
94
|
*/
|
|
92
95
|
|
|
93
96
|
/**
|
|
@@ -112,7 +115,8 @@
|
|
|
112
115
|
* @property {string} [doubleOptInMessage] - Required when adultContent is true (20-1024 characters)
|
|
113
116
|
* @property {string} programSummary - Generated-but-editable campaign/program summary (required, 40-2048 characters)
|
|
114
117
|
* @property {string} optInConfirmationMessage - The opt-in confirmation message (required, 20-1024 characters)
|
|
115
|
-
* @property {string}
|
|
118
|
+
* @property {string} optInUrl - Public HTTPS URL for the live opt-in experience, shown to reviewers as a link (required; private, local, and credentialed URLs are rejected)
|
|
119
|
+
* @property {string} screenshotUrl - Hosted opt-in proof screenshot URL returned by `uploadOptInImage` (required). Must be a Signal House-hosted opt-in image owned by your group; external URLs are rejected
|
|
116
120
|
*/
|
|
117
121
|
|
|
118
122
|
/**
|
|
@@ -126,7 +130,6 @@
|
|
|
126
130
|
* @property {string} sample1 - Sample message 1 (required, 20-1024 characters)
|
|
127
131
|
* @property {string} sample2 - Sample message 2 (required, 20-1024 characters)
|
|
128
132
|
* @property {string} sample3 - Sample message 3 (required, 20-1024 characters)
|
|
129
|
-
* @property {boolean} [autoRenewal=true] - Whether the campaign should auto-renew (optional, defaults to true)
|
|
130
133
|
* @property {string} [tag] - A tag for the campaign (optional, at most 255 characters)
|
|
131
134
|
* @property {ShortCodeDetails} shortCode - The Short Code campaign details (required)
|
|
132
135
|
*/
|
|
@@ -183,13 +186,14 @@ export class Campaigns {
|
|
|
183
186
|
/**
|
|
184
187
|
* Transition a Short Code campaign's review status (SHGHL-2225). A customer-visible reason is
|
|
185
188
|
* required for both rejection states ("REJECTED" = Signal House Rejected, "DCA_REJECTED" =
|
|
186
|
-
* Rejected).
|
|
189
|
+
* Rejected). Selecting "PENDING_DCA_APPROVAL" runs the guarded carrier-review transition;
|
|
190
|
+
* fulfillment remains a separate staff operation.
|
|
187
191
|
* @async
|
|
188
192
|
* @roles signalhouse
|
|
189
193
|
* @param {Object} params - The parameters for the status transition
|
|
190
194
|
* @param {string} params.campaignId - The ID of the campaign to transition
|
|
191
|
-
* @param {string} params.status - The target status: "PENDING_REVIEW", "REJECTED", "
|
|
192
|
-
* @param {string} [params.rejectionReason] - Required for "REJECTED"/"DCA_REJECTED" (
|
|
195
|
+
* @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
|
+
* @param {string} [params.rejectionReason] - Required, nonblank reason for "REJECTED"/"DCA_REJECTED" (max 1024 characters)
|
|
193
197
|
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
|
|
194
198
|
* @throws {Error} Throws an error if the campaignId or status parameter is missing
|
|
195
199
|
* @returns {Promise<Object>} The updated campaign
|
|
@@ -210,16 +214,17 @@ export class Campaigns {
|
|
|
210
214
|
* @param {Object} params - Fulfillment parameters.
|
|
211
215
|
* @param {string} params.campaignId - Campaign identifier.
|
|
212
216
|
* @param {string} params.actualCode - Issued five- or six-digit Short Code.
|
|
217
|
+
* @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.
|
|
213
218
|
* @param {string} [params.internalNotes] - Staff-only fulfillment notes.
|
|
214
219
|
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options.
|
|
215
220
|
* @returns {Promise<Object>} The updated campaign.
|
|
216
221
|
*/
|
|
217
|
-
fulfillShortCodeCampaign: async ({ campaignId, actualCode, internalNotes, options = {} }) => {
|
|
218
|
-
this.client._require({ campaignId, actualCode });
|
|
222
|
+
fulfillShortCodeCampaign: async ({ campaignId, actualCode, leaseEndDate, internalNotes, options = {} }) => {
|
|
223
|
+
this.client._require({ campaignId, actualCode, leaseEndDate });
|
|
219
224
|
const safeCampaignId = encodeURIComponent(campaignId);
|
|
220
225
|
return this.client(`/campaign/short-code/${safeCampaignId}/fulfill`, {
|
|
221
226
|
method: 'POST',
|
|
222
|
-
body: { actualCode, internalNotes },
|
|
227
|
+
body: { actualCode, leaseEndDate, internalNotes },
|
|
223
228
|
...options,
|
|
224
229
|
});
|
|
225
230
|
},
|
|
@@ -240,6 +245,39 @@ export class Campaigns {
|
|
|
240
245
|
...options,
|
|
241
246
|
});
|
|
242
247
|
},
|
|
248
|
+
/** Confirm Registry offboarding and complete a pending Short Code cancellation. */
|
|
249
|
+
completeShortCodeCancellation: async ({ campaignId, requestId, note, options = {} }) => {
|
|
250
|
+
this.client._require({ campaignId, requestId });
|
|
251
|
+
const safeCampaignId = encodeURIComponent(campaignId);
|
|
252
|
+
return this.client(`/campaign/short-code/${safeCampaignId}/cancellation/complete`, {
|
|
253
|
+
method: 'POST',
|
|
254
|
+
body: { requestId, note },
|
|
255
|
+
...options,
|
|
256
|
+
});
|
|
257
|
+
},
|
|
258
|
+
/** Dismiss a pending Short Code cancellation and restore its prior lifecycle state. */
|
|
259
|
+
dismissShortCodeCancellation: async ({ campaignId, requestId, note, options = {} }) => {
|
|
260
|
+
this.client._require({ campaignId, requestId });
|
|
261
|
+
const safeCampaignId = encodeURIComponent(campaignId);
|
|
262
|
+
return this.client(`/campaign/short-code/${safeCampaignId}/cancellation/dismiss`, {
|
|
263
|
+
method: 'POST',
|
|
264
|
+
body: { requestId, note },
|
|
265
|
+
...options,
|
|
266
|
+
});
|
|
267
|
+
},
|
|
268
|
+
/** Read expired Short Code leases awaiting manual Registry offboarding. */
|
|
269
|
+
getExpiredShortCodeLeases: async ({ page, limit, options = {} } = {}) => {
|
|
270
|
+
const query = this.client._getQueryString({ page, limit });
|
|
271
|
+
return this.client(`/campaign/short-code/expired-leases${query}`, { method: 'GET', ...options });
|
|
272
|
+
},
|
|
273
|
+
/** Confirm Registry offboarding and mark an expired Short Code released. */
|
|
274
|
+
releaseExpiredShortCodeLease: async ({ campaignId, note, options = {} }) => {
|
|
275
|
+
this.client._require({ campaignId });
|
|
276
|
+
const safeCampaignId = encodeURIComponent(campaignId);
|
|
277
|
+
return this.client(`/campaign/short-code/${safeCampaignId}/expired-lease/release`, {
|
|
278
|
+
method: 'POST', body: { note }, ...options,
|
|
279
|
+
});
|
|
280
|
+
},
|
|
243
281
|
};
|
|
244
282
|
}
|
|
245
283
|
}
|
|
@@ -261,6 +299,23 @@ export class Campaigns {
|
|
|
261
299
|
* @param {string} [params.sortOrder] - Sort direction ("asc" or "desc")
|
|
262
300
|
* @param {string} [params.registrationType] - Filter by registration type ("TEN_DLC", "TOLL_FREE", or "SHORT_CODE")
|
|
263
301
|
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
|
|
302
|
+
*
|
|
303
|
+
* Every record carries a `sentiment` object -- trailing 7-day and 30-day inbound reply sentiment,
|
|
304
|
+
* refreshed periodically from analytics rather than computed per request: `{ sevenDay, thirtyDay,
|
|
305
|
+
* updatedAt }`, each window being `{ score, label, scoredCount, positive, neutral, negative }`. The
|
|
306
|
+
* object is always present and fully populated, so it can be read without a presence check.
|
|
307
|
+
* `score` is a volume-weighted average in -100..100 and is null when nothing was scored in the
|
|
308
|
+
* window, which is not the same as a score of 0 -- null means nobody replied, 0 means replies
|
|
309
|
+
* averaged neutral. `updatedAt` is null until the first rollup writes the record, and it tracks when
|
|
310
|
+
* the figures last CHANGED, not when the job last ran.
|
|
311
|
+
*
|
|
312
|
+
* Every record also carries a `health` object -- trailing 7-day and 30-day delivery/opt-out health from
|
|
313
|
+
* the same periodic refresh: `{ sevenDay, thirtyDay, updatedAt }`, each window being `{ score,
|
|
314
|
+
* deliveryRate, optOutRate, deliveryScore, optOutScore, messagesSent, messagesDelivered, messagesFailed,
|
|
315
|
+
* optOuts }`. `score` is 1.0..10.0 (the mean of the two bucket scores) and is null when nothing was sent
|
|
316
|
+
* in the window; the volumes say how much traffic sits behind it. A campaign's figure is scored from the
|
|
317
|
+
* campaign's own summed counters, never averaged from its numbers. For a live figure use GET /number/health
|
|
318
|
+
* or GET /campaign/health.
|
|
264
319
|
* @returns {Promise<Array|Object>} The response from the server - array when unpaginated, or { data, total, page, limit, totalPages } when paginated
|
|
265
320
|
*/
|
|
266
321
|
async getCampaigns({
|
|
@@ -342,9 +397,9 @@ export class Campaigns {
|
|
|
342
397
|
|
|
343
398
|
/**
|
|
344
399
|
* Create a new Short Code campaign and submit it for Signal House review (SHGHL-2225). Requires an
|
|
345
|
-
* approved (VERIFIED) Short Code brand.
|
|
346
|
-
|
|
347
|
-
|
|
400
|
+
* approved (VERIFIED) Short Code brand. Upload the opt-in proof screenshot first with `uploadOptInImage`
|
|
401
|
+
* and pass the returned URL as `campaignData.shortCode.screenshotUrl` (required). Request or register the
|
|
402
|
+
* campaign's Short Code separately through `numbers.requestShortCodeAcquisition` after creation.
|
|
348
403
|
* @async
|
|
349
404
|
* @roles api, admin, developer, user
|
|
350
405
|
* @param {Object} params - The parameters for creating the Short Code campaign
|
|
@@ -367,7 +422,7 @@ export class Campaigns {
|
|
|
367
422
|
* @roles api, admin, developer, user
|
|
368
423
|
* @param {Object} params - The parameters for updating the Short Code campaign
|
|
369
424
|
* @param {string} params.campaignId - The ID of the campaign to update
|
|
370
|
-
* @param {Object} params.updateData - The fields to update (top-level campaign fields plus an optional `shortCode` object of editable Short Code fields)
|
|
425
|
+
* @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)
|
|
371
426
|
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
|
|
372
427
|
* @throws {Error} Throws an error if the campaignId parameter is missing
|
|
373
428
|
* @returns {Promise<Object>} The updated campaign
|
|
@@ -379,10 +434,9 @@ export class Campaigns {
|
|
|
379
434
|
}
|
|
380
435
|
|
|
381
436
|
/**
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
* already-fulfilled Signal House request) is never auto-released — see SHGHL-2228 for offboarding.
|
|
437
|
+
* Cancel a Short Code campaign. A customer cancellation for an issued Short Code returns
|
|
438
|
+
* PENDING_DELETE (displayed as Cancellation Pending) until Signal House confirms Registry offboarding.
|
|
439
|
+
* Unissued RANDOM/VANITY requests, plus staff-confirmed cancellations, return EXPIRED immediately.
|
|
386
440
|
* @async
|
|
387
441
|
* @roles api, admin, developer, user
|
|
388
442
|
* @param {Object} params - The parameters for cancelling the campaign
|
|
@@ -418,7 +472,7 @@ export class Campaigns {
|
|
|
418
472
|
|
|
419
473
|
/**
|
|
420
474
|
* Upload an opt-in proof image to be hosted on-platform, returning a publicly-fetchable URL suitable for a
|
|
421
|
-
* Toll-Free campaign's optInImageURLs
|
|
475
|
+
* Toll-Free campaign's optInImageURLs or a Short Code campaign's shortCode.screenshotUrl
|
|
422
476
|
* @async
|
|
423
477
|
* @roles api, admin, developer, user
|
|
424
478
|
* @param {Object} params - The parameters for uploading the opt-in image
|
|
@@ -441,13 +495,18 @@ export class Campaigns {
|
|
|
441
495
|
* @roles api, admin, developer, user
|
|
442
496
|
* @param {Object} params - The parameters for capturing the opt-in image
|
|
443
497
|
* @param {string} params.brandId - The ID of the brand whose generated landing page should be captured
|
|
498
|
+
* @param {string} [params.landingId] - The specific page to capture. Required for Toll-Free brands, which have
|
|
499
|
+
* one page per campaign — omitted, the request is refused rather than guessing which page to shoot. A 10DLC
|
|
500
|
+
* brand has a single page, so it may be omitted there
|
|
444
501
|
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
|
|
445
502
|
* @throws {Error} Throws an error if the brandId parameter is missing
|
|
446
503
|
* @returns {Promise<Object>} The response from the server containing the hosted image's id and URL
|
|
447
504
|
*/
|
|
448
|
-
async captureOptInImageFromLanding({ brandId, options = {} }) {
|
|
505
|
+
async captureOptInImageFromLanding({ brandId, landingId, options = {} }) {
|
|
449
506
|
this.client._require({ brandId });
|
|
450
|
-
|
|
507
|
+
const body = { brandId };
|
|
508
|
+
if (landingId) body.landingId = landingId;
|
|
509
|
+
return this.client(`/campaign/opt-in-image/from-landing`, { method: 'POST', body, ...options });
|
|
451
510
|
}
|
|
452
511
|
|
|
453
512
|
/**
|
package/src/domains/Landings.js
CHANGED
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {Object} TollFreeConsentBox
|
|
3
|
+
* @property {string} useCase - The use case the checkbox covers
|
|
4
|
+
* @property {string} channel - The channel the checkbox covers ("SMS" or "MMS")
|
|
5
|
+
* @property {string} text - The wording rendered beside the checkbox
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @typedef {Object} TollFreeLandingData
|
|
10
|
+
* @property {string[]} useCases - The campaign's real use cases; one consent box is rendered per use case per channel
|
|
11
|
+
* @property {string[]} channels - The channels consent covers ("SMS", "MMS", "VOICE")
|
|
12
|
+
* @property {string} consentDisclosure - The shared disclosure rendered once above the consent boxes (max 1024 characters)
|
|
13
|
+
* @property {TollFreeConsentBox[]} consentBoxes - The consent boxes the page renders (max 16; each text max 512 characters)
|
|
14
|
+
*/
|
|
15
|
+
|
|
1
16
|
/**
|
|
2
17
|
* @typedef {Object} CreateLandingData
|
|
3
18
|
* @property {string} brandId - The ID of the brand to associate with the landing page
|
|
@@ -7,6 +22,11 @@
|
|
|
7
22
|
* @property {string} primaryTextColor - The primary text color for the landing page (e.g., "#000000")
|
|
8
23
|
* @property {string} secondaryTextColor - The secondary text color for the landing page (e.g., "#333333")
|
|
9
24
|
* @property {Buffer} logo - A logo image file for the landing page, provided as a Buffer
|
|
25
|
+
* @property {string} [registrationType] - Which page type to build: "TEN_DLC" (default) or "TOLL_FREE"
|
|
26
|
+
* @property {TollFreeLandingData} [tollFree] - Toll-Free consent content; required when registrationType is "TOLL_FREE"
|
|
27
|
+
* @property {boolean} [useBrandTemplate] - Toll-Free only. Build the page from the brand's landing page template,
|
|
28
|
+
* taking its colors, logo and webhook URL from there. When set, no logo file is required. `description` is
|
|
29
|
+
* still sent by the caller, since the About paragraph names the services this campaign's use cases cover.
|
|
10
30
|
*/
|
|
11
31
|
|
|
12
32
|
/**
|
|
@@ -17,6 +37,21 @@
|
|
|
17
37
|
* @property {string} [primaryTextColor] - The primary text color for the landing page (e.g., "#000000")
|
|
18
38
|
* @property {string} [secondaryTextColor] - The secondary text color for the landing page (e.g., "#333333")
|
|
19
39
|
* @property {Buffer} [logo] - A logo image file for the landing page, provided as a Buffer
|
|
40
|
+
* @property {string} [registrationType] - Which page type to build: "TEN_DLC" or "TOLL_FREE"
|
|
41
|
+
* @property {TollFreeLandingData} [tollFree] - Replaces the whole Toll-Free consent subdocument when set
|
|
42
|
+
* @property {boolean} [useBrandTemplate] - Toll-Free only. Re-copy the brand's landing page template into this
|
|
43
|
+
* page, so a corrected logo or color reaches a page that already exists instead of creating a second one.
|
|
44
|
+
*/
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* @typedef {Object} LandingTemplateData
|
|
48
|
+
* @property {string} userDescription - The customer's own sentence about their business. Not the finished About
|
|
49
|
+
* paragraph: the services clause is added per campaign when a page is generated
|
|
50
|
+
* @property {string} [primaryBackgroundColor] - The primary background color (e.g., "#FFFFFF")
|
|
51
|
+
* @property {string} [secondaryBackgroundColor] - The secondary background color (e.g., "#F0F0F0")
|
|
52
|
+
* @property {string} [primaryTextColor] - The primary text color (e.g., "#000000")
|
|
53
|
+
* @property {string} [secondaryTextColor] - The secondary text color (e.g., "#333333")
|
|
54
|
+
* @property {string} [webhookUrl] - Where generated pages post opt-in submissions
|
|
20
55
|
*/
|
|
21
56
|
|
|
22
57
|
export class Landings {
|
|
@@ -139,6 +174,55 @@ export class Landings {
|
|
|
139
174
|
return this.client(`/landing/brand/${safeBrandId}`, { method: "GET", ...options });
|
|
140
175
|
}
|
|
141
176
|
|
|
177
|
+
/**
|
|
178
|
+
* Get a brand's Toll-Free landing page template — the reusable look every page the brand generates
|
|
179
|
+
* snapshots. Returns an empty array when the brand has no template.
|
|
180
|
+
* @async
|
|
181
|
+
* @roles api, admin, developer, billing, user
|
|
182
|
+
* @param {Object} params - The parameters for getting a landing page template
|
|
183
|
+
* @param {string} params.brandId - The brand ID to look up the template for
|
|
184
|
+
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
|
|
185
|
+
* @throws {Error} Throws an error if the brandId parameter is missing
|
|
186
|
+
* @returns {Promise<Object>} - The template returned from the server
|
|
187
|
+
*/
|
|
188
|
+
async getLandingTemplate({ brandId, options = {} }) {
|
|
189
|
+
this.client._require({ brandId });
|
|
190
|
+
const safeBrandId = encodeURIComponent(brandId);
|
|
191
|
+
return this.client(`/landing/template/${safeBrandId}`, { method: "GET", ...options });
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Create or replace a brand's Toll-Free landing page template. Editing a template never alters a page
|
|
196
|
+
* that already exists, so a URL already given to a carrier keeps rendering what was declared.
|
|
197
|
+
* @async
|
|
198
|
+
* @roles api, admin, developer, billing, user
|
|
199
|
+
* @param {Object} params - The parameters for saving a landing page template
|
|
200
|
+
* @param {string} params.brandId - The brand the template belongs to
|
|
201
|
+
* @param {LandingTemplateData} params.templateData - The template fields (see LandingTemplateData typedef)
|
|
202
|
+
* @param {Buffer} [params.file] - A logo image file, provided as a Buffer. Required the first time only;
|
|
203
|
+
* omit it on a later save to keep the stored logo
|
|
204
|
+
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
|
|
205
|
+
* @throws {Error} Throws an error if the brandId parameter is missing
|
|
206
|
+
* @returns {Promise<Object>} - The saved template returned from the server
|
|
207
|
+
*/
|
|
208
|
+
async upsertLandingTemplate({ brandId, templateData, file, options = {} }) {
|
|
209
|
+
this.client._require({ brandId });
|
|
210
|
+
const safeBrandId = encodeURIComponent(brandId);
|
|
211
|
+
const formData = new FormData();
|
|
212
|
+
|
|
213
|
+
if (file) {
|
|
214
|
+
formData.append("file", file);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
Object.entries(templateData).forEach(([key, value]) => {
|
|
218
|
+
if (value !== undefined) {
|
|
219
|
+
formData.append(key, typeof value === "object" ? JSON.stringify(value) : value);
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
return this.multipartClient(`/landing/template/${safeBrandId}`, { method: "PUT", body: formData, ...options });
|
|
224
|
+
}
|
|
225
|
+
|
|
142
226
|
async deleteLanding({ landingId, options = {} }) {
|
|
143
227
|
this.client._require({ landingId });
|
|
144
228
|
const safeLandingId = encodeURIComponent(landingId);
|
package/src/domains/Messages.js
CHANGED
|
@@ -5,6 +5,16 @@ export class Messages {
|
|
|
5
5
|
this.enableAdmin = enableAdmin;
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* Estimate Canadian SMS/MMS retail cost without sending or charging.
|
|
10
|
+
* @async
|
|
11
|
+
* @param {Object} params - Sender, up to 100 recipients, messageBody and request options.
|
|
12
|
+
* @returns {Promise<Object>} - Per-recipient rates and total in microdollars; unknown carriers use the upper fallback.
|
|
13
|
+
*/
|
|
14
|
+
async estimateMessage({ senderPhoneNumber, recipientPhoneNumbers, messageBody, messageType = "SMS", options = {} }) {
|
|
15
|
+
return this.client("/message/estimate", { method: "POST", body: { senderPhoneNumber, recipientPhoneNumbers, messageBody, messageType }, ...options });
|
|
16
|
+
}
|
|
17
|
+
|
|
8
18
|
/**
|
|
9
19
|
* Get a list of messages with optional filters and pagination parameters
|
|
10
20
|
* @async
|
|
@@ -18,19 +28,22 @@ export class Messages {
|
|
|
18
28
|
* @param {string} [params.status] - Filter messages by their status (ENQUEUED, DEQUEUED, SENT, FAILED, DELIVERED)
|
|
19
29
|
* @param {string} [params.direction] - Filter messages by their direction (INBOUND, OUTBOUND)
|
|
20
30
|
* @param {string|string[]} [params.messageType] - Filter messages by their type. Accepts a single value or an array (e.g. ["SMS", "MMS"]). Allowed values: SMS, MMS, RCS, WHATSAPP, VIBER, P2P. When omitted, defaults to all non-P2P types.
|
|
21
|
-
* @param {string|string[]} [params.channel] - Filter messages by channel. Accepts a single value or an array. Allowed values: tenDLC, tollFree, shortCode, p2p. Each message records its channel when it is saved, and this filters on that stored value; older messages from before this feature have no channel and count as tenDLC. Ignored when matchAny is true (matchAny takes precedence).
|
|
31
|
+
* @param {string|string[]} [params.channel] - Filter messages by channel. Accepts a single value or an array. Allowed values: tenDLC, virtualLongCode, tollFree, shortCode, p2p. Each message records its channel when it is saved, and this filters on that stored value; older messages from before this feature have no channel and count as tenDLC. Ignored when matchAny is true (matchAny takes precedence).
|
|
22
32
|
* @param {boolean} [params.matchAny] - When true, the provided campaignId/brandId/phoneNumber filters are OR'd (a message matches ANY of them) instead of the default most-specific-single behavior. subgroupId stays an AND scope. Opt-in/additive.
|
|
23
33
|
* @param {string} [params.carrier] - Filter messages by the carrier used for sending
|
|
34
|
+
* @param {string|string[]} [params.sentimentLabel] - Filter messages by sentiment bucket. Accepts a single value or an array (e.g. ["positive", "negative"]). Allowed values: positive, neutral, negative. Applied as the sentimentScore range the ±25 label threshold produces, so unscored messages match no bucket and outbound messages (never scored) are excluded.
|
|
24
35
|
* @param {string} [params.senderPhoneNumber] - Filter messages by the sender's 5-6 digit Short Code or 10+ digit phone number
|
|
25
36
|
* @param {string} [params.recipientPhoneNumber] - Filter messages by the recipient's phone number
|
|
26
37
|
* @param {string} [params.startDate] - ISO-8601 date or timestamp; normalized to start-of-UTC-day (inclusive)
|
|
27
38
|
* @param {string} [params.endDate] - ISO-8601 date or timestamp; normalized to end-of-UTC-day (inclusive). Hourly resolution is not supported
|
|
28
|
-
* @param {string} [params.sortField] - The field to sort the messages by
|
|
39
|
+
* @param {string} [params.sortField] - The field to sort the messages by (createdAt, segmentCount, status, sentimentScore)
|
|
29
40
|
* @param {string} [params.sortOrder] - The order to sort the messages (asc, desc)
|
|
30
41
|
* @param {number} [params.page] - The page number for pagination
|
|
31
42
|
* @param {number} [params.limit] - The number of messages per page
|
|
32
43
|
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
|
|
33
|
-
* @returns {Promise<Object>} - A promise that resolves to the list of messages
|
|
44
|
+
* @returns {Promise<Object>} - A promise that resolves to the list of messages. Inbound messages also carry
|
|
45
|
+
* sentimentScore (-100..100, null when unscored), sentimentLabel ("positive"|"neutral"|"negative", null when
|
|
46
|
+
* sentimentScore is null) and sentimentScoredAt. Outbound messages are never scored.
|
|
34
47
|
*/
|
|
35
48
|
async getMessages({
|
|
36
49
|
id,
|
|
@@ -47,6 +60,7 @@ export class Messages {
|
|
|
47
60
|
channel,
|
|
48
61
|
matchAny,
|
|
49
62
|
carrier,
|
|
63
|
+
sentimentLabel,
|
|
50
64
|
startDate,
|
|
51
65
|
endDate,
|
|
52
66
|
sortField,
|
|
@@ -55,7 +69,7 @@ export class Messages {
|
|
|
55
69
|
limit,
|
|
56
70
|
options = {},
|
|
57
71
|
}) {
|
|
58
|
-
const filters = { id, campaignId, brandId, subgroupId, groupId, phoneNumber, senderPhoneNumber, recipientPhoneNumber, status, direction, messageType, channel, matchAny, carrier, startDate, endDate, sortField, sortOrder, page, limit };
|
|
72
|
+
const filters = { id, campaignId, brandId, subgroupId, groupId, phoneNumber, senderPhoneNumber, recipientPhoneNumber, status, direction, messageType, channel, matchAny, carrier, sentimentLabel, startDate, endDate, sortField, sortOrder, page, limit };
|
|
59
73
|
const queryString = this.client._getQueryString(filters);
|
|
60
74
|
return this.client(`/message${queryString}`, { method: "GET", ...options });
|
|
61
75
|
}
|
|
@@ -86,20 +100,29 @@ export class Messages {
|
|
|
86
100
|
* @roles api, admin, developer, billing, user
|
|
87
101
|
* @param {Object} params - The parameters for getting analytics
|
|
88
102
|
* @param {string} [params.groupId] - Filter analytics by the ID of the associated group
|
|
89
|
-
* @param {string} [params.subgroupId] - Filter analytics by the ID of the associated subgroup
|
|
90
|
-
* @param {string} [params.brandId] - Filter analytics by the ID of the associated brand
|
|
91
|
-
* @param {string} [params.campaignId] - Filter analytics by the ID of the associated campaign
|
|
92
|
-
* @param {string} [params.phoneNumber] - Filter analytics by the phone number involved in the messages
|
|
93
|
-
* @param {string} [params.carrier] - Filter analytics by the carrier used for sending
|
|
103
|
+
* @param {string|string[]} [params.subgroupId] - Filter analytics by the ID of the associated subgroup. Accepts a single value, an array, or a comma-separated string.
|
|
104
|
+
* @param {string|string[]} [params.brandId] - Filter analytics by the ID of the associated brand. Accepts a single value, an array, or a comma-separated string.
|
|
105
|
+
* @param {string|string[]} [params.campaignId] - Filter analytics by the ID of the associated campaign. Accepts a single value, an array, or a comma-separated string.
|
|
106
|
+
* @param {string|string[]} [params.phoneNumber] - Filter analytics by the phone number involved in the messages. Accepts a single value, an array, or a comma-separated string.
|
|
107
|
+
* @param {string|string[]} [params.carrier] - Filter analytics by the carrier used for sending. Accepts a single value, an array, or a comma-separated string.
|
|
108
|
+
* @param {string|string[]} [params.carrierFamily] - Filter analytics by the recipient's resolved carrier family (Default, ATT, TMobile, Verizon, USCellular, GoogleVoice, ClearSky, Interop, RogueMobile, P2P). Accepts a single value, an array, or a comma-separated string. Only accepted where the environment serves hourly analytics; elsewhere any value is rejected with a 400 -- omit the parameter unless it is wanted.
|
|
94
109
|
* @param {string} [params.startDate] - ISO-8601 date or timestamp; normalized to start-of-UTC-day (inclusive)
|
|
95
110
|
* @param {string} [params.endDate] - ISO-8601 date or timestamp; normalized to end-of-UTC-day (inclusive). Hourly resolution is not supported
|
|
96
111
|
* @param {boolean} [params.matchAny] - When true, the provided campaignId/brandId/phoneNumber filters are OR'd (match ANY) instead of the default most-specific-single behavior. subgroupId stays an AND scope. Opt-in/additive.
|
|
97
|
-
* @param {string|string[]} [params.
|
|
112
|
+
* @param {(string|string[])} [params.messageType] - Message type(s) the SENTIMENT figures are scoped to: SMS, MMS or P2P (single value, array, or comma-separated string). Omit for all scored types. Does NOT narrow the message counts, which are always returned split per type (smsInbound/mmsInbound/p2pInbound) and have no filterable type dimension.
|
|
113
|
+
* @param {string|string[]} [params.channel] - Filter analytics by channel (tenDLC, virtualLongCode, tollFree, shortCode, p2p). Filters on the stored channel column; a tenDLC selection also includes older messages that have no channel, and p2p is a real channel here (matched by carrier). Accepts a single value or an array. Ignored when matchAny is true (matchAny takes precedence).
|
|
98
114
|
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
|
|
99
|
-
* @returns {Promise<Object>} - A promise that resolves to the analytics data
|
|
115
|
+
* @returns {Promise<Object>} - A promise that resolves to the analytics data. Also includes inbound-message
|
|
116
|
+
* sentiment for the requested scope: sentimentScore (volume-weighted average of every scored inbound message
|
|
117
|
+
* in range, -100..100, null when nothing was scored), sentimentLabel ("positive"|"neutral"|"negative", null
|
|
118
|
+
* when sentimentScore is null), sentimentScoredCount, sentimentPositive, sentimentNeutral, sentimentNegative.
|
|
119
|
+
* plus the same six per message type under smsSentiment*, mmsSentiment* and p2pSentiment* prefixes. Every
|
|
120
|
+
* score is divided server-side and the raw sums are never returned: a score is an average and must never be
|
|
121
|
+
* summed or re-averaged across types, rows or responses. To weight a subset of message types, pass
|
|
122
|
+
* messageType and read sentimentScore.
|
|
100
123
|
*/
|
|
101
|
-
async getAnalytics({ groupId, subgroupId, brandId, campaignId, phoneNumber, carrier, startDate, endDate, channel, matchAny, options = {} }) {
|
|
102
|
-
const filters = { groupId, subgroupId, brandId, campaignId, phoneNumber, carrier, startDate, endDate, channel, matchAny };
|
|
124
|
+
async getAnalytics({ groupId, subgroupId, brandId, campaignId, phoneNumber, carrier, carrierFamily, startDate, endDate, channel, messageType, matchAny, options = {} }) {
|
|
125
|
+
const filters = { groupId, subgroupId, brandId, campaignId, phoneNumber, carrier, carrierFamily, startDate, endDate, channel, messageType, matchAny };
|
|
103
126
|
const queryString = this.client._getQueryString(filters);
|
|
104
127
|
return this.client(`/message/analytics${queryString}`, { method: "GET", ...options });
|
|
105
128
|
}
|
|
@@ -110,19 +133,29 @@ export class Messages {
|
|
|
110
133
|
* @roles api, admin, developer, billing, user
|
|
111
134
|
* @param {Object} params - The parameters for getting detailed analytics
|
|
112
135
|
* @param {string} [params.groupId] - Filter analytics by the ID of the associated group
|
|
113
|
-
* @param {string} [params.subgroupId] - Filter analytics by the ID of the associated subgroup
|
|
114
|
-
* @param {string} [params.brandId] - Filter analytics by the ID of the associated brand
|
|
115
|
-
* @param {string} [params.campaignId] - Filter analytics by the ID of the associated campaign
|
|
116
|
-
* @param {string} [params.phoneNumber] - Filter analytics by the phone number involved in the messages
|
|
117
|
-
* @param {string} [params.carrier] - Filter analytics by the carrier used for sending
|
|
118
|
-
* @param {string} [params.
|
|
119
|
-
* @param {string} [params.
|
|
120
|
-
* @param {string
|
|
136
|
+
* @param {string|string[]} [params.subgroupId] - Filter analytics by the ID of the associated subgroup. Accepts a single value, an array, or a comma-separated string.
|
|
137
|
+
* @param {string|string[]} [params.brandId] - Filter analytics by the ID of the associated brand. Accepts a single value, an array, or a comma-separated string.
|
|
138
|
+
* @param {string|string[]} [params.campaignId] - Filter analytics by the ID of the associated campaign. Accepts a single value, an array, or a comma-separated string.
|
|
139
|
+
* @param {string|string[]} [params.phoneNumber] - Filter analytics by the phone number involved in the messages. Accepts a single value, an array, or a comma-separated string.
|
|
140
|
+
* @param {string|string[]} [params.carrier] - Filter analytics by the carrier used for sending. Accepts a single value, an array, or a comma-separated string.
|
|
141
|
+
* @param {string|string[]} [params.carrierFamily] - Filter analytics by the recipient's resolved carrier family (Default, ATT, TMobile, Verizon, USCellular, GoogleVoice, ClearSky, Interop, RogueMobile, P2P). Accepts a single value, an array, or a comma-separated string. Only accepted where the environment serves hourly analytics; elsewhere any value is rejected with a 400 -- omit the parameter unless it is wanted.
|
|
142
|
+
* @param {string} [params.startDate] - ISO-8601 date or timestamp. At day granularity it is normalized to start-of-UTC-day (inclusive); at hour granularity it is floored to its hour.
|
|
143
|
+
* @param {string} [params.endDate] - ISO-8601 date or timestamp. At day granularity it is normalized to end-of-UTC-day (inclusive); at hour granularity it is honoured as given.
|
|
144
|
+
* @param {(string|string[])} [params.messageType] - Message type(s) the SENTIMENT figures are scoped to: SMS, MMS or P2P (single value, array, or comma-separated string). Omit for all scored types. Does NOT narrow the message counts, which are always returned split per type (smsInbound/mmsInbound/p2pInbound) and have no filterable type dimension.
|
|
145
|
+
* @param {string|string[]} [params.channel] - Filter analytics by channel (tenDLC, virtualLongCode, tollFree, shortCode, p2p). Filters on the stored channel column; a tenDLC selection also includes older messages that have no channel, and p2p is a real channel here. Accepts a single value or an array.
|
|
146
|
+
* @param {("day"|"hour")} [params.granularity] - Time-bucket grain of the byDate rows. Omit for day (each row's _id is a "YYYY-MM-DD" date). "hour" buckets by hour (each row's _id is a "YYYY-MM-DD HH:MM:SS" UTC hour) and is capped to a 7-day span. Only accepted where the environment serves hourly analytics; elsewhere any value, including "day", is rejected with a 400 -- omit the parameter unless hour grain is wanted.
|
|
147
|
+
* @param {("carrier"|"carrierFamily")} [params.breakdown] - Adds a byBreakdown time × dimension series to the response ({ dimension, rows }: each row is one byDate bucket (_id) for one carrier or carrier family (key), over the top 50 keys by volume, 10DLC only) and caps the span at 31 days. Only accepted where the environment serves hourly analytics; elsewhere any value is rejected with a 400 -- omit the parameter unless it is wanted.
|
|
121
148
|
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
|
|
122
|
-
* @returns {Promise<Array>} - A promise that resolves to an array of analytics snapshot records
|
|
149
|
+
* @returns {Promise<Array>} - A promise that resolves to an array of analytics snapshot records. cardTotals and
|
|
150
|
+
* every byDate/byPhoneNumber/byCarrier row also carry that row's own inbound-message sentiment: sentimentScore
|
|
151
|
+
* (volume-weighted average, -100..100, null when nothing in that row's scope was scored), sentimentLabel,
|
|
152
|
+
* sentimentScoredCount, sentimentPositive, sentimentNeutral, sentimentNegative. The fields are always present;
|
|
153
|
+
* plus the same six per message type under smsSentiment*, mmsSentiment* and p2pSentiment* prefixes. Every
|
|
154
|
+
* score is divided server-side and the raw sums are never returned: a score is an average and must never be
|
|
155
|
+
* summed or re-averaged across types, rows or responses.
|
|
123
156
|
*/
|
|
124
|
-
async getAnalyticsDetail({ groupId, subgroupId, brandId, campaignId, phoneNumber, carrier, startDate, endDate, channel, options = {} }) {
|
|
125
|
-
const filters = { groupId, subgroupId, brandId, campaignId, phoneNumber, carrier, startDate, endDate, channel };
|
|
157
|
+
async getAnalyticsDetail({ groupId, subgroupId, brandId, campaignId, phoneNumber, carrier, carrierFamily, startDate, endDate, channel, messageType, granularity, breakdown, options = {} }) {
|
|
158
|
+
const filters = { groupId, subgroupId, brandId, campaignId, phoneNumber, carrier, carrierFamily, startDate, endDate, channel, messageType, granularity, breakdown };
|
|
126
159
|
const queryString = this.client._getQueryString(filters);
|
|
127
160
|
return this.client(`/message/analytics/detail${queryString}`, { method: "GET", ...options });
|
|
128
161
|
}
|
|
@@ -155,16 +188,19 @@ export class Messages {
|
|
|
155
188
|
* @param {string|string[]} [params.campaignId]
|
|
156
189
|
* @param {string|string[]} [params.phoneNumber]
|
|
157
190
|
* @param {string|string[]} [params.carrier]
|
|
191
|
+
* @param {string|string[]} [params.carrierFamily] - Resolved carrier family of the recipient (Default, ATT, TMobile, Verizon, USCellular, GoogleVoice, ClearSky, Interop, RogueMobile, P2P); single value, array, or comma-separated. Only accepted where the environment serves hourly analytics; elsewhere any value is rejected with a 400 -- omit the parameter unless it is wanted.
|
|
158
192
|
* @param {string} [params.startDate]
|
|
159
193
|
* @param {string} [params.endDate]
|
|
160
194
|
* @param {number} [params.page=1]
|
|
161
195
|
* @param {number} [params.limit=50] - max 50 per page
|
|
162
|
-
* @param {("tenDLC"|"tollFree"|"shortCode"|"p2p"|"both")|Array<"tenDLC"|"tollFree"|"shortCode"|"p2p">} [params.channel="both"] - Filter and rank rows by the stored channel column. "both" (default) means all activity. tenDLC/tollFree/shortCode/p2p (single value or array) limit to the selected channel(s).
|
|
196
|
+
* @param {("tenDLC"|"virtualLongCode"|"tollFree"|"shortCode"|"p2p"|"both")|Array<"tenDLC"|"virtualLongCode"|"tollFree"|"shortCode"|"p2p">} [params.channel="both"] - Filter and rank rows by the stored channel column. "both" (default) means all activity. tenDLC/virtualLongCode/tollFree/shortCode/p2p (single value or array) limit to the selected channel(s).
|
|
197
|
+
* @param {(string|string[])} [params.messageType] - Message type(s) the SENTIMENT figures are scoped to: SMS, MMS or P2P (single value, array, or comma-separated string). Omit for all scored types. Does NOT narrow the message counts, which are always returned split per type (smsInbound/mmsInbound/p2pInbound) and have no filterable type dimension.
|
|
163
198
|
* @param {import('../SignalHouseSDK').RequestOptions} [params.options]
|
|
164
199
|
* @returns {Promise<Object>} - { rows, totalCount, page, limit }. Each row carries sms/mms/p2p metric columns plus `smsOptOuts` and `mmsOptOuts` from the DNC analytics MV (P2P has no opt-outs).
|
|
200
|
+
* Each row also carries that subgroup's inbound-message sentiment: `sentimentScore` (volume-weighted average of every scored inbound message in that subgroup, -100..100, null when nothing was scored), `sentimentLabel`, `sentimentScoredCount`, `sentimentPositive`, `sentimentNeutral`, `sentimentNegative`, plus the same six per message type under `smsSentiment*`, `mmsSentiment*` and `p2pSentiment*` prefixes. The score is derived server-side and must never be re-averaged across rows — combine the counts, not the scores.
|
|
165
201
|
*/
|
|
166
|
-
async getAnalyticsBySubgroup({ groupId, subgroupId, brandId, campaignId, phoneNumber, carrier, startDate, endDate, page, limit, channel, options = {} }) {
|
|
167
|
-
const filters = { groupId, subgroupId, brandId, campaignId, phoneNumber, carrier, startDate, endDate, page, limit, channel };
|
|
202
|
+
async getAnalyticsBySubgroup({ groupId, subgroupId, brandId, campaignId, phoneNumber, carrier, carrierFamily, startDate, endDate, page, limit, channel, messageType, options = {} }) {
|
|
203
|
+
const filters = { groupId, subgroupId, brandId, campaignId, phoneNumber, carrier, carrierFamily, startDate, endDate, page, limit, channel, messageType };
|
|
168
204
|
const queryString = this.client._getQueryString(filters);
|
|
169
205
|
return this.client(`/message/analytics/by-subgroup${queryString}`, { method: "GET", ...options });
|
|
170
206
|
}
|
|
@@ -181,16 +217,17 @@ export class Messages {
|
|
|
181
217
|
* @param {string|string[]} [params.campaignId]
|
|
182
218
|
* @param {string|string[]} [params.phoneNumber]
|
|
183
219
|
* @param {string|string[]} [params.carrier]
|
|
220
|
+
* @param {string|string[]} [params.carrierFamily] - Resolved carrier family of the recipient (Default, ATT, TMobile, Verizon, USCellular, GoogleVoice, ClearSky, Interop, RogueMobile, P2P); single value, array, or comma-separated. Only accepted where the environment serves hourly analytics; elsewhere any value is rejected with a 400 -- omit the parameter unless it is wanted.
|
|
184
221
|
* @param {string} [params.startDate]
|
|
185
222
|
* @param {string} [params.endDate]
|
|
186
223
|
* @param {number} [params.page=1]
|
|
187
224
|
* @param {number} [params.limit=50] - max 50 per page
|
|
188
|
-
* @param {("tenDLC"|"tollFree"|"shortCode"|"p2p"|"both")|Array<"tenDLC"|"tollFree"|"shortCode"|"p2p">} [params.channel="both"] - Filter and rank rows by the stored channel column. "both" (default) means every code. tenDLC/tollFree/shortCode/p2p (single value or array) limit to the selected channel(s); when one channel is selected, totalErrors reflects only that channel.
|
|
225
|
+
* @param {("tenDLC"|"virtualLongCode"|"tollFree"|"shortCode"|"p2p"|"both")|Array<"tenDLC"|"virtualLongCode"|"tollFree"|"shortCode"|"p2p">} [params.channel="both"] - Filter and rank rows by the stored channel column. "both" (default) means every code. tenDLC/virtualLongCode/tollFree/shortCode/p2p (single value or array) limit to the selected channel(s); when one channel is selected, totalErrors reflects only that channel.
|
|
189
226
|
* @param {import('../SignalHouseSDK').RequestOptions} [params.options]
|
|
190
227
|
* @returns {Promise<Object>} - { rows, totalCount, totalErrors: { sms, mms, p2p, all }, page, limit }
|
|
191
228
|
*/
|
|
192
|
-
async getAnalyticsByErrorCode({ groupId, subgroupId, brandId, campaignId, phoneNumber, carrier, startDate, endDate, page, limit, channel, options = {} }) {
|
|
193
|
-
const filters = { groupId, subgroupId, brandId, campaignId, phoneNumber, carrier, startDate, endDate, page, limit, channel };
|
|
229
|
+
async getAnalyticsByErrorCode({ groupId, subgroupId, brandId, campaignId, phoneNumber, carrier, carrierFamily, startDate, endDate, page, limit, channel, options = {} }) {
|
|
230
|
+
const filters = { groupId, subgroupId, brandId, campaignId, phoneNumber, carrier, carrierFamily, startDate, endDate, page, limit, channel };
|
|
194
231
|
const queryString = this.client._getQueryString(filters);
|
|
195
232
|
return this.client(`/message/analytics/by-error-code${queryString}`, { method: "GET", ...options });
|
|
196
233
|
}
|
|
@@ -208,9 +245,9 @@ export class Messages {
|
|
|
208
245
|
* @param {string} [params.carrier] - Filter by the carrier
|
|
209
246
|
* @param {string} [params.startDate] - ISO-8601 date or timestamp; normalized to start-of-UTC-day (inclusive)
|
|
210
247
|
* @param {string} [params.endDate] - ISO-8601 date or timestamp; normalized to end-of-UTC-day (inclusive). Hourly resolution is not supported
|
|
211
|
-
* @param {string|string[]} [params.channel] - Filter by channel (tenDLC, tollFree, shortCode). Opt-outs are A2P-only, so p2p applies no filter. Filters on the stored channel column; a tenDLC selection also includes older opt-outs that have no channel.
|
|
248
|
+
* @param {string|string[]} [params.channel] - Filter by channel (tenDLC, virtualLongCode, tollFree, shortCode). Opt-outs are A2P-only, so p2p applies no filter. Filters on the stored channel column; a tenDLC selection also includes older opt-outs that have no channel.
|
|
212
249
|
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
|
|
213
|
-
* @returns {Promise<Object>} - A promise that resolves to the DNC analytics data (totals, byDate, byPhoneNumber, byCarrier)
|
|
250
|
+
* @returns {Promise<Object>} - A promise that resolves to the DNC analytics data (totals, byDate, byPhoneNumber, byCarrier, byKeyword). byKeyword breaks opt-outs down by the normalized keyword that revoked consent ({ optOutKeyword, total, sms, mms }); opt-outs recorded before keyword capture shipped appear as a single optOutKeyword: null bucket ("not recorded"). The distinct keyword set is open-ended (campaigns register their own keywords beyond the mandatory floor) — render top-N plus Other, never a fixed list.
|
|
214
251
|
*/
|
|
215
252
|
async getDncAnalytics({ groupId, subgroupId, brandId, campaignId, phoneNumber, carrier, startDate, endDate, channel, options = {} }) {
|
|
216
253
|
const filters = { groupId, subgroupId, brandId, campaignId, phoneNumber, carrier, startDate, endDate, channel };
|
|
@@ -235,9 +272,9 @@ export class Messages {
|
|
|
235
272
|
* @param {number} [params.limit] - Number of records per page
|
|
236
273
|
* @param {string} [params.sortField] - Field to sort by
|
|
237
274
|
* @param {string} [params.sortOrder] - Sort direction (asc, desc)
|
|
238
|
-
* @param {string|string[]} [params.channel] - Filter by channel (tenDLC, tollFree, shortCode). Opt-outs are A2P-only, so p2p applies no filter. Filters on the stored channel column; a tenDLC selection also includes older opt-outs that have no channel.
|
|
275
|
+
* @param {string|string[]} [params.channel] - Filter by channel (tenDLC, virtualLongCode, tollFree, shortCode). Opt-outs are A2P-only, so p2p applies no filter. Filters on the stored channel column; a tenDLC selection also includes older opt-outs that have no channel.
|
|
239
276
|
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
|
|
240
|
-
* @returns {Promise<Object>} - A promise that resolves to the paginated DNC records
|
|
277
|
+
* @returns {Promise<Object>} - A promise that resolves to the paginated DNC records. Each record carries optOutKeyword — the normalized keyword that revoked consent (e.g. "stop", "opt out"; a repeat opt-out records the most recent word), null for opt-outs recorded before keyword capture shipped — and carrierFamily, the resolved carrier family of the recipient number (Default, ATT, TMobile, Verizon, USCellular, GoogleVoice, ClearSky, Interop, RogueMobile), copied from the inbound message that triggered the opt-out.
|
|
241
278
|
*/
|
|
242
279
|
async getDncRecords({ groupId, subgroupId, brandId, campaignId, phoneNumber, carrier, startDate, endDate, page, limit, sortField, sortOrder, channel, options = {} }) {
|
|
243
280
|
const filters = { groupId, subgroupId, brandId, campaignId, phoneNumber, carrier, startDate, endDate, page, limit, sortField, sortOrder, channel };
|
|
@@ -261,7 +298,7 @@ export class Messages {
|
|
|
261
298
|
* @roles api, admin, developer, billing, user
|
|
262
299
|
* @param {Object} params - The parameters for sending an SMS message
|
|
263
300
|
* @param {string} params.senderPhoneNumber - The 5-6 digit Short Code or 10+ digit phone number to send the message from
|
|
264
|
-
* @param {string|string[]} params.recipientPhoneNumbers - The phone number(s) to send the message to
|
|
301
|
+
* @param {string|string[]} params.recipientPhoneNumbers - The 10+ digit phone number(s) to send the message to. A Short Code sender permits exactly one recipient, and it must be a +1 (US/Canada) number; a bare 10-digit number is treated as +1. The API rejects Short Code sends with multiple recipients or a non-+1 recipient.
|
|
265
302
|
* @param {string} params.messageBody - The body of the SMS message
|
|
266
303
|
* @param {string} [params.statusCallbackUrl] - The URL to receive status callbacks
|
|
267
304
|
* @param {boolean} [params.enableShortlink=false] - Whether to enable shortlink in the message
|
|
@@ -342,7 +379,7 @@ export class Messages {
|
|
|
342
379
|
* @roles api, admin, developer, billing, user
|
|
343
380
|
* @param {Object} params - The parameters for sending an MMS message
|
|
344
381
|
* @param {string} params.senderPhoneNumber - The 5-6 digit Short Code or 10+ digit phone number to send the message from
|
|
345
|
-
* @param {string[]} params.recipientPhoneNumbers - The phone number(s) to send the message to
|
|
382
|
+
* @param {string[]} params.recipientPhoneNumbers - The 10+ digit phone number(s) to send the message to. A Short Code sender permits exactly one recipient, and it must be a +1 (US/Canada) number; a bare 10-digit number is treated as +1. The API rejects Short Code sends with multiple recipients or a non-+1 recipient.
|
|
346
383
|
* @param {string} params.messageBody - The body of the MMS message
|
|
347
384
|
* @param {string[]} [params.mediaUrls] - The URLs of the media attachments
|
|
348
385
|
* @param {string} [params.statusCallbackUrl] - The URL to receive status callbacks
|