@signalhousellc/sdk 1.0.65 → 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.
@@ -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);
@@ -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
  }
@@ -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
@@ -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), or ring a registered SIP endpoint (SIP_PROFILE).
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
  */