@signalhousellc/sdk 1.0.64 → 1.0.66
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 +19 -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 +114 -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/domains/Auth.js +36 -3
- package/src/domains/Brands.js +4 -4
- package/src/domains/Campaigns.js +21 -4
- package/src/domains/Groups.js +18 -1
- package/src/domains/Landings.js +84 -0
- package/src/domains/Messages.js +42 -21
- package/src/domains/Numbers.js +17 -3
- package/src/domains/Onboarding.js +7 -3
- package/src/domains/Subgroups.js +18 -0
- package/src/domains/Tickets.js +14 -0
- package/src/domains/voice/ProgrammableVoiceProfiles.js +4 -2
- package/src/domains/voice/Tokens.js +26 -0
- package/src/domains/voice/browser/Device.js +270 -24
package/src/domains/Brands.js
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
* @property {string} vertical - The vertical for the brand (PROFESSIONAL, REAL_ESTATE, HEALTHCARE, HUMAN_RESOURCES, ENERGY, ENTERTAINMENT, RETAIL, TRANSPORTATION, AGRICULTURE, INSURANCE, POSTAL, EDUCATION, HOSPITALITY, FINANCIAL, POLITICAL, GAMBLING, LEGAL, CONSTRUCTION, NGO, MANUFACTURING, GOVERNMENT, TECHNOLOGY, COMMUNICATION)
|
|
31
31
|
* @property {string} [referenceId] - A unique reference for the brand
|
|
32
32
|
* @property {Array<string>} [tag] - An array of tags to associate with the brand
|
|
33
|
-
* @property {boolean} [mock] - Whether to
|
|
33
|
+
* @property {boolean} [mock] - Whether to register the brand in TCR's mock environment instead of the live registry. TCR is still called and the mock brand auto-approves, so it does not exercise the rejection states a live registration can hit. Brand creation is not billed; campaign registration and number purchase are still billed as normal
|
|
34
34
|
* @property {string} [businessContactEmail] - The email address of the business contact for the brand (required if entityType is PUBLIC_PROFIT or NON_PROFIT)
|
|
35
35
|
*/
|
|
36
36
|
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
* @property {string} [altBusinessIdType] - The type of the alternative business identifier ("NONE", "DUNS", "LEI", "GIIN")
|
|
60
60
|
* @property {string} [brandRelationship] - Not in use - reserved for future use
|
|
61
61
|
* @property {string} [businessContactEmail] - The email address of the business contact for the brand (required if entityType is PUBLIC_PROFIT or NON_PROFIT)
|
|
62
|
-
* @property {Object} [tollFree] - Toll-Free editable fields, used when updating a Toll-Free brand. Optional sub-fields: legalEntityType, businessRegistrationType, taxId, countryCode, supportPhone, taxIdIssuingCountry, businessDBA, businessWebsite. (Toll-Free brands sync to Infobip; only DCA_PENDING/DCA_ACTIVE brands are editable and subgroupId is immutable.)
|
|
62
|
+
* @property {Object} [tollFree] - Toll-Free editable fields, used when updating a Toll-Free brand. Optional sub-fields: legalEntityType, businessRegistrationType, taxId, countryCode, supportPhone, taxIdIssuingCountry, businessDBA, businessWebsite. supportPhone must be E.164 with an optional leading "+" and no spaces, parentheses or hyphens (e.g. "17025550100"). (Toll-Free brands sync to Infobip; only DCA_PENDING/DCA_ACTIVE brands are editable and subgroupId is immutable.)
|
|
63
63
|
*/
|
|
64
64
|
|
|
65
65
|
/**
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
* @property {string} legalEntityType - The legal entity type (required, one of PRIVATE_COMPANY, PUBLIC_COMPANY, NON_PROFIT, GOVERNMENT, SOLE_PROPRIETOR)
|
|
69
69
|
* @property {string} taxId - The business tax identifier (required, at most 50 characters)
|
|
70
70
|
* @property {string} countryCode - The business country code (required, 2-letter ISO code)
|
|
71
|
-
* @property {string} supportPhone - The customer-support phone number (required,
|
|
71
|
+
* @property {string} supportPhone - The customer-support phone number (required, E.164 with an optional leading "+" and no spaces, parentheses or hyphens, e.g. "17025550100")
|
|
72
72
|
* @property {string} [taxIdIssuingCountry] - The country that issued the tax ID (optional, 2-letter ISO code)
|
|
73
73
|
* @property {string} [businessDBA] - The business "doing business as" name (optional, at most 255 characters)
|
|
74
74
|
* @property {string} [businessWebsite] - The customer's real website, sent to Infobip for brand verification (optional, valid URL, at most 255 characters; distinct from the top-level website / landing URL)
|
|
@@ -90,7 +90,7 @@
|
|
|
90
90
|
* @property {TollFreeBrandDetails} tollFree - The Toll-Free brand details (required)
|
|
91
91
|
* @property {string} [referenceId] - A unique reference for the brand (optional, at most 50 characters)
|
|
92
92
|
* @property {Array<string>} [tag] - An array of tags to associate with the brand (optional)
|
|
93
|
-
* @property {boolean} [mock] -
|
|
93
|
+
* @property {boolean} [mock] - Accepted and stored, but has no effect on Toll-Free registration: Toll-Free does not use TCR and is already free
|
|
94
94
|
* @property {string} [optInLink] - A URL linking to the opt-in flow for the brand (optional, valid URL, at most 255 characters)
|
|
95
95
|
* @property {string} [privacyPolicyLink] - A URL linking to the privacy policy for the brand (optional, valid URL, at most 255 characters)
|
|
96
96
|
* @property {string} [termsAndConditionsLink] - A URL linking to the terms and conditions for the brand (optional, valid URL, at most 255 characters)
|
package/src/domains/Campaigns.js
CHANGED
|
@@ -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
|
/**
|
|
@@ -261,6 +264,15 @@ export class Campaigns {
|
|
|
261
264
|
* @param {string} [params.sortOrder] - Sort direction ("asc" or "desc")
|
|
262
265
|
* @param {string} [params.registrationType] - Filter by registration type ("TEN_DLC", "TOLL_FREE", or "SHORT_CODE")
|
|
263
266
|
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
|
|
267
|
+
*
|
|
268
|
+
* Every record carries a `sentiment` object -- trailing 7-day and 30-day inbound reply sentiment,
|
|
269
|
+
* refreshed periodically from analytics rather than computed per request: `{ sevenDay, thirtyDay,
|
|
270
|
+
* updatedAt }`, each window being `{ score, label, scoredCount, positive, neutral, negative }`. The
|
|
271
|
+
* object is always present and fully populated, so it can be read without a presence check.
|
|
272
|
+
* `score` is a volume-weighted average in -100..100 and is null when nothing was scored in the
|
|
273
|
+
* window, which is not the same as a score of 0 -- null means nobody replied, 0 means replies
|
|
274
|
+
* averaged neutral. `updatedAt` is null until the first rollup writes the record, and it tracks when
|
|
275
|
+
* the figures last CHANGED, not when the job last ran.
|
|
264
276
|
* @returns {Promise<Array|Object>} The response from the server - array when unpaginated, or { data, total, page, limit, totalPages } when paginated
|
|
265
277
|
*/
|
|
266
278
|
async getCampaigns({
|
|
@@ -441,13 +453,18 @@ export class Campaigns {
|
|
|
441
453
|
* @roles api, admin, developer, user
|
|
442
454
|
* @param {Object} params - The parameters for capturing the opt-in image
|
|
443
455
|
* @param {string} params.brandId - The ID of the brand whose generated landing page should be captured
|
|
456
|
+
* @param {string} [params.landingId] - The specific page to capture. Required for Toll-Free brands, which have
|
|
457
|
+
* one page per campaign — omitted, the request is refused rather than guessing which page to shoot. A 10DLC
|
|
458
|
+
* brand has a single page, so it may be omitted there
|
|
444
459
|
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
|
|
445
460
|
* @throws {Error} Throws an error if the brandId parameter is missing
|
|
446
461
|
* @returns {Promise<Object>} The response from the server containing the hosted image's id and URL
|
|
447
462
|
*/
|
|
448
|
-
async captureOptInImageFromLanding({ brandId, options = {} }) {
|
|
463
|
+
async captureOptInImageFromLanding({ brandId, landingId, options = {} }) {
|
|
449
464
|
this.client._require({ brandId });
|
|
450
|
-
|
|
465
|
+
const body = { brandId };
|
|
466
|
+
if (landingId) body.landingId = landingId;
|
|
467
|
+
return this.client(`/campaign/opt-in-image/from-landing`, { method: 'POST', body, ...options });
|
|
451
468
|
}
|
|
452
469
|
|
|
453
470
|
/**
|
package/src/domains/Groups.js
CHANGED
|
@@ -6,6 +6,23 @@ export class Groups {
|
|
|
6
6
|
// Hidden Admin namespace INSIDE the domain
|
|
7
7
|
if (enableAdmin) {
|
|
8
8
|
this.admin = {
|
|
9
|
+
/**
|
|
10
|
+
* Get resource counts grouped by group ID. Only signalhouse_admin can query all groups;
|
|
11
|
+
* every other allowed role is restricted to its JWT group scope.
|
|
12
|
+
* @async
|
|
13
|
+
* @roles signalhouse, api, admin, developer, billing, user
|
|
14
|
+
* @param {Object} [params] - Optional group-count filters and pagination.
|
|
15
|
+
* @param {string} [params.groupId] - Restrict results to a group.
|
|
16
|
+
* @param {number} [params.limit] - Maximum rows to return.
|
|
17
|
+
* @param {number} [params.offset] - Rows to skip; requires limit.
|
|
18
|
+
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
|
|
19
|
+
* @returns {Promise<Object>} - Group-level resource count rows.
|
|
20
|
+
*/
|
|
21
|
+
getGroupCounts: async ({ groupId, limit, offset, options = {} } = {}) => {
|
|
22
|
+
const queryString = this.client._getQueryString({ groupId, limit, offset });
|
|
23
|
+
return this.client(`/group/counts${queryString}`, { method: "GET", ...options });
|
|
24
|
+
},
|
|
25
|
+
|
|
9
26
|
/**
|
|
10
27
|
* Get a list of all groups with optional pagination parameters
|
|
11
28
|
* @async
|
|
@@ -27,7 +44,7 @@ export class Groups {
|
|
|
27
44
|
* @async
|
|
28
45
|
* @roles signalhouse
|
|
29
46
|
* @param {Object} params - The parameters for creating a new group
|
|
30
|
-
* @param {Object} params.groupData - The data for the new group, including required fields such as groupName
|
|
47
|
+
* @param {Object} params.groupData - The data for the new group, including required fields such as groupName. Optionally accepts `psPartnerKey` and `ownerEmail` to credit a referring partner.
|
|
31
48
|
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
|
|
32
49
|
* @throws {Error} Throws an error if the groupData parameter is missing or if required fields within groupData are missing
|
|
33
50
|
* @returns {Promise<Object>} - The created group object returned from the server
|
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
|
@@ -21,16 +21,19 @@ export class Messages {
|
|
|
21
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).
|
|
22
22
|
* @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
23
|
* @param {string} [params.carrier] - Filter messages by the carrier used for sending
|
|
24
|
+
* @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
25
|
* @param {string} [params.senderPhoneNumber] - Filter messages by the sender's 5-6 digit Short Code or 10+ digit phone number
|
|
25
26
|
* @param {string} [params.recipientPhoneNumber] - Filter messages by the recipient's phone number
|
|
26
27
|
* @param {string} [params.startDate] - ISO-8601 date or timestamp; normalized to start-of-UTC-day (inclusive)
|
|
27
28
|
* @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
|
|
29
|
+
* @param {string} [params.sortField] - The field to sort the messages by (createdAt, segmentCount, status, sentimentScore)
|
|
29
30
|
* @param {string} [params.sortOrder] - The order to sort the messages (asc, desc)
|
|
30
31
|
* @param {number} [params.page] - The page number for pagination
|
|
31
32
|
* @param {number} [params.limit] - The number of messages per page
|
|
32
33
|
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
|
|
33
|
-
* @returns {Promise<Object>} - A promise that resolves to the list of messages
|
|
34
|
+
* @returns {Promise<Object>} - A promise that resolves to the list of messages. Inbound messages also carry
|
|
35
|
+
* sentimentScore (-100..100, null when unscored), sentimentLabel ("positive"|"neutral"|"negative", null when
|
|
36
|
+
* sentimentScore is null) and sentimentScoredAt. Outbound messages are never scored.
|
|
34
37
|
*/
|
|
35
38
|
async getMessages({
|
|
36
39
|
id,
|
|
@@ -47,6 +50,7 @@ export class Messages {
|
|
|
47
50
|
channel,
|
|
48
51
|
matchAny,
|
|
49
52
|
carrier,
|
|
53
|
+
sentimentLabel,
|
|
50
54
|
startDate,
|
|
51
55
|
endDate,
|
|
52
56
|
sortField,
|
|
@@ -55,7 +59,7 @@ export class Messages {
|
|
|
55
59
|
limit,
|
|
56
60
|
options = {},
|
|
57
61
|
}) {
|
|
58
|
-
const filters = { id, campaignId, brandId, subgroupId, groupId, phoneNumber, senderPhoneNumber, recipientPhoneNumber, status, direction, messageType, channel, matchAny, carrier, startDate, endDate, sortField, sortOrder, page, limit };
|
|
62
|
+
const filters = { id, campaignId, brandId, subgroupId, groupId, phoneNumber, senderPhoneNumber, recipientPhoneNumber, status, direction, messageType, channel, matchAny, carrier, sentimentLabel, startDate, endDate, sortField, sortOrder, page, limit };
|
|
59
63
|
const queryString = this.client._getQueryString(filters);
|
|
60
64
|
return this.client(`/message${queryString}`, { method: "GET", ...options });
|
|
61
65
|
}
|
|
@@ -86,20 +90,28 @@ export class Messages {
|
|
|
86
90
|
* @roles api, admin, developer, billing, user
|
|
87
91
|
* @param {Object} params - The parameters for getting analytics
|
|
88
92
|
* @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
|
|
93
|
+
* @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.
|
|
94
|
+
* @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.
|
|
95
|
+
* @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.
|
|
96
|
+
* @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.
|
|
97
|
+
* @param {string|string[]} [params.carrier] - Filter analytics by the carrier used for sending. Accepts a single value, an array, or a comma-separated string.
|
|
94
98
|
* @param {string} [params.startDate] - ISO-8601 date or timestamp; normalized to start-of-UTC-day (inclusive)
|
|
95
99
|
* @param {string} [params.endDate] - ISO-8601 date or timestamp; normalized to end-of-UTC-day (inclusive). Hourly resolution is not supported
|
|
96
100
|
* @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.
|
|
101
|
+
* @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.
|
|
97
102
|
* @param {string|string[]} [params.channel] - Filter analytics by channel (tenDLC, 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
103
|
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
|
|
99
|
-
* @returns {Promise<Object>} - A promise that resolves to the analytics data
|
|
104
|
+
* @returns {Promise<Object>} - A promise that resolves to the analytics data. Also includes inbound-message
|
|
105
|
+
* sentiment for the requested scope: sentimentScore (volume-weighted average of every scored inbound message
|
|
106
|
+
* in range, -100..100, null when nothing was scored), sentimentLabel ("positive"|"neutral"|"negative", null
|
|
107
|
+
* when sentimentScore is null), sentimentScoredCount, sentimentPositive, sentimentNeutral, sentimentNegative.
|
|
108
|
+
* plus the same six per message type under smsSentiment*, mmsSentiment* and p2pSentiment* prefixes. Every
|
|
109
|
+
* score is divided server-side and the raw sums are never returned: a score is an average and must never be
|
|
110
|
+
* summed or re-averaged across types, rows or responses. To weight a subset of message types, pass
|
|
111
|
+
* messageType and read sentimentScore.
|
|
100
112
|
*/
|
|
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 };
|
|
113
|
+
async getAnalytics({ groupId, subgroupId, brandId, campaignId, phoneNumber, carrier, startDate, endDate, channel, messageType, matchAny, options = {} }) {
|
|
114
|
+
const filters = { groupId, subgroupId, brandId, campaignId, phoneNumber, carrier, startDate, endDate, channel, messageType, matchAny };
|
|
103
115
|
const queryString = this.client._getQueryString(filters);
|
|
104
116
|
return this.client(`/message/analytics${queryString}`, { method: "GET", ...options });
|
|
105
117
|
}
|
|
@@ -110,19 +122,26 @@ export class Messages {
|
|
|
110
122
|
* @roles api, admin, developer, billing, user
|
|
111
123
|
* @param {Object} params - The parameters for getting detailed analytics
|
|
112
124
|
* @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
|
|
125
|
+
* @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.
|
|
126
|
+
* @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.
|
|
127
|
+
* @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.
|
|
128
|
+
* @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.
|
|
129
|
+
* @param {string|string[]} [params.carrier] - Filter analytics by the carrier used for sending. Accepts a single value, an array, or a comma-separated string.
|
|
118
130
|
* @param {string} [params.startDate] - ISO-8601 date or timestamp; normalized to start-of-UTC-day (inclusive)
|
|
119
131
|
* @param {string} [params.endDate] - ISO-8601 date or timestamp; normalized to end-of-UTC-day (inclusive). Hourly resolution is not supported
|
|
132
|
+
* @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.
|
|
120
133
|
* @param {string|string[]} [params.channel] - Filter analytics by channel (tenDLC, 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.
|
|
121
134
|
* @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
|
|
135
|
+
* @returns {Promise<Array>} - A promise that resolves to an array of analytics snapshot records. cardTotals and
|
|
136
|
+
* every byDate/byPhoneNumber/byCarrier row also carry that row's own inbound-message sentiment: sentimentScore
|
|
137
|
+
* (volume-weighted average, -100..100, null when nothing in that row's scope was scored), sentimentLabel,
|
|
138
|
+
* sentimentScoredCount, sentimentPositive, sentimentNeutral, sentimentNegative. The fields are always present;
|
|
139
|
+
* plus the same six per message type under smsSentiment*, mmsSentiment* and p2pSentiment* prefixes. Every
|
|
140
|
+
* score is divided server-side and the raw sums are never returned: a score is an average and must never be
|
|
141
|
+
* summed or re-averaged across types, rows or responses.
|
|
123
142
|
*/
|
|
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 };
|
|
143
|
+
async getAnalyticsDetail({ groupId, subgroupId, brandId, campaignId, phoneNumber, carrier, startDate, endDate, channel, messageType, options = {} }) {
|
|
144
|
+
const filters = { groupId, subgroupId, brandId, campaignId, phoneNumber, carrier, startDate, endDate, channel, messageType };
|
|
126
145
|
const queryString = this.client._getQueryString(filters);
|
|
127
146
|
return this.client(`/message/analytics/detail${queryString}`, { method: "GET", ...options });
|
|
128
147
|
}
|
|
@@ -160,11 +179,13 @@ export class Messages {
|
|
|
160
179
|
* @param {number} [params.page=1]
|
|
161
180
|
* @param {number} [params.limit=50] - max 50 per page
|
|
162
181
|
* @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).
|
|
182
|
+
* @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
183
|
* @param {import('../SignalHouseSDK').RequestOptions} [params.options]
|
|
164
184
|
* @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).
|
|
185
|
+
* 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
186
|
*/
|
|
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 };
|
|
187
|
+
async getAnalyticsBySubgroup({ groupId, subgroupId, brandId, campaignId, phoneNumber, carrier, startDate, endDate, page, limit, channel, messageType, options = {} }) {
|
|
188
|
+
const filters = { groupId, subgroupId, brandId, campaignId, phoneNumber, carrier, startDate, endDate, page, limit, channel, messageType };
|
|
168
189
|
const queryString = this.client._getQueryString(filters);
|
|
169
190
|
return this.client(`/message/analytics/by-subgroup${queryString}`, { method: "GET", ...options });
|
|
170
191
|
}
|
package/src/domains/Numbers.js
CHANGED
|
@@ -77,6 +77,15 @@ export class Numbers {
|
|
|
77
77
|
* @param {number} [params.page] - The page number for pagination (default: 1)
|
|
78
78
|
* @param {number} [params.limit] - The number of items per page for pagination (default: 20)
|
|
79
79
|
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
|
|
80
|
+
*
|
|
81
|
+
* Every record carries a `sentiment` object -- trailing 7-day and 30-day inbound reply sentiment,
|
|
82
|
+
* refreshed periodically from analytics rather than computed per request: `{ sevenDay, thirtyDay,
|
|
83
|
+
* updatedAt }`, each window being `{ score, label, scoredCount, positive, neutral, negative }`. The
|
|
84
|
+
* object is always present and fully populated, so it can be read without a presence check.
|
|
85
|
+
* `score` is a volume-weighted average in -100..100 and is null when nothing was scored in the
|
|
86
|
+
* window, which is not the same as a score of 0 -- null means nobody replied, 0 means replies
|
|
87
|
+
* averaged neutral. `updatedAt` is null until the first rollup writes the record, and it tracks when
|
|
88
|
+
* the figures last CHANGED, not when the job last ran.
|
|
80
89
|
* @returns {Promise<Object>} A promise that resolves to the list of phone numbers
|
|
81
90
|
*/
|
|
82
91
|
async getPhoneNumbers({ phoneNumber, campaignId, brandId, subgroupId, groupId, page, limit, options = {} }) {
|
|
@@ -254,6 +263,8 @@ export class Numbers {
|
|
|
254
263
|
* @param {string} params.phoneNumber - The phone number to update
|
|
255
264
|
* @param {Object} params.updateData - The data to update for the phone number
|
|
256
265
|
* @param {string} [params.updateData.friendlyName] - An optional friendly name for the phone number
|
|
266
|
+
* @param {string|null} [params.updateData.primaryInboundWebhookUrl] - Primary inbound voice webhook URL (http/https). When set, inbound calls to this number are driven by the SHML your webhook returns (programmable call control). Pass null or an empty string to clear.
|
|
267
|
+
* @param {string|null} [params.updateData.secondaryInboundWebhookUrl] - Secondary inbound voice webhook URL (http/https), used for failover when the primary returns an error. Pass null or an empty string to clear.
|
|
257
268
|
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
|
|
258
269
|
* @throws {Error} Throws an error if the phoneNumber or updateData parameter is missing
|
|
259
270
|
* @returns {Promise<Object>} A promise that resolves to the updated phone number object
|
|
@@ -339,15 +350,18 @@ export class Numbers {
|
|
|
339
350
|
}
|
|
340
351
|
|
|
341
352
|
/**
|
|
342
|
-
* Assign phone numbers to a campaign by providing the campaign ID and a list of phone numbers to assign
|
|
353
|
+
* Assign phone numbers to a campaign by providing the campaign ID and a list of phone numbers to assign.
|
|
354
|
+
* Numbers that are not found, already RELEASED, already assigned to a different campaign, on a mismatched
|
|
355
|
+
* DCA, or (for a 10DLC campaign without a number pool) beyond the remaining 49-number-per-campaign limit
|
|
356
|
+
* are not queued - each is reported back individually in `skipped` instead of failing the whole request.
|
|
343
357
|
* @async
|
|
344
358
|
* @roles api, admin, developer, billing, user
|
|
345
359
|
* @param {Object} params - The parameters for assigning phone numbers to a campaign
|
|
346
360
|
* @param {string} params.campaignId - The ID of the campaign to assign phone numbers to
|
|
347
361
|
* @param {string[]} params.phoneNumbers - The list of phone numbers to assign to the campaign
|
|
348
362
|
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
|
|
349
|
-
* @throws {Error} Throws an error if the campaignId or phoneNumbers parameter is missing
|
|
350
|
-
* @returns {Promise<Object>} A promise that resolves to
|
|
363
|
+
* @throws {Error} Throws an error if the campaignId or phoneNumbers parameter is missing, if none of the phone numbers exist in the account, or if the campaign is not found or in a terminal state
|
|
364
|
+
* @returns {Promise<Object>} A promise that resolves to `{ Message, queued, skipped }` - `queued` numbers were sent for assignment; `skipped` numbers were rejected (not found, RELEASED, already assigned to a campaign, cross-DCA mismatch, or over the 49-number limit).
|
|
351
365
|
*/
|
|
352
366
|
async assignPhoneNumberToCampaign({ campaignId, phoneNumbers, options = {} }) {
|
|
353
367
|
this.client._require({ campaignId, phoneNumbers });
|
|
@@ -38,12 +38,16 @@ export class Onboarding {
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
/**
|
|
41
|
-
* Get the caller's own onboarding record (customer-safe projection)
|
|
42
|
-
*
|
|
41
|
+
* Get the caller's own onboarding record (customer-safe projection) — the selections captured at
|
|
42
|
+
* signup plus the gate flags derived from them. Never returns internal KYC, staff assignment,
|
|
43
|
+
* referral, or external-reference data.
|
|
44
|
+
*
|
|
45
|
+
* Staff roles and sessions with no active group receive a synthetic verified, selection-free
|
|
46
|
+
* record rather than an error, so callers never have to special-case them.
|
|
43
47
|
* @async
|
|
44
48
|
* @param {Object} [params] - Optional parameters
|
|
45
49
|
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
|
|
46
|
-
* @returns {Promise<Object>} - `{ acceptedTermsOfService: boolean, emailVerified: boolean }`
|
|
50
|
+
* @returns {Promise<Object>} - `{ acceptedTermsOfService: boolean, emailVerified: boolean, products: string[], estimatedVolume: string|null, pendingExternalLink: "ghl"|"shopify"|null }`
|
|
47
51
|
*/
|
|
48
52
|
async getMyOnboarding({ options = {} } = {}) {
|
|
49
53
|
return this.client(`/group/onboarding/my`, { method: "GET", ...options });
|
package/src/domains/Subgroups.js
CHANGED
|
@@ -60,6 +60,24 @@ export class Subgroups {
|
|
|
60
60
|
return this.client(`/subgroup${queryString}`, { method: "GET", ...options });
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
+
/**
|
|
64
|
+
* Get resource counts grouped by subgroup ID. Only signalhouse_admin can query all groups;
|
|
65
|
+
* every other allowed role is restricted to its JWT group scope.
|
|
66
|
+
* @async
|
|
67
|
+
* @roles signalhouse, api, admin, developer, billing, user
|
|
68
|
+
* @param {Object} [params={}] - Optional count filters.
|
|
69
|
+
* @param {string} [params.groupId] - Restrict results to a group.
|
|
70
|
+
* @param {string} [params.subgroupId] - Restrict results to a subgroup.
|
|
71
|
+
* @param {number} [params.limit] - Maximum rows to return.
|
|
72
|
+
* @param {number} [params.offset] - Rows to skip; requires limit.
|
|
73
|
+
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
|
|
74
|
+
* @returns {Promise<Object>} - Subgroup-level resource count rows.
|
|
75
|
+
*/
|
|
76
|
+
async getSubgroupCounts({ groupId, subgroupId, limit, offset, options = {} } = {}) {
|
|
77
|
+
const queryString = this.client._getQueryString({ groupId, subgroupId, limit, offset });
|
|
78
|
+
return this.client(`/subgroup/counts${queryString}`, { method: "GET", ...options });
|
|
79
|
+
}
|
|
80
|
+
|
|
63
81
|
/**
|
|
64
82
|
* Create a new subgroup with the specified subgroup data
|
|
65
83
|
* @async
|
package/src/domains/Tickets.js
CHANGED
|
@@ -32,6 +32,20 @@ export class Tickets {
|
|
|
32
32
|
return this.client(`/admin/ticket/jira/epics${queryString}`, { method: "GET", ...options });
|
|
33
33
|
},
|
|
34
34
|
|
|
35
|
+
/**
|
|
36
|
+
* Search open non-Epic, non-Subtask issues for the Subtask parent picker. Staff-only.
|
|
37
|
+
* @async
|
|
38
|
+
* @roles signalhouse
|
|
39
|
+
* @param {Object} [params]
|
|
40
|
+
* @param {string} [params.query] - Optional issue summary/key filter
|
|
41
|
+
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
|
|
42
|
+
* @returns {Promise<Object>} - `{ issues: Array<{ id, key, summary }> }`
|
|
43
|
+
*/
|
|
44
|
+
searchJiraParentIssues: async ({ query, options = {} } = {}) => {
|
|
45
|
+
const queryString = this.client._getQueryString({ query });
|
|
46
|
+
return this.client(`/admin/ticket/jira/parent-issues${queryString}`, { method: "GET", ...options });
|
|
47
|
+
},
|
|
48
|
+
|
|
35
49
|
/**
|
|
36
50
|
* Search assignable Jira users for the assignee picker. Staff-only.
|
|
37
51
|
* @async
|
|
@@ -3,11 +3,12 @@
|
|
|
3
3
|
* @property {string} name - Profile name (required).
|
|
4
4
|
* @property {string[]} subgroupIds - Subgroups this profile spans (required, at least one).
|
|
5
5
|
* @property {string} [region] - Region/POP label.
|
|
6
|
-
* @property {"FORWARD"|"WEBRTC"|"SIP_TRUNK"|"SIP_PROFILE"} [routeAction] - Inbound call action (default "FORWARD"). Deliver the call to a PSTN number (FORWARD), ring the profile's subgroup registered softphones (WEBRTC), send to a SIP trunk (SIP_TRUNK),
|
|
6
|
+
* @property {"FORWARD"|"WEBRTC"|"SIP_TRUNK"|"SIP_PROFILE"|"CALL_CONTROL"} [routeAction] - Inbound call action (default "FORWARD"). Deliver the call to a PSTN number (FORWARD), ring the profile's subgroup registered softphones (WEBRTC), send to a SIP trunk (SIP_TRUNK), ring a registered SIP endpoint (SIP_PROFILE), or hand the call to your programmable call-control webhook that returns SHML (CALL_CONTROL).
|
|
7
7
|
* @property {string} [forwardToE164] - Destination number, required when routeAction is "FORWARD".
|
|
8
8
|
* @property {number} [forwardAfterSeconds] - Ring seconds before the action fires.
|
|
9
9
|
* @property {string} [routeSipTrunkId] - SIP trunk id, required when routeAction is "SIP_TRUNK".
|
|
10
10
|
* @property {string} [routeSipProfileId] - SIP endpoint id, required when routeAction is "SIP_PROFILE".
|
|
11
|
+
* @property {string} [webhookUrl] - Your inbound voice webhook (SHML program URL), required when routeAction is "CALL_CONTROL". Inbound calls to this profile's numbers are driven by the SHML your webhook returns.
|
|
11
12
|
* @property {boolean} [recordingEnabled] - Record calls on this profile.
|
|
12
13
|
* @property {boolean} [enabled] - Active state (default true).
|
|
13
14
|
*/
|
|
@@ -17,11 +18,12 @@
|
|
|
17
18
|
* @property {string} [name] - Profile name.
|
|
18
19
|
* @property {string[]} [subgroupIds] - Subgroups this profile spans.
|
|
19
20
|
* @property {string|null} [region] - Region/POP label.
|
|
20
|
-
* @property {"FORWARD"|"WEBRTC"|"SIP_TRUNK"|"SIP_PROFILE"} [routeAction] - Inbound call action (FORWARD | WEBRTC | SIP_TRUNK | SIP_PROFILE).
|
|
21
|
+
* @property {"FORWARD"|"WEBRTC"|"SIP_TRUNK"|"SIP_PROFILE"|"CALL_CONTROL"} [routeAction] - Inbound call action (FORWARD | WEBRTC | SIP_TRUNK | SIP_PROFILE | CALL_CONTROL).
|
|
21
22
|
* @property {string|null} [forwardToE164] - FORWARD destination.
|
|
22
23
|
* @property {number|null} [forwardAfterSeconds] - Ring seconds before the action fires.
|
|
23
24
|
* @property {string|null} [routeSipTrunkId] - SIP trunk id (required when routeAction is "SIP_TRUNK").
|
|
24
25
|
* @property {string|null} [routeSipProfileId] - SIP endpoint id (required when routeAction is "SIP_PROFILE").
|
|
26
|
+
* @property {string|null} [webhookUrl] - Inbound voice webhook / SHML program URL (required when routeAction is "CALL_CONTROL"). Pass null to clear.
|
|
25
27
|
* @property {boolean} [recordingEnabled] - Record calls on this profile.
|
|
26
28
|
* @property {boolean} [enabled] - Active state.
|
|
27
29
|
*/
|
|
@@ -61,4 +61,30 @@ export class Tokens {
|
|
|
61
61
|
async create({ tokenData = {}, options = {} } = {}) {
|
|
62
62
|
return this.client(`/voice/tokens`, { method: "POST", body: tokenData, ...options });
|
|
63
63
|
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Refresh (extend) an existing voice token in place — identity-preserving.
|
|
67
|
+
* Wraps voice-backend's `/voice/tokens/refresh`. Keeps the same wrtc_
|
|
68
|
+
* identity + SIP credentials and only pushes out `expires_at`, so a
|
|
69
|
+
* long-lived softphone stays registered without re-establishing its SIP
|
|
70
|
+
* registration (unlike `create()`, which mints a NEW identity). Provide the
|
|
71
|
+
* current `token` (its identity is decoded server-side) or the `identity`
|
|
72
|
+
* directly. Rejects with a 404 when the token no longer exists for the
|
|
73
|
+
* account — mint a fresh one with `create()` in that case.
|
|
74
|
+
* @async
|
|
75
|
+
* @roles api, admin, developer, billing, user
|
|
76
|
+
* @param {Object} [params] - Request parameters.
|
|
77
|
+
* @param {string} [params.token] - The current voice token (JWT) whose identity to extend.
|
|
78
|
+
* @param {string} [params.identity] - The wrtc_ identity to extend, if held directly (from a prior mint/refresh response).
|
|
79
|
+
* @param {number} [params.ttl] - New TTL in seconds. Defaults to the server default, capped at the server maximum.
|
|
80
|
+
* @param {import('../../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
|
|
81
|
+
* @returns {Promise<CreateTokenResponse>} The refreshed token + embedded SIP credentials (same shape as create()).
|
|
82
|
+
*/
|
|
83
|
+
async refresh({ token, identity, ttl, options = {} } = {}) {
|
|
84
|
+
const body = {};
|
|
85
|
+
if (token) body.token = token;
|
|
86
|
+
if (identity) body.identity = identity;
|
|
87
|
+
if (ttl != null) body.ttl = ttl;
|
|
88
|
+
return this.client(`/voice/tokens/refresh`, { method: "POST", body, ...options });
|
|
89
|
+
}
|
|
64
90
|
}
|