@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.
@@ -77,6 +77,23 @@ 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.
89
+ *
90
+ * Every record also carries a `health` object -- trailing 7-day and 30-day delivery/opt-out health from
91
+ * the same periodic refresh: `{ sevenDay, thirtyDay, updatedAt }`, each window being `{ score,
92
+ * deliveryRate, optOutRate, deliveryScore, optOutScore, messagesSent, messagesDelivered, messagesFailed,
93
+ * optOuts }`. `score` is 1.0..10.0 (the mean of the two bucket scores) and is null when nothing was sent
94
+ * in the window; the volumes say how much traffic sits behind it. A campaign's figure is scored from the
95
+ * campaign's own summed counters, never averaged from its numbers. For a live figure use GET /number/health
96
+ * or GET /campaign/health.
80
97
  * @returns {Promise<Object>} A promise that resolves to the list of phone numbers
81
98
  */
82
99
  async getPhoneNumbers({ phoneNumber, campaignId, brandId, subgroupId, groupId, page, limit, options = {} }) {
@@ -111,6 +128,7 @@ export class Numbers {
111
128
  * @param {boolean} [params.voiceEnabled] - Filter for phone numbers that are voice enabled
112
129
  * @param {string} [params.country] - Filter by country code (e.g., "US")
113
130
  * @param {string} [params.state] - Filter by state code (e.g., "CA")
131
+ * @param {string} [params.city] - City prefix; requires country US/CA and state/province.
114
132
  * @param {string} [params.npa] - Filter by NPA (area code)
115
133
  * @param {string} [params.nxx] - Filter by NXX (central office code) - the first three digits of the local phone number after the area code
116
134
  * @param {string} [params.phoneNumber] - Filter by phone number
@@ -125,6 +143,7 @@ export class Numbers {
125
143
  voiceEnabled,
126
144
  country,
127
145
  state,
146
+ city,
128
147
  npa,
129
148
  nxx,
130
149
  phoneNumber,
@@ -132,7 +151,7 @@ export class Numbers {
132
151
  page,
133
152
  options = {},
134
153
  }) {
135
- const filters = { smsEnabled, mmsEnabled, voiceEnabled, country, state, npa, nxx, phoneNumber, limit, page };
154
+ const filters = { smsEnabled, mmsEnabled, voiceEnabled, country, state, city, npa, nxx, phoneNumber, limit, page };
136
155
  const queryString = this.client._getQueryString(filters);
137
156
  return this.client(`/number/available${queryString}`, { method: 'GET', ...options });
138
157
  }
@@ -147,13 +166,14 @@ export class Numbers {
147
166
  * @param {Object} params - The parameters for purchasing phone numbers
148
167
  * @param {string[]} params.phoneNumbers - The list of phone numbers to purchase
149
168
  * @param {string} params.subgroupId - The ID of the subgroup to assign the purchased phone numbers to
169
+ * @param {'US'|'CA'} [params.country='US'] - ISO-2 purchase country. Toll-Free always uses the shared registry.
150
170
  * @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
151
171
  * @throws {Error} Throws an error if the phoneNumbers or subgroupId parameter is missing
152
172
  * @returns {Promise<Object>} A promise that resolves to `{ message }` once the request is queued.
153
173
  */
154
- async purchasePhoneNumber({ phoneNumbers, subgroupId, options = {} }) {
174
+ async purchasePhoneNumber({ phoneNumbers, subgroupId, country = 'US', options = {} }) {
155
175
  this.client._require({ phoneNumbers, subgroupId });
156
- return this.client(`/number`, { method: 'POST', body: { phoneNumbers, subgroupId }, ...options });
176
+ return this.client(`/number`, { method: 'POST', body: { phoneNumbers, subgroupId, country }, ...options });
157
177
  }
158
178
 
159
179
  /**
@@ -167,19 +187,19 @@ export class Numbers {
167
187
  * @param {Object} params - The parameters for purchasing toll-free numbers
168
188
  * @param {number} params.quantity - The number of toll-free numbers to purchase (1-10)
169
189
  * @param {string} params.subgroupId - The subgroup the purchased numbers are assigned to
190
+ * @param {'US'|'CA'} [params.country='US'] - ISO-2 purchase country. Toll-Free always uses the shared registry.
170
191
  * @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
171
192
  * @throws {Error} Throws an error if the quantity or subgroupId parameter is missing
172
193
  * @returns {Promise<Object>} A promise that resolves to `{ message, orderId }` once the request is queued.
173
194
  */
174
- async purchaseTollFreeNumbers({ quantity, subgroupId, options = {} }) {
195
+ async purchaseTollFreeNumbers({ quantity, subgroupId, country = 'US', options = {} }) {
175
196
  this.client._require({ quantity, subgroupId });
176
- return this.client(`/number/toll-free`, { method: 'POST', body: { quantity, subgroupId }, ...options });
197
+ return this.client(`/number/toll-free`, { method: 'POST', body: { quantity, subgroupId, country }, ...options });
177
198
  }
178
199
 
179
200
  /**
180
- * Request a campaign-bound Short Code acquisition or register a customer-owned Registry lease.
181
- * An inventory request soft-holds an existing unassigned Short Code. Random and vanity requests remain pending
182
- * until Signal House staff fulfill them. An external lease creates a pending Short Code number immediately; it
201
+ * Request a campaign-bound Short Code acquisition or register a customer-owned Registry lease.
202
+ * Random and vanity requests remain pending until Signal House staff fulfill them. An external lease creates a pending Short Code number immediately; it
183
203
  * becomes READY only when its campaign becomes ACTIVE.
184
204
  * @async
185
205
  * @roles api, admin, developer, billing, user
@@ -187,13 +207,12 @@ export class Numbers {
187
207
  * @param {string} params.subgroupId - The owning subgroup ID.
188
208
  * @param {string} params.brandId - The owning Short Code brand ID.
189
209
  * @param {string} params.campaignId - The owning Short Code campaign ID.
190
- * @param {'INVENTORY'|'RANDOM'|'VANITY'|'EXTERNAL_LEASE'} params.requestType - Acquisition path.
191
- * @param {string} [params.existingPhoneNumber] - Required existing five- or six-digit Short Code for INVENTORY.
210
+ * @param {'RANDOM'|'VANITY'|'EXTERNAL_LEASE'} params.requestType - Acquisition path.
192
211
  * @param {number} [params.leaseTermMonths] - Required 3, 6, or 12-month term for RANDOM/VANITY.
193
212
  * @param {string} [params.requestedVanityCode] - Required five- or six-digit desired code for VANITY.
194
213
  * @param {string} [params.actualCode] - Required customer-owned five- or six-digit code for EXTERNAL_LEASE.
195
214
  * @param {string} [params.orderId] - Required Registry order ID for EXTERNAL_LEASE.
196
- * @param {string|Date} [params.leaseEndDate] - Required future Registry lease end date for EXTERNAL_LEASE.
215
+ * @param {string|Date} [params.leaseEndDate] - Required future Registry lease end date for EXTERNAL_LEASE. A YYYY-MM-DD value expires at 23:59:59 UTC.
197
216
  * @param {Buffer|Blob|File} [params.leaseReceiptFile] - Required PNG, JPEG, or PDF lease receipt for EXTERNAL_LEASE.
198
217
  * @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
199
218
  * @returns {Promise<Object>} A pending acquisition request or pending external-lease number.
@@ -203,7 +222,6 @@ export class Numbers {
203
222
  brandId,
204
223
  campaignId,
205
224
  requestType,
206
- existingPhoneNumber,
207
225
  requestedVanityCode,
208
226
  leaseTermMonths,
209
227
  actualCode,
@@ -216,7 +234,7 @@ export class Numbers {
216
234
  const formData = new FormData();
217
235
  formData.append(
218
236
  'acquisitionData',
219
- JSON.stringify({ subgroupId, brandId, campaignId, requestType, existingPhoneNumber, requestedVanityCode, leaseTermMonths, actualCode, orderId, leaseEndDate }),
237
+ JSON.stringify({ subgroupId, brandId, campaignId, requestType, requestedVanityCode, leaseTermMonths, actualCode, orderId, leaseEndDate }),
220
238
  );
221
239
  if (leaseReceiptFile) formData.append('leaseReceipt', leaseReceiptFile);
222
240
  return this.multipartClient(`/number/short-code`, {
@@ -254,6 +272,8 @@ export class Numbers {
254
272
  * @param {string} params.phoneNumber - The phone number to update
255
273
  * @param {Object} params.updateData - The data to update for the phone number
256
274
  * @param {string} [params.updateData.friendlyName] - An optional friendly name for the phone number
275
+ * @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.
276
+ * @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
277
  * @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
258
278
  * @throws {Error} Throws an error if the phoneNumber or updateData parameter is missing
259
279
  * @returns {Promise<Object>} A promise that resolves to the updated phone number object
@@ -340,9 +360,10 @@ export class Numbers {
340
360
 
341
361
  /**
342
362
  * Assign phone numbers to a campaign by providing the campaign ID and a list of phone numbers to assign.
343
- * Numbers that are not found, already RELEASED, already assigned to a different campaign, on a mismatched
344
- * DCA, or (for a 10DLC campaign without a number pool) beyond the remaining 49-number-per-campaign limit
345
- * are not queued - each is reported back individually in `skipped` instead of failing the whole request.
363
+ * Numbers that are not found, already RELEASED, currently being released (transient PENDING_RELEASE
364
+ * status), already assigned to a different campaign, on a mismatched DCA, or (for a 10DLC campaign
365
+ * without a number pool) beyond the remaining 49-number-per-campaign limit are not queued - each is
366
+ * reported back individually in `skipped` instead of failing the whole request.
346
367
  * @async
347
368
  * @roles api, admin, developer, billing, user
348
369
  * @param {Object} params - The parameters for assigning phone numbers to a campaign
@@ -350,7 +371,7 @@ export class Numbers {
350
371
  * @param {string[]} params.phoneNumbers - The list of phone numbers to assign to the campaign
351
372
  * @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
352
373
  * @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
353
- * @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).
374
+ * @returns {Promise<Object>} A promise that resolves to `{ Message, queued, skipped }` - `queued` numbers were sent for assignment; `skipped` numbers were rejected (not found, RELEASED, currently being released, already assigned to a campaign, cross-DCA mismatch, or over the 49-number limit).
354
375
  */
355
376
  async assignPhoneNumberToCampaign({ campaignId, phoneNumbers, options = {} }) {
356
377
  this.client._require({ campaignId, phoneNumbers });
@@ -374,7 +395,7 @@ export class Numbers {
374
395
  }
375
396
 
376
397
  /**
377
- * Delete a list of phone numbers (mark them as RELEASED). The phone numbers will no longer be active or usable but they will still be visible in the system with a status of "RELEASED". Note: This operation is irreversible and should be used with caution.
398
+ * Delete a list of phone numbers (mark them as RELEASED). The phone numbers will no longer be active or usable but they will still be visible in the system with a status of "RELEASED". A number briefly shows a transient "PENDING_RELEASE" status while the deletion is being processed, before settling to "RELEASED". Note: This operation is irreversible and should be used with caution.
378
399
  * @async
379
400
  * @roles api, admin, developer, billing, user
380
401
  * @param {Object} params - The parameters for deleting phone numbers
@@ -435,15 +456,15 @@ export class Numbers {
435
456
  /**
436
457
  * Search NPA/NXX lookup data with optional filters.
437
458
  * At least one search parameter is required.
438
- * Location filters (country, state, city) cannot be combined with NPA/NXX filters.
459
+ * Country may scope NPA/NXX filters; state and city cannot be combined with them.
439
460
  * @async
440
461
  * @roles api, admin, developer, billing, user
441
462
  * @param {Object} params - The parameters for searching NPA/NXX data
442
463
  * @param {string} [params.country] - Filter by country code
443
464
  * @param {string} [params.state] - Filter by state code (2 characters)
444
465
  * @param {string} [params.city] - Filter by city name (prefix match, case-insensitive; requires country and state)
445
- * @param {string} [params.npa] - Area code filter (1-3 digits; cannot combine with location filters)
446
- * @param {string} [params.nxx] - Central office code filter (1-3 digits; cannot combine with location filters)
466
+ * @param {string} [params.npa] - Area code filter (1-3 digits; optional country, no state/city)
467
+ * @param {string} [params.nxx] - Central office code filter (1-3 digits; optional country, no state/city)
447
468
  * @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
448
469
  * @returns {Promise<Object>} A promise that resolves to matching NPA/NXX records or unique NPA/NXX arrays
449
470
  */
@@ -5,7 +5,9 @@ export class Webhooks {
5
5
  }
6
6
 
7
7
  /**
8
- * Get a list of webhooks with optional filters
8
+ * Get a list of webhooks with optional filters. Each returned endpoint carries `hasSigningSecret`
9
+ * (boolean) instead of the signing secret itself — the plaintext secret is only ever returned once,
10
+ * from `createWebhook`, and is never exposed again on any read (SHGHL-2944).
9
11
  * @async
10
12
  * @roles api, admin, developer
11
13
  * @param {Object} params - The parameters for getting webhooks
@@ -25,14 +27,19 @@ export class Webhooks {
25
27
  }
26
28
 
27
29
  /**
28
- * Create a new webhook with the specified data
30
+ * Create a new webhook with the specified data. The response includes a `signingSecret` — a
31
+ * plaintext HMAC-SHA256 secret used to sign every delivery to this endpoint, sent as the
32
+ * `X-SignalHouse-Signature` header alongside `X-SignalHouse-Timestamp` (the signed string is
33
+ * `${timestamp}.${rawRequestBody}`) and `X-SignalHouse-Delivery-Id` (stable across retries of the
34
+ * same event, for receiver-side dedup). Store this secret now: it is never returned again by any
35
+ * read (SHGHL-2944).
29
36
  * @async
30
37
  * @roles api, admin, developer
31
38
  * @param {Object} params - The parameters for creating a webhook
32
39
  * @param {Object} params.webhookData - The data for the new webhook
33
40
  * @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
34
41
  * @throws {Error} Throws an error if the webhookData parameter is missing or if required fields in webhookData are missing
35
- * @returns {Promise<Object>} The response from the server
42
+ * @returns {Promise<Object>} The response from the server, including the plaintext `signingSecret` (this one time only)
36
43
  */
37
44
  async createWebhook({ webhookData, options = {} }) {
38
45
  this.client._require({ webhookData: webhookData });
@@ -40,7 +47,9 @@ export class Webhooks {
40
47
  }
41
48
 
42
49
  /**
43
- * Update an existing webhook with the specified data
50
+ * Update an existing webhook with the specified data. Like every other read of a webhook, the
51
+ * response carries `hasSigningSecret` (boolean), never the signing secret itself — see
52
+ * `createWebhook` (SHGHL-2944).
44
53
  * @async
45
54
  * @roles api, admin, developer
46
55
  * @param {Object} params - The parameters for updating a webhook
@@ -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
  */