@signalhousellc/sdk 1.0.66 → 1.0.67
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -0
- package/package.json +1 -1
- package/skills/signalhouse-10dlc/references/tcr-rejection-causes.md +4 -7
- package/src/SignalHouseSDK.js +3 -0
- package/src/domains/Agents.js +456 -0
- package/src/domains/Campaigns.js +61 -19
- package/src/domains/Messages.js +37 -21
- package/src/domains/Numbers.js +31 -21
- package/src/domains/Webhooks.js +13 -4
package/README.md
CHANGED
|
@@ -55,3 +55,13 @@ For full API reference and advanced usage, visit https://api.signalhouse.io
|
|
|
55
55
|
|
|
56
56
|
License
|
|
57
57
|
ISC © Signal House
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
### Geographic availability search
|
|
61
|
+
|
|
62
|
+
The availability path supports optional `city` as a case-insensitive prefix within an explicit `country` (`CA` or `US`) and `state` (province/state code). City must be supplied with both country and state. Example: `getAvailablePhoneNumbers({ country: "CA", state: "QC", city: "Charny", npa: "367", nxx: "883", limit: 10 })`. Canadian province, city, NPA and NXX matches are checked before the result limit; unrelated substring matches are excluded. Availability may change before purchase.
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
Canadian message estimates return per-recipient `phoneNumber`, `rate`, `amount` and `fallback`, plus segment count and total in microdollars. They use cached carrier information without exposing carrier names or making a paid lookup. Rates remain 75,500 for standard carriers and 81,000 for Ice Wireless/Iristel or unresolved carriers; MMS/group MMS use one segment per recipient.
|
|
66
|
+
|
|
67
|
+
Available-number searches return `{ numbers, numberCount? }`. `numberCount` is omitted when the total is unknown, including Canadian geographic and US city searches; the page length is not a total. These filtered searches have a 20-second discovery deadline and return HTTP 503 when incomplete. Narrow the location/NPA/NXX or retry later. Successful Infobip samples may be cached for 15 seconds across pages; purchase rechecks availability.
|
package/package.json
CHANGED
|
@@ -42,13 +42,10 @@ Two distinct real causes share this code.
|
|
|
42
42
|
|
|
43
43
|
**`Invalid sub-usecases: SOCIAL`.** `SOCIAL` is not a valid sub-use-case under any parent,
|
|
44
44
|
neither `LOW_VOLUME` nor `MIXED`. Valid sub-use-cases for `LOW_VOLUME` are
|
|
45
|
-
`ACCOUNT_NOTIFICATION`, `CUSTOMER_CARE`, `DELIVERY_NOTIFICATION`, `MARKETING`.
|
|
46
|
-
`SOCIAL`
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
the *use-case* enum, so `SOCIAL` is selectable as a sub-use-case even though the registry always
|
|
50
|
-
rejects it. **Delete this subsection when SHGHL-2943 ships.** It documents a defect, and a
|
|
51
|
-
workaround left in a skill becomes permanent.
|
|
45
|
+
`ACCOUNT_NOTIFICATION`, `CUSTOMER_CARE`, `DELIVERY_NOTIFICATION`, `MARKETING`. Signal House's own
|
|
46
|
+
validation now rejects `SOCIAL` as a `subUsecases` value with an immediate 400 before the request
|
|
47
|
+
ever reaches TCR (SHGHL-2943), so this specific 501 should no longer be reachable through the
|
|
48
|
+
API — `SOCIAL` is still a valid top-level `usecase`, just never a sub-use-case.
|
|
52
49
|
|
|
53
50
|
**Punctuation in a tag.** A tag of `maria-answers` was rejected for containing a hyphen. The
|
|
54
51
|
campaign content was fine. Fix the tag (`mariaanswers`), then the campaign has to be
|
package/src/SignalHouseSDK.js
CHANGED
|
@@ -24,6 +24,7 @@ import { Users } from "./domains/Users.js";
|
|
|
24
24
|
import { Notifications } from "./domains/Notifications.js";
|
|
25
25
|
import { Webhooks } from "./domains/Webhooks.js";
|
|
26
26
|
import { Voice } from "./domains/Voice.js";
|
|
27
|
+
import { Agents } from "./domains/Agents.js";
|
|
27
28
|
|
|
28
29
|
export class SignalHouseSDK {
|
|
29
30
|
/**
|
|
@@ -73,6 +74,8 @@ export class SignalHouseSDK {
|
|
|
73
74
|
// Voice domain targets the voice-backend service under /voice. Available
|
|
74
75
|
// like any other domain; gating (if any) will be decided later.
|
|
75
76
|
this.voice = new Voice(client, this.enableAdmin);
|
|
77
|
+
// AI Agents domain — customer-facing agent config under /agent.
|
|
78
|
+
this.agents = new Agents(client, this.enableAdmin);
|
|
76
79
|
}
|
|
77
80
|
|
|
78
81
|
/**
|
|
@@ -0,0 +1,456 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {Object} CreateAgentProfileData
|
|
3
|
+
* @property {string} groupId - The parent group id (at least 8 characters, starts with 'G').
|
|
4
|
+
* @property {string|null} [subgroupId] - Optional subgroup id (at least 8 characters, starts with 'S'); null/omitted = group-level agent.
|
|
5
|
+
* @property {string} name - The agent's name (required).
|
|
6
|
+
* @property {string} [status] - Lifecycle status: "active" or "inactive" (defaults to "active").
|
|
7
|
+
* @property {string} [systemPrompt] - Base system prompt composed into every conversation.
|
|
8
|
+
* @property {string} [greeting] - Opening line the agent leads with.
|
|
9
|
+
* @property {string} [guardrails] - Freeform guardrail instructions appended to the composed prompt.
|
|
10
|
+
* @property {string|null} [voiceId] - ElevenLabs voice id for the voice channel; null until set.
|
|
11
|
+
* @property {string} [llmProvider] - LLM backend: "bedrock", "openai", "anthropic", or "groq" (defaults to "bedrock").
|
|
12
|
+
* @property {string|null} [llmModel] - Concrete model id for the provider; null = provider default.
|
|
13
|
+
* @property {number} [temperature] - Sampling temperature (0-2).
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @typedef {Object} UpdateAgentProfileData
|
|
18
|
+
* @property {string} [name] - The agent's name.
|
|
19
|
+
* @property {string} [status] - Lifecycle status: "active" or "inactive".
|
|
20
|
+
* @property {string} [systemPrompt] - Base system prompt composed into every conversation.
|
|
21
|
+
* @property {string} [greeting] - Opening line the agent leads with.
|
|
22
|
+
* @property {string} [guardrails] - Freeform guardrail instructions appended to the composed prompt.
|
|
23
|
+
* @property {string|null} [voiceId] - ElevenLabs voice id for the voice channel.
|
|
24
|
+
* @property {string} [llmProvider] - LLM backend: "bedrock", "openai", "anthropic", or "groq".
|
|
25
|
+
* @property {string|null} [llmModel] - Concrete model id for the provider; null = provider default.
|
|
26
|
+
* @property {number} [temperature] - Sampling temperature (0-2).
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
export class Agents {
|
|
30
|
+
constructor(client, enableAdmin) {
|
|
31
|
+
this.client = client;
|
|
32
|
+
this.enableAdmin = enableAdmin;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* List the agent profiles under a group.
|
|
37
|
+
* @async
|
|
38
|
+
* @roles api, admin, developer, billing, user
|
|
39
|
+
* @param {Object} params - The parameters for listing agent profiles.
|
|
40
|
+
* @param {string} params.groupId - The group whose profiles to list (required).
|
|
41
|
+
* @param {number} [params.page] - The page number for pagination.
|
|
42
|
+
* @param {number} [params.limit] - The number of items per page for pagination.
|
|
43
|
+
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
|
|
44
|
+
* @throws {Error} Throws an error if the groupId parameter is missing.
|
|
45
|
+
* @returns {Promise<Object>} - The list of agent profiles returned from the server.
|
|
46
|
+
*/
|
|
47
|
+
async getAgentProfiles({ groupId, page, limit, options = {} }) {
|
|
48
|
+
this.client._require({ groupId });
|
|
49
|
+
const queryString = this.client._getQueryString({ groupId, page, limit });
|
|
50
|
+
return this.client(`/agent/profiles${queryString}`, { method: "GET", ...options });
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Get a single agent profile by id.
|
|
55
|
+
* @async
|
|
56
|
+
* @roles api, admin, developer, billing, user
|
|
57
|
+
* @param {Object} params - The parameters for getting an agent profile.
|
|
58
|
+
* @param {string} params.agentProfileId - The id of the agent profile to fetch.
|
|
59
|
+
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
|
|
60
|
+
* @throws {Error} Throws an error if the agentProfileId parameter is missing.
|
|
61
|
+
* @returns {Promise<Object>} - The agent profile returned from the server.
|
|
62
|
+
*/
|
|
63
|
+
async getAgentProfile({ agentProfileId, options = {} }) {
|
|
64
|
+
this.client._require({ agentProfileId });
|
|
65
|
+
const safeId = encodeURIComponent(agentProfileId);
|
|
66
|
+
return this.client(`/agent/profiles/${safeId}`, { method: "GET", ...options });
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Create a new agent profile.
|
|
71
|
+
* @async
|
|
72
|
+
* @roles api, admin, developer
|
|
73
|
+
* @param {Object} params - The parameters for creating an agent profile (see CreateAgentProfileData typedef).
|
|
74
|
+
* @param {CreateAgentProfileData} params.profileData - The data for the agent profile to create, including required fields groupId and name.
|
|
75
|
+
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
|
|
76
|
+
* @throws {Error} Throws an error if the profileData parameter is missing.
|
|
77
|
+
* @returns {Promise<Object>} - The created agent profile returned from the server.
|
|
78
|
+
*/
|
|
79
|
+
async createAgentProfile({ profileData, options = {} }) {
|
|
80
|
+
this.client._require({ profileData });
|
|
81
|
+
return this.client(`/agent/profiles`, { method: "POST", body: profileData, ...options });
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Update an existing agent profile.
|
|
86
|
+
* @async
|
|
87
|
+
* @roles api, admin, developer
|
|
88
|
+
* @param {Object} params - The parameters for updating an agent profile (see UpdateAgentProfileData typedef).
|
|
89
|
+
* @param {string} params.id - The id of the agent profile to update.
|
|
90
|
+
* @param {UpdateAgentProfileData} params.updateData - The data for the agent profile to update.
|
|
91
|
+
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
|
|
92
|
+
* @throws {Error} Throws an error if the id or updateData parameter is missing.
|
|
93
|
+
* @returns {Promise<Object>} - The updated agent profile returned from the server.
|
|
94
|
+
*/
|
|
95
|
+
async updateAgentProfile({ id, updateData, options = {} }) {
|
|
96
|
+
this.client._require({ id, updateData });
|
|
97
|
+
const safeId = encodeURIComponent(id);
|
|
98
|
+
return this.client(`/agent/profiles/${safeId}`, { method: "PUT", body: updateData, ...options });
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Delete (inactivate) an agent profile by its id.
|
|
103
|
+
* @async
|
|
104
|
+
* @roles api, admin, developer
|
|
105
|
+
* @param {Object} params - The parameters for deleting an agent profile.
|
|
106
|
+
* @param {string} params.id - The id of the agent profile to delete.
|
|
107
|
+
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
|
|
108
|
+
* @throws {Error} Throws an error if the id parameter is missing.
|
|
109
|
+
* @returns {Promise<Object>} - The inactivated agent profile returned from the server.
|
|
110
|
+
*/
|
|
111
|
+
async deleteAgentProfile({ id, options = {} }) {
|
|
112
|
+
this.client._require({ id });
|
|
113
|
+
const safeId = encodeURIComponent(id);
|
|
114
|
+
return this.client(`/agent/profiles/${safeId}`, { method: "DELETE", ...options });
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Send a message to an agent and get its reply — the app-native conversation
|
|
119
|
+
* endpoint (webchat / SMS). Omit conversationId to start a new conversation, or
|
|
120
|
+
* pass one to continue an existing one. Runs the agent's LLM tool loop server-side
|
|
121
|
+
* and returns the assistant's reply along with any tools it invoked.
|
|
122
|
+
* @async
|
|
123
|
+
* @roles api, admin, developer, billing, user
|
|
124
|
+
* @param {Object} params - The parameters for sending a message.
|
|
125
|
+
* @param {string} params.agentProfileId - The agent to talk to (required).
|
|
126
|
+
* @param {string} params.channel - The channel: "webchat", "sms", or "voice" (required).
|
|
127
|
+
* @param {string} params.message - The user's message (required).
|
|
128
|
+
* @param {string} [params.conversationId] - Continue this conversation; omit to start a new one.
|
|
129
|
+
* @param {string} [params.contactIdentifier] - The far-end identifier (webchat visitor id, sender number).
|
|
130
|
+
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
|
|
131
|
+
* @throws {Error} Throws an error if agentProfileId, channel, or message is missing.
|
|
132
|
+
* @returns {Promise<Object>} - `{ conversationId, conversationSessionId, reply, toolInvocations, ok }` from the server.
|
|
133
|
+
*/
|
|
134
|
+
async sendAgentMessage({ agentProfileId, channel, message, conversationId, contactIdentifier, options = {} }) {
|
|
135
|
+
this.client._require({ agentProfileId, channel, message });
|
|
136
|
+
const body = { agentProfileId, channel, message };
|
|
137
|
+
if (conversationId !== undefined && conversationId !== null) body.conversationId = conversationId;
|
|
138
|
+
if (contactIdentifier !== undefined && contactIdentifier !== null) body.contactIdentifier = contactIdentifier;
|
|
139
|
+
return this.client(`/agent/messages`, { method: "POST", body, ...options });
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* List an agent's per-channel settings (the tools enabled per channel, whether the
|
|
144
|
+
* channel is on, and any channel-specific prompt/greeting).
|
|
145
|
+
* @async
|
|
146
|
+
* @roles api, admin, developer, billing, user
|
|
147
|
+
* @param {Object} params - The parameters for listing channel settings.
|
|
148
|
+
* @param {string} params.agentProfileId - The agent whose channel settings to list.
|
|
149
|
+
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
|
|
150
|
+
* @throws {Error} Throws an error if the agentProfileId parameter is missing.
|
|
151
|
+
* @returns {Promise<Object>} - The agent's channel settings returned from the server.
|
|
152
|
+
*/
|
|
153
|
+
async getAgentChannelSettings({ agentProfileId, options = {} }) {
|
|
154
|
+
this.client._require({ agentProfileId });
|
|
155
|
+
const safeId = encodeURIComponent(agentProfileId);
|
|
156
|
+
return this.client(`/agent/profiles/${safeId}/channels`, { method: "GET", ...options });
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Get a single per-channel setting for an agent.
|
|
161
|
+
* @async
|
|
162
|
+
* @roles api, admin, developer, billing, user
|
|
163
|
+
* @param {Object} params - The parameters for getting a channel setting.
|
|
164
|
+
* @param {string} params.agentProfileId - The agent the setting belongs to.
|
|
165
|
+
* @param {string} params.channel - The channel: "webchat", "sms", or "voice".
|
|
166
|
+
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
|
|
167
|
+
* @throws {Error} Throws an error if agentProfileId or channel is missing.
|
|
168
|
+
* @returns {Promise<Object>} - The channel setting returned from the server.
|
|
169
|
+
*/
|
|
170
|
+
async getAgentChannelSetting({ agentProfileId, channel, options = {} }) {
|
|
171
|
+
this.client._require({ agentProfileId, channel });
|
|
172
|
+
const safeId = encodeURIComponent(agentProfileId);
|
|
173
|
+
const safeChannel = encodeURIComponent(channel);
|
|
174
|
+
return this.client(`/agent/profiles/${safeId}/channels/${safeChannel}`, { method: "GET", ...options });
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Create or update (upsert) an agent's per-channel setting. One row per (agent, channel);
|
|
179
|
+
* the channel is taken from the path, the fields from settingData.
|
|
180
|
+
* @async
|
|
181
|
+
* @roles api, admin, developer
|
|
182
|
+
* @param {Object} params - The parameters for the upsert.
|
|
183
|
+
* @param {string} params.agentProfileId - The agent the setting belongs to.
|
|
184
|
+
* @param {string} params.channel - The channel: "webchat", "sms", or "voice".
|
|
185
|
+
* @param {Object} [params.settingData] - The fields to set: allowedTools (string[]), enabled (boolean), channelPrompt (string), greeting (string|null).
|
|
186
|
+
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
|
|
187
|
+
* @throws {Error} Throws an error if agentProfileId or channel is missing.
|
|
188
|
+
* @returns {Promise<Object>} - The created or updated channel setting returned from the server.
|
|
189
|
+
*/
|
|
190
|
+
async upsertAgentChannelSetting({ agentProfileId, channel, settingData = {}, options = {} }) {
|
|
191
|
+
this.client._require({ agentProfileId, channel });
|
|
192
|
+
const safeId = encodeURIComponent(agentProfileId);
|
|
193
|
+
const safeChannel = encodeURIComponent(channel);
|
|
194
|
+
return this.client(`/agent/profiles/${safeId}/channels/${safeChannel}`, { method: "PUT", body: settingData, ...options });
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Delete an agent's per-channel setting.
|
|
199
|
+
* @async
|
|
200
|
+
* @roles api, admin, developer
|
|
201
|
+
* @param {Object} params - The parameters for the delete.
|
|
202
|
+
* @param {string} params.agentProfileId - The agent the setting belongs to.
|
|
203
|
+
* @param {string} params.channel - The channel: "webchat", "sms", or "voice".
|
|
204
|
+
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
|
|
205
|
+
* @throws {Error} Throws an error if agentProfileId or channel is missing.
|
|
206
|
+
* @returns {Promise<Object>} - The delete confirmation returned from the server.
|
|
207
|
+
*/
|
|
208
|
+
async deleteAgentChannelSetting({ agentProfileId, channel, options = {} }) {
|
|
209
|
+
this.client._require({ agentProfileId, channel });
|
|
210
|
+
const safeId = encodeURIComponent(agentProfileId);
|
|
211
|
+
const safeChannel = encodeURIComponent(channel);
|
|
212
|
+
return this.client(`/agent/profiles/${safeId}/channels/${safeChannel}`, { method: "DELETE", ...options });
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Read the tenant AI settings for a scope (group, or a subgroup within it) — brand, tone,
|
|
217
|
+
* timezone, business hours, and after-hours message. Returns the scope's own row only (no
|
|
218
|
+
* group-level fallback).
|
|
219
|
+
* @async
|
|
220
|
+
* @roles api, admin, developer, billing, user
|
|
221
|
+
* @param {Object} params - The parameters for reading tenant settings.
|
|
222
|
+
* @param {string} params.groupId - The group (required).
|
|
223
|
+
* @param {string} [params.subgroupId] - The subgroup; omit for the group-level settings.
|
|
224
|
+
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
|
|
225
|
+
* @throws {Error} Throws an error if the groupId parameter is missing.
|
|
226
|
+
* @returns {Promise<Object>} - The tenant settings returned from the server.
|
|
227
|
+
*/
|
|
228
|
+
async getTenantAiSettings({ groupId, subgroupId, options = {} }) {
|
|
229
|
+
this.client._require({ groupId });
|
|
230
|
+
const queryString = this.client._getQueryString({ groupId, subgroupId });
|
|
231
|
+
return this.client(`/agent/tenant-settings${queryString}`, { method: "GET", ...options });
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Create or update (upsert) the tenant AI settings for a scope. The scope is identified by
|
|
236
|
+
* the query params; the body carries the settings fields.
|
|
237
|
+
* @async
|
|
238
|
+
* @roles api, admin, developer
|
|
239
|
+
* @param {Object} params - The parameters for the upsert.
|
|
240
|
+
* @param {string} params.groupId - The group (required).
|
|
241
|
+
* @param {string} [params.subgroupId] - The subgroup; omit for the group-level settings.
|
|
242
|
+
* @param {Object} [params.settingsData] - Fields to set: brandName (string), tone (string), timezone (IANA string), businessHours (array of {day, closed, open, close}), afterHoursMessage (string).
|
|
243
|
+
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
|
|
244
|
+
* @throws {Error} Throws an error if the groupId parameter is missing.
|
|
245
|
+
* @returns {Promise<Object>} - The created or updated tenant settings returned from the server.
|
|
246
|
+
*/
|
|
247
|
+
async upsertTenantAiSettings({ groupId, subgroupId, settingsData = {}, options = {} }) {
|
|
248
|
+
this.client._require({ groupId });
|
|
249
|
+
const queryString = this.client._getQueryString({ groupId, subgroupId });
|
|
250
|
+
return this.client(`/agent/tenant-settings${queryString}`, { method: "PUT", body: settingsData, ...options });
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Delete the tenant AI settings for a scope.
|
|
255
|
+
* @async
|
|
256
|
+
* @roles api, admin, developer
|
|
257
|
+
* @param {Object} params - The parameters for the delete.
|
|
258
|
+
* @param {string} params.groupId - The group (required).
|
|
259
|
+
* @param {string} [params.subgroupId] - The subgroup; omit for the group-level settings.
|
|
260
|
+
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
|
|
261
|
+
* @throws {Error} Throws an error if the groupId parameter is missing.
|
|
262
|
+
* @returns {Promise<Object>} - The delete confirmation returned from the server.
|
|
263
|
+
*/
|
|
264
|
+
async deleteTenantAiSettings({ groupId, subgroupId, options = {} }) {
|
|
265
|
+
this.client._require({ groupId });
|
|
266
|
+
const queryString = this.client._getQueryString({ groupId, subgroupId });
|
|
267
|
+
return this.client(`/agent/tenant-settings${queryString}`, { method: "DELETE", ...options });
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* List the knowledge-base items an agent can answer from (RAG), scoped to a group and
|
|
272
|
+
* optionally narrowed to a subgroup and/or a single agent.
|
|
273
|
+
* @async
|
|
274
|
+
* @roles api, admin, developer, billing, user
|
|
275
|
+
* @param {Object} params - The parameters for listing knowledge items.
|
|
276
|
+
* @param {string} params.groupId - The group whose knowledge to list (required).
|
|
277
|
+
* @param {string} [params.subgroupId] - Narrow to a subgroup.
|
|
278
|
+
* @param {string} [params.agentProfileId] - Narrow to one agent.
|
|
279
|
+
* @param {number} [params.page] - Page number (1-based) for pagination.
|
|
280
|
+
* @param {number} [params.limit] - Items per page (max 100; server default 25).
|
|
281
|
+
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
|
|
282
|
+
* @throws {Error} Throws an error if the groupId parameter is missing.
|
|
283
|
+
* @returns {Promise<Object>} - The knowledge items returned from the server.
|
|
284
|
+
*/
|
|
285
|
+
async getKnowledgeItems({ groupId, subgroupId, agentProfileId, page, limit, options = {} }) {
|
|
286
|
+
this.client._require({ groupId });
|
|
287
|
+
const queryString = this.client._getQueryString({ groupId, subgroupId, agentProfileId, page, limit });
|
|
288
|
+
return this.client(`/agent/knowledge${queryString}`, { method: "GET", ...options });
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Get a single knowledge item by id.
|
|
293
|
+
* @async
|
|
294
|
+
* @roles api, admin, developer, billing, user
|
|
295
|
+
* @param {Object} params - The parameters for getting a knowledge item.
|
|
296
|
+
* @param {string} params.knowledgeItemId - The id of the knowledge item to fetch.
|
|
297
|
+
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
|
|
298
|
+
* @throws {Error} Throws an error if the knowledgeItemId parameter is missing.
|
|
299
|
+
* @returns {Promise<Object>} - The knowledge item returned from the server.
|
|
300
|
+
*/
|
|
301
|
+
async getKnowledgeItem({ knowledgeItemId, options = {} }) {
|
|
302
|
+
this.client._require({ knowledgeItemId });
|
|
303
|
+
const safeId = encodeURIComponent(knowledgeItemId);
|
|
304
|
+
return this.client(`/agent/knowledge/${safeId}`, { method: "GET", ...options });
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Create a knowledge item. The raw `text` is stored and Atlas Vector Search owns the
|
|
309
|
+
* embedding — there is no embedding to supply.
|
|
310
|
+
* @async
|
|
311
|
+
* @roles api, admin, developer
|
|
312
|
+
* @param {Object} params - The parameters for creating a knowledge item.
|
|
313
|
+
* @param {Object} params.itemData - The knowledge fields. Required: groupId (starts with 'G'), text.
|
|
314
|
+
* Optional: subgroupId (starts with 'S', nullable), agentProfileId
|
|
315
|
+
* (nullable = shared across the tenant's agents), title, source
|
|
316
|
+
* ("manual" | "url" | "document" | "import"), enabled (boolean), metadata (object|null).
|
|
317
|
+
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
|
|
318
|
+
* @throws {Error} Throws an error if the itemData parameter is missing.
|
|
319
|
+
* @returns {Promise<Object>} - The created knowledge item returned from the server.
|
|
320
|
+
*/
|
|
321
|
+
async createKnowledgeItem({ itemData, options = {} }) {
|
|
322
|
+
this.client._require({ itemData });
|
|
323
|
+
return this.client(`/agent/knowledge`, { method: "POST", body: itemData, ...options });
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Update a knowledge item. The item's scope (group/subgroup/agent) is immutable and
|
|
328
|
+
* cannot be changed.
|
|
329
|
+
* @async
|
|
330
|
+
* @roles api, admin, developer
|
|
331
|
+
* @param {Object} params - The parameters for updating a knowledge item.
|
|
332
|
+
* @param {string} params.id - The id of the knowledge item to update.
|
|
333
|
+
* @param {Object} params.updateData - The fields to update: title, text, source, enabled, metadata.
|
|
334
|
+
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
|
|
335
|
+
* @throws {Error} Throws an error if the id or updateData parameter is missing.
|
|
336
|
+
* @returns {Promise<Object>} - The updated knowledge item returned from the server.
|
|
337
|
+
*/
|
|
338
|
+
async updateKnowledgeItem({ id, updateData, options = {} }) {
|
|
339
|
+
this.client._require({ id, updateData });
|
|
340
|
+
const safeId = encodeURIComponent(id);
|
|
341
|
+
return this.client(`/agent/knowledge/${safeId}`, { method: "PUT", body: updateData, ...options });
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* Delete a knowledge item by its id.
|
|
346
|
+
* @async
|
|
347
|
+
* @roles api, admin, developer
|
|
348
|
+
* @param {Object} params - The parameters for deleting a knowledge item.
|
|
349
|
+
* @param {string} params.id - The id of the knowledge item to delete.
|
|
350
|
+
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
|
|
351
|
+
* @throws {Error} Throws an error if the id parameter is missing.
|
|
352
|
+
* @returns {Promise<Object>} - The delete confirmation returned from the server.
|
|
353
|
+
*/
|
|
354
|
+
async deleteKnowledgeItem({ id, options = {} }) {
|
|
355
|
+
this.client._require({ id });
|
|
356
|
+
const safeId = encodeURIComponent(id);
|
|
357
|
+
return this.client(`/agent/knowledge/${safeId}`, { method: "DELETE", ...options });
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* List the tools defined under a group — custom webhook tools, configured built-ins, and
|
|
362
|
+
* (future) MCP. `webhookAuth` secrets are redacted in the response.
|
|
363
|
+
* @async
|
|
364
|
+
* @roles api, admin, developer, billing, user
|
|
365
|
+
* @param {Object} params - The parameters for listing tools.
|
|
366
|
+
* @param {string} params.groupId - The group whose tools to list (required).
|
|
367
|
+
* @param {string} [params.subgroupId] - Narrow to a subgroup.
|
|
368
|
+
* @param {string} [params.agentProfileId] - Narrow to one agent.
|
|
369
|
+
* @param {string} [params.type] - Narrow to a tool type: "builtin", "webhook", or "mcp".
|
|
370
|
+
* @param {number} [params.page] - Page number (1-based) for pagination.
|
|
371
|
+
* @param {number} [params.limit] - Items per page (max 100; server default 25).
|
|
372
|
+
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
|
|
373
|
+
* @throws {Error} Throws an error if the groupId parameter is missing.
|
|
374
|
+
* @returns {Promise<Object>} - The tools returned from the server (secrets redacted).
|
|
375
|
+
*/
|
|
376
|
+
async getAgentTools({ groupId, subgroupId, agentProfileId, type, page, limit, options = {} }) {
|
|
377
|
+
this.client._require({ groupId });
|
|
378
|
+
const queryString = this.client._getQueryString({ groupId, subgroupId, agentProfileId, type, page, limit });
|
|
379
|
+
return this.client(`/agent/tools${queryString}`, { method: "GET", ...options });
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* Get a single agent tool by id. `webhookAuth` secrets are redacted in the response.
|
|
384
|
+
* @async
|
|
385
|
+
* @roles api, admin, developer, billing, user
|
|
386
|
+
* @param {Object} params - The parameters for getting a tool.
|
|
387
|
+
* @param {string} params.agentToolId - The id of the tool to fetch.
|
|
388
|
+
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
|
|
389
|
+
* @throws {Error} Throws an error if the agentToolId parameter is missing.
|
|
390
|
+
* @returns {Promise<Object>} - The tool returned from the server (secrets redacted).
|
|
391
|
+
*/
|
|
392
|
+
async getAgentTool({ agentToolId, options = {} }) {
|
|
393
|
+
this.client._require({ agentToolId });
|
|
394
|
+
const safeId = encodeURIComponent(agentToolId);
|
|
395
|
+
return this.client(`/agent/tools/${safeId}`, { method: "GET", ...options });
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
* Create an agent tool. For a webhook tool, `webhookUrl` must be an https URL that does not
|
|
400
|
+
* target a private/internal address (rejected otherwise). `webhookAuth` is stored and never
|
|
401
|
+
* echoed back.
|
|
402
|
+
* @async
|
|
403
|
+
* @roles api, admin, developer
|
|
404
|
+
* @param {Object} params - The parameters for creating a tool.
|
|
405
|
+
* @param {Object} params.toolData - The tool fields. Required: groupId (starts with 'G'), name, description.
|
|
406
|
+
* Type-specific: type ("builtin" | "webhook" | "mcp"); webhook → webhookUrl, builtin →
|
|
407
|
+
* builtinKey, mcp → mcpServerUrl. Optional: subgroupId, agentProfileId (nullable = shared),
|
|
408
|
+
* parametersSchema, config, channels (string[]), enabled (boolean), and webhookAuth —
|
|
409
|
+
* which MUST be `{ headers?: { [name]: value }, signingSecret?: string }` (any other shape,
|
|
410
|
+
* e.g. `{ header, value }`, is rejected with a 400). `headers` are sent verbatim on every
|
|
411
|
+
* call (reserved/framing and `x-signalhouse-*` names are rejected); `signingSecret` makes us
|
|
412
|
+
* send `X-SignalHouse-Signature: sha256=HMAC-SHA256(`${X-SignalHouse-Timestamp}.${rawBody}`)`
|
|
413
|
+
* so you can verify the call and reject replays. Stored, never returned.
|
|
414
|
+
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
|
|
415
|
+
* @throws {Error} Throws an error if the toolData parameter is missing.
|
|
416
|
+
* @returns {Promise<Object>} - The created tool returned from the server (secrets redacted).
|
|
417
|
+
*/
|
|
418
|
+
async createAgentTool({ toolData, options = {} }) {
|
|
419
|
+
this.client._require({ toolData });
|
|
420
|
+
return this.client(`/agent/tools`, { method: "POST", body: toolData, ...options });
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* Update an agent tool. The tool's scope (group/subgroup/agent) is immutable. A supplied
|
|
425
|
+
* `webhookUrl` is SSRF-checked.
|
|
426
|
+
* @async
|
|
427
|
+
* @roles api, admin, developer
|
|
428
|
+
* @param {Object} params - The parameters for updating a tool.
|
|
429
|
+
* @param {string} params.id - The id of the tool to update.
|
|
430
|
+
* @param {Object} params.updateData - The fields to update: name, description, type, builtinKey, parametersSchema, config, webhookUrl, webhookAuth, mcpServerUrl, channels, enabled.
|
|
431
|
+
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
|
|
432
|
+
* @throws {Error} Throws an error if the id or updateData parameter is missing.
|
|
433
|
+
* @returns {Promise<Object>} - The updated tool returned from the server (secrets redacted).
|
|
434
|
+
*/
|
|
435
|
+
async updateAgentTool({ id, updateData, options = {} }) {
|
|
436
|
+
this.client._require({ id, updateData });
|
|
437
|
+
const safeId = encodeURIComponent(id);
|
|
438
|
+
return this.client(`/agent/tools/${safeId}`, { method: "PUT", body: updateData, ...options });
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
/**
|
|
442
|
+
* Delete an agent tool by its id.
|
|
443
|
+
* @async
|
|
444
|
+
* @roles api, admin, developer
|
|
445
|
+
* @param {Object} params - The parameters for deleting a tool.
|
|
446
|
+
* @param {string} params.id - The id of the tool to delete.
|
|
447
|
+
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
|
|
448
|
+
* @throws {Error} Throws an error if the id parameter is missing.
|
|
449
|
+
* @returns {Promise<Object>} - The delete confirmation returned from the server.
|
|
450
|
+
*/
|
|
451
|
+
async deleteAgentTool({ id, options = {} }) {
|
|
452
|
+
this.client._require({ id });
|
|
453
|
+
const safeId = encodeURIComponent(id);
|
|
454
|
+
return this.client(`/agent/tools/${safeId}`, { method: "DELETE", ...options });
|
|
455
|
+
}
|
|
456
|
+
}
|
package/src/domains/Campaigns.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @typedef {Object} CreateCampaignData
|
|
3
3
|
* @property {string} brandId - The ID of the brand associated with the campaign (required)
|
|
4
4
|
* @property {string} usecase - The use case for the campaign (2FA, ACCOUNT_NOTIFICATION, AGENTS_FRANCHISES, CARRIER_EXEMPT, CHARITY, CUSTOMER_CARE, DELIVERY_NOTIFICATION, EMERGENCY, FRAUD_ALERT, HIGHER_EDUCATION, K12_EDUCATION, LOW_VOLUME, M2M, MARKETING, MIXED, POLITICAL, POLLING_VOTING, PROXY, PUBLIC_SAFETY_RESTRICTED, PUBLIC_SERVICE_ANNOUNCEMENT, SECURITY_ALERT, SOCIAL, SOLE_PROPRIETOR, SWEEPSTAKE, TRIAL, UCAAS_HIGH, UCAAS_LOW)
|
|
5
|
-
* @property {Array<string>} [subUsecases] - An array of sub-use cases for the campaign (2FA, ACCOUNT_NOTIFICATION, AGENTS_FRANCHISES, CARRIER_EXEMPT, CHARITY, CUSTOMER_CARE, DELIVERY_NOTIFICATION, EMERGENCY, FRAUD_ALERT, HIGHER_EDUCATION, K12_EDUCATION, LOW_VOLUME, M2M, MARKETING, MIXED, POLITICAL, POLLING_VOTING, PROXY, PUBLIC_SAFETY_RESTRICTED, PUBLIC_SERVICE_ANNOUNCEMENT, SECURITY_ALERT,
|
|
5
|
+
* @property {Array<string>} [subUsecases] - An array of sub-use cases for the campaign (2FA, ACCOUNT_NOTIFICATION, AGENTS_FRANCHISES, CARRIER_EXEMPT, CHARITY, CUSTOMER_CARE, DELIVERY_NOTIFICATION, EMERGENCY, FRAUD_ALERT, HIGHER_EDUCATION, K12_EDUCATION, LOW_VOLUME, M2M, MARKETING, MIXED, POLITICAL, POLLING_VOTING, PROXY, PUBLIC_SAFETY_RESTRICTED, PUBLIC_SERVICE_ANNOUNCEMENT, SECURITY_ALERT, SOLE_PROPRIETOR, SWEEPSTAKE, TRIAL, UCAAS_HIGH, UCAAS_LOW — NOT SOCIAL, which TCR rejects as a sub-usecase for every parent usecase even though it is valid as the top-level `usecase`)
|
|
6
6
|
* @property {string} description - A detailed description of the campaign (required, must be between 40 and 4096 characters)
|
|
7
7
|
* @property {boolean} [embeddedLink=true] - Whether the campaign includes an embedded link (optional, defaults to true)
|
|
8
8
|
* @property {boolean} [embeddedPhone=false] - Whether the campaign includes an embedded phone number (optional, defaults to false)
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
/**
|
|
37
37
|
* @typedef {Object} UpdateCampaignData
|
|
38
38
|
* @property {string} [usecase] - The use case for the campaign (2FA, ACCOUNT_NOTIFICATION, AGENTS_FRANCHISES, CARRIER_EXEMPT, CHARITY, CUSTOMER_CARE, DELIVERY_NOTIFICATION, EMERGENCY, FRAUD_ALERT, HIGHER_EDUCATION, K12_EDUCATION, LOW_VOLUME, M2M, MARKETING, MIXED, POLITICAL, POLLING_VOTING, PROXY, PUBLIC_SAFETY_RESTRICTED, PUBLIC_SERVICE_ANNOUNCEMENT, SECURITY_ALERT, SOCIAL, SOLE_PROPRIETOR, SWEEPSTAKE, TRIAL, UCAAS_HIGH, UCAAS_LOW)
|
|
39
|
-
* @property {Array<string>} [subUsecases] - An array of sub-use cases for the campaign (2FA, ACCOUNT_NOTIFICATION, AGENTS_FRANCHISES, CARRIER_EXEMPT, CHARITY, CUSTOMER_CARE, DELIVERY_NOTIFICATION, EMERGENCY, FRAUD_ALERT, HIGHER_EDUCATION, K12_EDUCATION, LOW_VOLUME, M2M, MARKETING, MIXED, POLITICAL, POLLING_VOTING, PROXY, PUBLIC_SAFETY_RESTRICTED, PUBLIC_SERVICE_ANNOUNCEMENT, SECURITY_ALERT,
|
|
39
|
+
* @property {Array<string>} [subUsecases] - An array of sub-use cases for the campaign (2FA, ACCOUNT_NOTIFICATION, AGENTS_FRANCHISES, CARRIER_EXEMPT, CHARITY, CUSTOMER_CARE, DELIVERY_NOTIFICATION, EMERGENCY, FRAUD_ALERT, HIGHER_EDUCATION, K12_EDUCATION, LOW_VOLUME, M2M, MARKETING, MIXED, POLITICAL, POLLING_VOTING, PROXY, PUBLIC_SAFETY_RESTRICTED, PUBLIC_SERVICE_ANNOUNCEMENT, SECURITY_ALERT, SOLE_PROPRIETOR, SWEEPSTAKE, TRIAL, UCAAS_HIGH, UCAAS_LOW — NOT SOCIAL, which TCR rejects as a sub-usecase for every parent usecase even though it is valid as the top-level `usecase`)
|
|
40
40
|
* @property {string} [description] - A detailed description of the campaign (optional, must be between 40 and 4096 characters if provided)
|
|
41
41
|
* @property {boolean} [embeddedLink] - Whether the campaign includes an embedded link (optional)
|
|
42
42
|
* @property {boolean} [embeddedPhone] - Whether the campaign includes an embedded phone number (optional)
|
|
@@ -115,7 +115,8 @@
|
|
|
115
115
|
* @property {string} [doubleOptInMessage] - Required when adultContent is true (20-1024 characters)
|
|
116
116
|
* @property {string} programSummary - Generated-but-editable campaign/program summary (required, 40-2048 characters)
|
|
117
117
|
* @property {string} optInConfirmationMessage - The opt-in confirmation message (required, 20-1024 characters)
|
|
118
|
-
* @property {string}
|
|
118
|
+
* @property {string} optInUrl - Public HTTPS URL for the live opt-in experience, shown to reviewers as a link (required; private, local, and credentialed URLs are rejected)
|
|
119
|
+
* @property {string} screenshotUrl - Hosted opt-in proof screenshot URL returned by `uploadOptInImage` (required). Must be a Signal House-hosted opt-in image owned by your group; external URLs are rejected
|
|
119
120
|
*/
|
|
120
121
|
|
|
121
122
|
/**
|
|
@@ -129,7 +130,6 @@
|
|
|
129
130
|
* @property {string} sample1 - Sample message 1 (required, 20-1024 characters)
|
|
130
131
|
* @property {string} sample2 - Sample message 2 (required, 20-1024 characters)
|
|
131
132
|
* @property {string} sample3 - Sample message 3 (required, 20-1024 characters)
|
|
132
|
-
* @property {boolean} [autoRenewal=true] - Whether the campaign should auto-renew (optional, defaults to true)
|
|
133
133
|
* @property {string} [tag] - A tag for the campaign (optional, at most 255 characters)
|
|
134
134
|
* @property {ShortCodeDetails} shortCode - The Short Code campaign details (required)
|
|
135
135
|
*/
|
|
@@ -186,13 +186,14 @@ export class Campaigns {
|
|
|
186
186
|
/**
|
|
187
187
|
* Transition a Short Code campaign's review status (SHGHL-2225). A customer-visible reason is
|
|
188
188
|
* required for both rejection states ("REJECTED" = Signal House Rejected, "DCA_REJECTED" =
|
|
189
|
-
* Rejected).
|
|
189
|
+
* Rejected). Selecting "PENDING_DCA_APPROVAL" runs the guarded carrier-review transition;
|
|
190
|
+
* fulfillment remains a separate staff operation.
|
|
190
191
|
* @async
|
|
191
192
|
* @roles signalhouse
|
|
192
193
|
* @param {Object} params - The parameters for the status transition
|
|
193
194
|
* @param {string} params.campaignId - The ID of the campaign to transition
|
|
194
|
-
* @param {string} params.status - The target status: "PENDING_REVIEW", "REJECTED", "
|
|
195
|
-
* @param {string} [params.rejectionReason] - Required for "REJECTED"/"DCA_REJECTED" (
|
|
195
|
+
* @param {string} params.status - The target status: "PENDING_REVIEW", "REJECTED", "PENDING_DCA_APPROVAL", "DCA_REJECTED", or "ACTIVE". "PENDING_DCA_APPROVAL" requires a Signal House-approved Short Code brand, issued code, and captured opt-in proof.
|
|
196
|
+
* @param {string} [params.rejectionReason] - Required, nonblank reason for "REJECTED"/"DCA_REJECTED" (max 1024 characters)
|
|
196
197
|
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
|
|
197
198
|
* @throws {Error} Throws an error if the campaignId or status parameter is missing
|
|
198
199
|
* @returns {Promise<Object>} The updated campaign
|
|
@@ -213,16 +214,17 @@ export class Campaigns {
|
|
|
213
214
|
* @param {Object} params - Fulfillment parameters.
|
|
214
215
|
* @param {string} params.campaignId - Campaign identifier.
|
|
215
216
|
* @param {string} params.actualCode - Issued five- or six-digit Short Code.
|
|
217
|
+
* @param {string} params.leaseEndDate - Fixed future lease end date. A YYYY-MM-DD value expires at 23:59:59 UTC; timestamps retain their supplied time.
|
|
216
218
|
* @param {string} [params.internalNotes] - Staff-only fulfillment notes.
|
|
217
219
|
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options.
|
|
218
220
|
* @returns {Promise<Object>} The updated campaign.
|
|
219
221
|
*/
|
|
220
|
-
fulfillShortCodeCampaign: async ({ campaignId, actualCode, internalNotes, options = {} }) => {
|
|
221
|
-
this.client._require({ campaignId, actualCode });
|
|
222
|
+
fulfillShortCodeCampaign: async ({ campaignId, actualCode, leaseEndDate, internalNotes, options = {} }) => {
|
|
223
|
+
this.client._require({ campaignId, actualCode, leaseEndDate });
|
|
222
224
|
const safeCampaignId = encodeURIComponent(campaignId);
|
|
223
225
|
return this.client(`/campaign/short-code/${safeCampaignId}/fulfill`, {
|
|
224
226
|
method: 'POST',
|
|
225
|
-
body: { actualCode, internalNotes },
|
|
227
|
+
body: { actualCode, leaseEndDate, internalNotes },
|
|
226
228
|
...options,
|
|
227
229
|
});
|
|
228
230
|
},
|
|
@@ -243,6 +245,39 @@ export class Campaigns {
|
|
|
243
245
|
...options,
|
|
244
246
|
});
|
|
245
247
|
},
|
|
248
|
+
/** Confirm Registry offboarding and complete a pending Short Code cancellation. */
|
|
249
|
+
completeShortCodeCancellation: async ({ campaignId, requestId, note, options = {} }) => {
|
|
250
|
+
this.client._require({ campaignId, requestId });
|
|
251
|
+
const safeCampaignId = encodeURIComponent(campaignId);
|
|
252
|
+
return this.client(`/campaign/short-code/${safeCampaignId}/cancellation/complete`, {
|
|
253
|
+
method: 'POST',
|
|
254
|
+
body: { requestId, note },
|
|
255
|
+
...options,
|
|
256
|
+
});
|
|
257
|
+
},
|
|
258
|
+
/** Dismiss a pending Short Code cancellation and restore its prior lifecycle state. */
|
|
259
|
+
dismissShortCodeCancellation: async ({ campaignId, requestId, note, options = {} }) => {
|
|
260
|
+
this.client._require({ campaignId, requestId });
|
|
261
|
+
const safeCampaignId = encodeURIComponent(campaignId);
|
|
262
|
+
return this.client(`/campaign/short-code/${safeCampaignId}/cancellation/dismiss`, {
|
|
263
|
+
method: 'POST',
|
|
264
|
+
body: { requestId, note },
|
|
265
|
+
...options,
|
|
266
|
+
});
|
|
267
|
+
},
|
|
268
|
+
/** Read expired Short Code leases awaiting manual Registry offboarding. */
|
|
269
|
+
getExpiredShortCodeLeases: async ({ page, limit, options = {} } = {}) => {
|
|
270
|
+
const query = this.client._getQueryString({ page, limit });
|
|
271
|
+
return this.client(`/campaign/short-code/expired-leases${query}`, { method: 'GET', ...options });
|
|
272
|
+
},
|
|
273
|
+
/** Confirm Registry offboarding and mark an expired Short Code released. */
|
|
274
|
+
releaseExpiredShortCodeLease: async ({ campaignId, note, options = {} }) => {
|
|
275
|
+
this.client._require({ campaignId });
|
|
276
|
+
const safeCampaignId = encodeURIComponent(campaignId);
|
|
277
|
+
return this.client(`/campaign/short-code/${safeCampaignId}/expired-lease/release`, {
|
|
278
|
+
method: 'POST', body: { note }, ...options,
|
|
279
|
+
});
|
|
280
|
+
},
|
|
246
281
|
};
|
|
247
282
|
}
|
|
248
283
|
}
|
|
@@ -273,6 +308,14 @@ export class Campaigns {
|
|
|
273
308
|
* window, which is not the same as a score of 0 -- null means nobody replied, 0 means replies
|
|
274
309
|
* averaged neutral. `updatedAt` is null until the first rollup writes the record, and it tracks when
|
|
275
310
|
* the figures last CHANGED, not when the job last ran.
|
|
311
|
+
*
|
|
312
|
+
* Every record also carries a `health` object -- trailing 7-day and 30-day delivery/opt-out health from
|
|
313
|
+
* the same periodic refresh: `{ sevenDay, thirtyDay, updatedAt }`, each window being `{ score,
|
|
314
|
+
* deliveryRate, optOutRate, deliveryScore, optOutScore, messagesSent, messagesDelivered, messagesFailed,
|
|
315
|
+
* optOuts }`. `score` is 1.0..10.0 (the mean of the two bucket scores) and is null when nothing was sent
|
|
316
|
+
* in the window; the volumes say how much traffic sits behind it. A campaign's figure is scored from the
|
|
317
|
+
* campaign's own summed counters, never averaged from its numbers. For a live figure use GET /number/health
|
|
318
|
+
* or GET /campaign/health.
|
|
276
319
|
* @returns {Promise<Array|Object>} The response from the server - array when unpaginated, or { data, total, page, limit, totalPages } when paginated
|
|
277
320
|
*/
|
|
278
321
|
async getCampaigns({
|
|
@@ -354,9 +397,9 @@ export class Campaigns {
|
|
|
354
397
|
|
|
355
398
|
/**
|
|
356
399
|
* Create a new Short Code campaign and submit it for Signal House review (SHGHL-2225). Requires an
|
|
357
|
-
* approved (VERIFIED) Short Code brand.
|
|
358
|
-
|
|
359
|
-
|
|
400
|
+
* approved (VERIFIED) Short Code brand. Upload the opt-in proof screenshot first with `uploadOptInImage`
|
|
401
|
+
* and pass the returned URL as `campaignData.shortCode.screenshotUrl` (required). Request or register the
|
|
402
|
+
* campaign's Short Code separately through `numbers.requestShortCodeAcquisition` after creation.
|
|
360
403
|
* @async
|
|
361
404
|
* @roles api, admin, developer, user
|
|
362
405
|
* @param {Object} params - The parameters for creating the Short Code campaign
|
|
@@ -379,7 +422,7 @@ export class Campaigns {
|
|
|
379
422
|
* @roles api, admin, developer, user
|
|
380
423
|
* @param {Object} params - The parameters for updating the Short Code campaign
|
|
381
424
|
* @param {string} params.campaignId - The ID of the campaign to update
|
|
382
|
-
* @param {Object} params.updateData - The fields to update (top-level campaign fields plus an optional `shortCode` object of editable Short Code fields)
|
|
425
|
+
* @param {Object} params.updateData - The fields to update (top-level campaign fields plus an optional `shortCode` object of editable Short Code fields; pass a new `uploadOptInImage` URL as `shortCode.screenshotUrl` to replace the opt-in proof)
|
|
383
426
|
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
|
|
384
427
|
* @throws {Error} Throws an error if the campaignId parameter is missing
|
|
385
428
|
* @returns {Promise<Object>} The updated campaign
|
|
@@ -391,10 +434,9 @@ export class Campaigns {
|
|
|
391
434
|
}
|
|
392
435
|
|
|
393
436
|
/**
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
* already-fulfilled Signal House request) is never auto-released — see SHGHL-2228 for offboarding.
|
|
437
|
+
* Cancel a Short Code campaign. A customer cancellation for an issued Short Code returns
|
|
438
|
+
* PENDING_DELETE (displayed as Cancellation Pending) until Signal House confirms Registry offboarding.
|
|
439
|
+
* Unissued RANDOM/VANITY requests, plus staff-confirmed cancellations, return EXPIRED immediately.
|
|
398
440
|
* @async
|
|
399
441
|
* @roles api, admin, developer, user
|
|
400
442
|
* @param {Object} params - The parameters for cancelling the campaign
|
|
@@ -430,7 +472,7 @@ export class Campaigns {
|
|
|
430
472
|
|
|
431
473
|
/**
|
|
432
474
|
* Upload an opt-in proof image to be hosted on-platform, returning a publicly-fetchable URL suitable for a
|
|
433
|
-
* Toll-Free campaign's optInImageURLs
|
|
475
|
+
* Toll-Free campaign's optInImageURLs or a Short Code campaign's shortCode.screenshotUrl
|
|
434
476
|
* @async
|
|
435
477
|
* @roles api, admin, developer, user
|
|
436
478
|
* @param {Object} params - The parameters for uploading the opt-in image
|
package/src/domains/Messages.js
CHANGED
|
@@ -5,6 +5,16 @@ export class Messages {
|
|
|
5
5
|
this.enableAdmin = enableAdmin;
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* Estimate Canadian SMS/MMS retail cost without sending or charging.
|
|
10
|
+
* @async
|
|
11
|
+
* @param {Object} params - Sender, up to 100 recipients, messageBody and request options.
|
|
12
|
+
* @returns {Promise<Object>} - Per-recipient rates and total in microdollars; unknown carriers use the upper fallback.
|
|
13
|
+
*/
|
|
14
|
+
async estimateMessage({ senderPhoneNumber, recipientPhoneNumbers, messageBody, messageType = "SMS", options = {} }) {
|
|
15
|
+
return this.client("/message/estimate", { method: "POST", body: { senderPhoneNumber, recipientPhoneNumbers, messageBody, messageType }, ...options });
|
|
16
|
+
}
|
|
17
|
+
|
|
8
18
|
/**
|
|
9
19
|
* Get a list of messages with optional filters and pagination parameters
|
|
10
20
|
* @async
|
|
@@ -18,7 +28,7 @@ export class Messages {
|
|
|
18
28
|
* @param {string} [params.status] - Filter messages by their status (ENQUEUED, DEQUEUED, SENT, FAILED, DELIVERED)
|
|
19
29
|
* @param {string} [params.direction] - Filter messages by their direction (INBOUND, OUTBOUND)
|
|
20
30
|
* @param {string|string[]} [params.messageType] - Filter messages by their type. Accepts a single value or an array (e.g. ["SMS", "MMS"]). Allowed values: SMS, MMS, RCS, WHATSAPP, VIBER, P2P. When omitted, defaults to all non-P2P types.
|
|
21
|
-
* @param {string|string[]} [params.channel] - Filter messages by channel. Accepts a single value or an array. Allowed values: tenDLC, tollFree, shortCode, p2p. Each message records its channel when it is saved, and this filters on that stored value; older messages from before this feature have no channel and count as tenDLC. Ignored when matchAny is true (matchAny takes precedence).
|
|
31
|
+
* @param {string|string[]} [params.channel] - Filter messages by channel. Accepts a single value or an array. Allowed values: tenDLC, virtualLongCode, tollFree, shortCode, p2p. Each message records its channel when it is saved, and this filters on that stored value; older messages from before this feature have no channel and count as tenDLC. Ignored when matchAny is true (matchAny takes precedence).
|
|
22
32
|
* @param {boolean} [params.matchAny] - When true, the provided campaignId/brandId/phoneNumber filters are OR'd (a message matches ANY of them) instead of the default most-specific-single behavior. subgroupId stays an AND scope. Opt-in/additive.
|
|
23
33
|
* @param {string} [params.carrier] - Filter messages by the carrier used for sending
|
|
24
34
|
* @param {string|string[]} [params.sentimentLabel] - Filter messages by sentiment bucket. Accepts a single value or an array (e.g. ["positive", "negative"]). Allowed values: positive, neutral, negative. Applied as the sentimentScore range the ±25 label threshold produces, so unscored messages match no bucket and outbound messages (never scored) are excluded.
|
|
@@ -95,11 +105,12 @@ export class Messages {
|
|
|
95
105
|
* @param {string|string[]} [params.campaignId] - Filter analytics by the ID of the associated campaign. Accepts a single value, an array, or a comma-separated string.
|
|
96
106
|
* @param {string|string[]} [params.phoneNumber] - Filter analytics by the phone number involved in the messages. Accepts a single value, an array, or a comma-separated string.
|
|
97
107
|
* @param {string|string[]} [params.carrier] - Filter analytics by the carrier used for sending. Accepts a single value, an array, or a comma-separated string.
|
|
108
|
+
* @param {string|string[]} [params.carrierFamily] - Filter analytics by the recipient's resolved carrier family (Default, ATT, TMobile, Verizon, USCellular, GoogleVoice, ClearSky, Interop, RogueMobile, P2P). Accepts a single value, an array, or a comma-separated string. Only accepted where the environment serves hourly analytics; elsewhere any value is rejected with a 400 -- omit the parameter unless it is wanted.
|
|
98
109
|
* @param {string} [params.startDate] - ISO-8601 date or timestamp; normalized to start-of-UTC-day (inclusive)
|
|
99
110
|
* @param {string} [params.endDate] - ISO-8601 date or timestamp; normalized to end-of-UTC-day (inclusive). Hourly resolution is not supported
|
|
100
111
|
* @param {boolean} [params.matchAny] - When true, the provided campaignId/brandId/phoneNumber filters are OR'd (match ANY) instead of the default most-specific-single behavior. subgroupId stays an AND scope. Opt-in/additive.
|
|
101
112
|
* @param {(string|string[])} [params.messageType] - Message type(s) the SENTIMENT figures are scoped to: SMS, MMS or P2P (single value, array, or comma-separated string). Omit for all scored types. Does NOT narrow the message counts, which are always returned split per type (smsInbound/mmsInbound/p2pInbound) and have no filterable type dimension.
|
|
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).
|
|
113
|
+
* @param {string|string[]} [params.channel] - Filter analytics by channel (tenDLC, virtualLongCode, tollFree, shortCode, p2p). Filters on the stored channel column; a tenDLC selection also includes older messages that have no channel, and p2p is a real channel here (matched by carrier). Accepts a single value or an array. Ignored when matchAny is true (matchAny takes precedence).
|
|
103
114
|
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
|
|
104
115
|
* @returns {Promise<Object>} - A promise that resolves to the analytics data. Also includes inbound-message
|
|
105
116
|
* sentiment for the requested scope: sentimentScore (volume-weighted average of every scored inbound message
|
|
@@ -110,8 +121,8 @@ export class Messages {
|
|
|
110
121
|
* summed or re-averaged across types, rows or responses. To weight a subset of message types, pass
|
|
111
122
|
* messageType and read sentimentScore.
|
|
112
123
|
*/
|
|
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 };
|
|
124
|
+
async getAnalytics({ groupId, subgroupId, brandId, campaignId, phoneNumber, carrier, carrierFamily, startDate, endDate, channel, messageType, matchAny, options = {} }) {
|
|
125
|
+
const filters = { groupId, subgroupId, brandId, campaignId, phoneNumber, carrier, carrierFamily, startDate, endDate, channel, messageType, matchAny };
|
|
115
126
|
const queryString = this.client._getQueryString(filters);
|
|
116
127
|
return this.client(`/message/analytics${queryString}`, { method: "GET", ...options });
|
|
117
128
|
}
|
|
@@ -127,10 +138,13 @@ export class Messages {
|
|
|
127
138
|
* @param {string|string[]} [params.campaignId] - Filter analytics by the ID of the associated campaign. Accepts a single value, an array, or a comma-separated string.
|
|
128
139
|
* @param {string|string[]} [params.phoneNumber] - Filter analytics by the phone number involved in the messages. Accepts a single value, an array, or a comma-separated string.
|
|
129
140
|
* @param {string|string[]} [params.carrier] - Filter analytics by the carrier used for sending. Accepts a single value, an array, or a comma-separated string.
|
|
130
|
-
* @param {string} [params.
|
|
131
|
-
* @param {string} [params.
|
|
141
|
+
* @param {string|string[]} [params.carrierFamily] - Filter analytics by the recipient's resolved carrier family (Default, ATT, TMobile, Verizon, USCellular, GoogleVoice, ClearSky, Interop, RogueMobile, P2P). Accepts a single value, an array, or a comma-separated string. Only accepted where the environment serves hourly analytics; elsewhere any value is rejected with a 400 -- omit the parameter unless it is wanted.
|
|
142
|
+
* @param {string} [params.startDate] - ISO-8601 date or timestamp. At day granularity it is normalized to start-of-UTC-day (inclusive); at hour granularity it is floored to its hour.
|
|
143
|
+
* @param {string} [params.endDate] - ISO-8601 date or timestamp. At day granularity it is normalized to end-of-UTC-day (inclusive); at hour granularity it is honoured as given.
|
|
132
144
|
* @param {(string|string[])} [params.messageType] - Message type(s) the SENTIMENT figures are scoped to: SMS, MMS or P2P (single value, array, or comma-separated string). Omit for all scored types. Does NOT narrow the message counts, which are always returned split per type (smsInbound/mmsInbound/p2pInbound) and have no filterable type dimension.
|
|
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.
|
|
145
|
+
* @param {string|string[]} [params.channel] - Filter analytics by channel (tenDLC, virtualLongCode, tollFree, shortCode, p2p). Filters on the stored channel column; a tenDLC selection also includes older messages that have no channel, and p2p is a real channel here. Accepts a single value or an array.
|
|
146
|
+
* @param {("day"|"hour")} [params.granularity] - Time-bucket grain of the byDate rows. Omit for day (each row's _id is a "YYYY-MM-DD" date). "hour" buckets by hour (each row's _id is a "YYYY-MM-DD HH:MM:SS" UTC hour) and is capped to a 7-day span. Only accepted where the environment serves hourly analytics; elsewhere any value, including "day", is rejected with a 400 -- omit the parameter unless hour grain is wanted.
|
|
147
|
+
* @param {("carrier"|"carrierFamily")} [params.breakdown] - Adds a byBreakdown time × dimension series to the response ({ dimension, rows }: each row is one byDate bucket (_id) for one carrier or carrier family (key), over the top 50 keys by volume, 10DLC only) and caps the span at 31 days. Only accepted where the environment serves hourly analytics; elsewhere any value is rejected with a 400 -- omit the parameter unless it is wanted.
|
|
134
148
|
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
|
|
135
149
|
* @returns {Promise<Array>} - A promise that resolves to an array of analytics snapshot records. cardTotals and
|
|
136
150
|
* every byDate/byPhoneNumber/byCarrier row also carry that row's own inbound-message sentiment: sentimentScore
|
|
@@ -140,8 +154,8 @@ export class Messages {
|
|
|
140
154
|
* score is divided server-side and the raw sums are never returned: a score is an average and must never be
|
|
141
155
|
* summed or re-averaged across types, rows or responses.
|
|
142
156
|
*/
|
|
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 };
|
|
157
|
+
async getAnalyticsDetail({ groupId, subgroupId, brandId, campaignId, phoneNumber, carrier, carrierFamily, startDate, endDate, channel, messageType, granularity, breakdown, options = {} }) {
|
|
158
|
+
const filters = { groupId, subgroupId, brandId, campaignId, phoneNumber, carrier, carrierFamily, startDate, endDate, channel, messageType, granularity, breakdown };
|
|
145
159
|
const queryString = this.client._getQueryString(filters);
|
|
146
160
|
return this.client(`/message/analytics/detail${queryString}`, { method: "GET", ...options });
|
|
147
161
|
}
|
|
@@ -174,18 +188,19 @@ export class Messages {
|
|
|
174
188
|
* @param {string|string[]} [params.campaignId]
|
|
175
189
|
* @param {string|string[]} [params.phoneNumber]
|
|
176
190
|
* @param {string|string[]} [params.carrier]
|
|
191
|
+
* @param {string|string[]} [params.carrierFamily] - Resolved carrier family of the recipient (Default, ATT, TMobile, Verizon, USCellular, GoogleVoice, ClearSky, Interop, RogueMobile, P2P); single value, array, or comma-separated. Only accepted where the environment serves hourly analytics; elsewhere any value is rejected with a 400 -- omit the parameter unless it is wanted.
|
|
177
192
|
* @param {string} [params.startDate]
|
|
178
193
|
* @param {string} [params.endDate]
|
|
179
194
|
* @param {number} [params.page=1]
|
|
180
195
|
* @param {number} [params.limit=50] - max 50 per page
|
|
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).
|
|
196
|
+
* @param {("tenDLC"|"virtualLongCode"|"tollFree"|"shortCode"|"p2p"|"both")|Array<"tenDLC"|"virtualLongCode"|"tollFree"|"shortCode"|"p2p">} [params.channel="both"] - Filter and rank rows by the stored channel column. "both" (default) means all activity. tenDLC/virtualLongCode/tollFree/shortCode/p2p (single value or array) limit to the selected channel(s).
|
|
182
197
|
* @param {(string|string[])} [params.messageType] - Message type(s) the SENTIMENT figures are scoped to: SMS, MMS or P2P (single value, array, or comma-separated string). Omit for all scored types. Does NOT narrow the message counts, which are always returned split per type (smsInbound/mmsInbound/p2pInbound) and have no filterable type dimension.
|
|
183
198
|
* @param {import('../SignalHouseSDK').RequestOptions} [params.options]
|
|
184
199
|
* @returns {Promise<Object>} - { rows, totalCount, page, limit }. Each row carries sms/mms/p2p metric columns plus `smsOptOuts` and `mmsOptOuts` from the DNC analytics MV (P2P has no opt-outs).
|
|
185
200
|
* Each row also carries that subgroup's inbound-message sentiment: `sentimentScore` (volume-weighted average of every scored inbound message in that subgroup, -100..100, null when nothing was scored), `sentimentLabel`, `sentimentScoredCount`, `sentimentPositive`, `sentimentNeutral`, `sentimentNegative`, plus the same six per message type under `smsSentiment*`, `mmsSentiment*` and `p2pSentiment*` prefixes. The score is derived server-side and must never be re-averaged across rows — combine the counts, not the scores.
|
|
186
201
|
*/
|
|
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 };
|
|
202
|
+
async getAnalyticsBySubgroup({ groupId, subgroupId, brandId, campaignId, phoneNumber, carrier, carrierFamily, startDate, endDate, page, limit, channel, messageType, options = {} }) {
|
|
203
|
+
const filters = { groupId, subgroupId, brandId, campaignId, phoneNumber, carrier, carrierFamily, startDate, endDate, page, limit, channel, messageType };
|
|
189
204
|
const queryString = this.client._getQueryString(filters);
|
|
190
205
|
return this.client(`/message/analytics/by-subgroup${queryString}`, { method: "GET", ...options });
|
|
191
206
|
}
|
|
@@ -202,16 +217,17 @@ export class Messages {
|
|
|
202
217
|
* @param {string|string[]} [params.campaignId]
|
|
203
218
|
* @param {string|string[]} [params.phoneNumber]
|
|
204
219
|
* @param {string|string[]} [params.carrier]
|
|
220
|
+
* @param {string|string[]} [params.carrierFamily] - Resolved carrier family of the recipient (Default, ATT, TMobile, Verizon, USCellular, GoogleVoice, ClearSky, Interop, RogueMobile, P2P); single value, array, or comma-separated. Only accepted where the environment serves hourly analytics; elsewhere any value is rejected with a 400 -- omit the parameter unless it is wanted.
|
|
205
221
|
* @param {string} [params.startDate]
|
|
206
222
|
* @param {string} [params.endDate]
|
|
207
223
|
* @param {number} [params.page=1]
|
|
208
224
|
* @param {number} [params.limit=50] - max 50 per page
|
|
209
|
-
* @param {("tenDLC"|"tollFree"|"shortCode"|"p2p"|"both")|Array<"tenDLC"|"tollFree"|"shortCode"|"p2p">} [params.channel="both"] - Filter and rank rows by the stored channel column. "both" (default) means every code. tenDLC/tollFree/shortCode/p2p (single value or array) limit to the selected channel(s); when one channel is selected, totalErrors reflects only that channel.
|
|
225
|
+
* @param {("tenDLC"|"virtualLongCode"|"tollFree"|"shortCode"|"p2p"|"both")|Array<"tenDLC"|"virtualLongCode"|"tollFree"|"shortCode"|"p2p">} [params.channel="both"] - Filter and rank rows by the stored channel column. "both" (default) means every code. tenDLC/virtualLongCode/tollFree/shortCode/p2p (single value or array) limit to the selected channel(s); when one channel is selected, totalErrors reflects only that channel.
|
|
210
226
|
* @param {import('../SignalHouseSDK').RequestOptions} [params.options]
|
|
211
227
|
* @returns {Promise<Object>} - { rows, totalCount, totalErrors: { sms, mms, p2p, all }, page, limit }
|
|
212
228
|
*/
|
|
213
|
-
async getAnalyticsByErrorCode({ groupId, subgroupId, brandId, campaignId, phoneNumber, carrier, startDate, endDate, page, limit, channel, options = {} }) {
|
|
214
|
-
const filters = { groupId, subgroupId, brandId, campaignId, phoneNumber, carrier, startDate, endDate, page, limit, channel };
|
|
229
|
+
async getAnalyticsByErrorCode({ groupId, subgroupId, brandId, campaignId, phoneNumber, carrier, carrierFamily, startDate, endDate, page, limit, channel, options = {} }) {
|
|
230
|
+
const filters = { groupId, subgroupId, brandId, campaignId, phoneNumber, carrier, carrierFamily, startDate, endDate, page, limit, channel };
|
|
215
231
|
const queryString = this.client._getQueryString(filters);
|
|
216
232
|
return this.client(`/message/analytics/by-error-code${queryString}`, { method: "GET", ...options });
|
|
217
233
|
}
|
|
@@ -229,9 +245,9 @@ export class Messages {
|
|
|
229
245
|
* @param {string} [params.carrier] - Filter by the carrier
|
|
230
246
|
* @param {string} [params.startDate] - ISO-8601 date or timestamp; normalized to start-of-UTC-day (inclusive)
|
|
231
247
|
* @param {string} [params.endDate] - ISO-8601 date or timestamp; normalized to end-of-UTC-day (inclusive). Hourly resolution is not supported
|
|
232
|
-
* @param {string|string[]} [params.channel] - Filter by channel (tenDLC, tollFree, shortCode). Opt-outs are A2P-only, so p2p applies no filter. Filters on the stored channel column; a tenDLC selection also includes older opt-outs that have no channel.
|
|
248
|
+
* @param {string|string[]} [params.channel] - Filter by channel (tenDLC, virtualLongCode, tollFree, shortCode). Opt-outs are A2P-only, so p2p applies no filter. Filters on the stored channel column; a tenDLC selection also includes older opt-outs that have no channel.
|
|
233
249
|
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
|
|
234
|
-
* @returns {Promise<Object>} - A promise that resolves to the DNC analytics data (totals, byDate, byPhoneNumber, byCarrier)
|
|
250
|
+
* @returns {Promise<Object>} - A promise that resolves to the DNC analytics data (totals, byDate, byPhoneNumber, byCarrier, byKeyword). byKeyword breaks opt-outs down by the normalized keyword that revoked consent ({ optOutKeyword, total, sms, mms }); opt-outs recorded before keyword capture shipped appear as a single optOutKeyword: null bucket ("not recorded"). The distinct keyword set is open-ended (campaigns register their own keywords beyond the mandatory floor) — render top-N plus Other, never a fixed list.
|
|
235
251
|
*/
|
|
236
252
|
async getDncAnalytics({ groupId, subgroupId, brandId, campaignId, phoneNumber, carrier, startDate, endDate, channel, options = {} }) {
|
|
237
253
|
const filters = { groupId, subgroupId, brandId, campaignId, phoneNumber, carrier, startDate, endDate, channel };
|
|
@@ -256,9 +272,9 @@ export class Messages {
|
|
|
256
272
|
* @param {number} [params.limit] - Number of records per page
|
|
257
273
|
* @param {string} [params.sortField] - Field to sort by
|
|
258
274
|
* @param {string} [params.sortOrder] - Sort direction (asc, desc)
|
|
259
|
-
* @param {string|string[]} [params.channel] - Filter by channel (tenDLC, tollFree, shortCode). Opt-outs are A2P-only, so p2p applies no filter. Filters on the stored channel column; a tenDLC selection also includes older opt-outs that have no channel.
|
|
275
|
+
* @param {string|string[]} [params.channel] - Filter by channel (tenDLC, virtualLongCode, tollFree, shortCode). Opt-outs are A2P-only, so p2p applies no filter. Filters on the stored channel column; a tenDLC selection also includes older opt-outs that have no channel.
|
|
260
276
|
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
|
|
261
|
-
* @returns {Promise<Object>} - A promise that resolves to the paginated DNC records
|
|
277
|
+
* @returns {Promise<Object>} - A promise that resolves to the paginated DNC records. Each record carries optOutKeyword — the normalized keyword that revoked consent (e.g. "stop", "opt out"; a repeat opt-out records the most recent word), null for opt-outs recorded before keyword capture shipped — and carrierFamily, the resolved carrier family of the recipient number (Default, ATT, TMobile, Verizon, USCellular, GoogleVoice, ClearSky, Interop, RogueMobile), copied from the inbound message that triggered the opt-out.
|
|
262
278
|
*/
|
|
263
279
|
async getDncRecords({ groupId, subgroupId, brandId, campaignId, phoneNumber, carrier, startDate, endDate, page, limit, sortField, sortOrder, channel, options = {} }) {
|
|
264
280
|
const filters = { groupId, subgroupId, brandId, campaignId, phoneNumber, carrier, startDate, endDate, page, limit, sortField, sortOrder, channel };
|
|
@@ -282,7 +298,7 @@ export class Messages {
|
|
|
282
298
|
* @roles api, admin, developer, billing, user
|
|
283
299
|
* @param {Object} params - The parameters for sending an SMS message
|
|
284
300
|
* @param {string} params.senderPhoneNumber - The 5-6 digit Short Code or 10+ digit phone number to send the message from
|
|
285
|
-
* @param {string|string[]} params.recipientPhoneNumbers - The phone number(s) to send the message to
|
|
301
|
+
* @param {string|string[]} params.recipientPhoneNumbers - The 10+ digit phone number(s) to send the message to. A Short Code sender permits exactly one recipient, and it must be a +1 (US/Canada) number; a bare 10-digit number is treated as +1. The API rejects Short Code sends with multiple recipients or a non-+1 recipient.
|
|
286
302
|
* @param {string} params.messageBody - The body of the SMS message
|
|
287
303
|
* @param {string} [params.statusCallbackUrl] - The URL to receive status callbacks
|
|
288
304
|
* @param {boolean} [params.enableShortlink=false] - Whether to enable shortlink in the message
|
|
@@ -363,7 +379,7 @@ export class Messages {
|
|
|
363
379
|
* @roles api, admin, developer, billing, user
|
|
364
380
|
* @param {Object} params - The parameters for sending an MMS message
|
|
365
381
|
* @param {string} params.senderPhoneNumber - The 5-6 digit Short Code or 10+ digit phone number to send the message from
|
|
366
|
-
* @param {string[]} params.recipientPhoneNumbers - The phone number(s) to send the message to
|
|
382
|
+
* @param {string[]} params.recipientPhoneNumbers - The 10+ digit phone number(s) to send the message to. A Short Code sender permits exactly one recipient, and it must be a +1 (US/Canada) number; a bare 10-digit number is treated as +1. The API rejects Short Code sends with multiple recipients or a non-+1 recipient.
|
|
367
383
|
* @param {string} params.messageBody - The body of the MMS message
|
|
368
384
|
* @param {string[]} [params.mediaUrls] - The URLs of the media attachments
|
|
369
385
|
* @param {string} [params.statusCallbackUrl] - The URL to receive status callbacks
|
package/src/domains/Numbers.js
CHANGED
|
@@ -86,6 +86,14 @@ export class Numbers {
|
|
|
86
86
|
* window, which is not the same as a score of 0 -- null means nobody replied, 0 means replies
|
|
87
87
|
* averaged neutral. `updatedAt` is null until the first rollup writes the record, and it tracks when
|
|
88
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.
|
|
89
97
|
* @returns {Promise<Object>} A promise that resolves to the list of phone numbers
|
|
90
98
|
*/
|
|
91
99
|
async getPhoneNumbers({ phoneNumber, campaignId, brandId, subgroupId, groupId, page, limit, options = {} }) {
|
|
@@ -120,6 +128,7 @@ export class Numbers {
|
|
|
120
128
|
* @param {boolean} [params.voiceEnabled] - Filter for phone numbers that are voice enabled
|
|
121
129
|
* @param {string} [params.country] - Filter by country code (e.g., "US")
|
|
122
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.
|
|
123
132
|
* @param {string} [params.npa] - Filter by NPA (area code)
|
|
124
133
|
* @param {string} [params.nxx] - Filter by NXX (central office code) - the first three digits of the local phone number after the area code
|
|
125
134
|
* @param {string} [params.phoneNumber] - Filter by phone number
|
|
@@ -134,6 +143,7 @@ export class Numbers {
|
|
|
134
143
|
voiceEnabled,
|
|
135
144
|
country,
|
|
136
145
|
state,
|
|
146
|
+
city,
|
|
137
147
|
npa,
|
|
138
148
|
nxx,
|
|
139
149
|
phoneNumber,
|
|
@@ -141,7 +151,7 @@ export class Numbers {
|
|
|
141
151
|
page,
|
|
142
152
|
options = {},
|
|
143
153
|
}) {
|
|
144
|
-
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 };
|
|
145
155
|
const queryString = this.client._getQueryString(filters);
|
|
146
156
|
return this.client(`/number/available${queryString}`, { method: 'GET', ...options });
|
|
147
157
|
}
|
|
@@ -156,13 +166,14 @@ export class Numbers {
|
|
|
156
166
|
* @param {Object} params - The parameters for purchasing phone numbers
|
|
157
167
|
* @param {string[]} params.phoneNumbers - The list of phone numbers to purchase
|
|
158
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.
|
|
159
170
|
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
|
|
160
171
|
* @throws {Error} Throws an error if the phoneNumbers or subgroupId parameter is missing
|
|
161
172
|
* @returns {Promise<Object>} A promise that resolves to `{ message }` once the request is queued.
|
|
162
173
|
*/
|
|
163
|
-
async purchasePhoneNumber({ phoneNumbers, subgroupId, options = {} }) {
|
|
174
|
+
async purchasePhoneNumber({ phoneNumbers, subgroupId, country = 'US', options = {} }) {
|
|
164
175
|
this.client._require({ phoneNumbers, subgroupId });
|
|
165
|
-
return this.client(`/number`, { method: 'POST', body: { phoneNumbers, subgroupId }, ...options });
|
|
176
|
+
return this.client(`/number`, { method: 'POST', body: { phoneNumbers, subgroupId, country }, ...options });
|
|
166
177
|
}
|
|
167
178
|
|
|
168
179
|
/**
|
|
@@ -176,19 +187,19 @@ export class Numbers {
|
|
|
176
187
|
* @param {Object} params - The parameters for purchasing toll-free numbers
|
|
177
188
|
* @param {number} params.quantity - The number of toll-free numbers to purchase (1-10)
|
|
178
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.
|
|
179
191
|
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
|
|
180
192
|
* @throws {Error} Throws an error if the quantity or subgroupId parameter is missing
|
|
181
193
|
* @returns {Promise<Object>} A promise that resolves to `{ message, orderId }` once the request is queued.
|
|
182
194
|
*/
|
|
183
|
-
async purchaseTollFreeNumbers({ quantity, subgroupId, options = {} }) {
|
|
195
|
+
async purchaseTollFreeNumbers({ quantity, subgroupId, country = 'US', options = {} }) {
|
|
184
196
|
this.client._require({ quantity, subgroupId });
|
|
185
|
-
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 });
|
|
186
198
|
}
|
|
187
199
|
|
|
188
200
|
/**
|
|
189
|
-
|
|
190
|
-
*
|
|
191
|
-
* 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
|
|
192
203
|
* becomes READY only when its campaign becomes ACTIVE.
|
|
193
204
|
* @async
|
|
194
205
|
* @roles api, admin, developer, billing, user
|
|
@@ -196,13 +207,12 @@ export class Numbers {
|
|
|
196
207
|
* @param {string} params.subgroupId - The owning subgroup ID.
|
|
197
208
|
* @param {string} params.brandId - The owning Short Code brand ID.
|
|
198
209
|
* @param {string} params.campaignId - The owning Short Code campaign ID.
|
|
199
|
-
* @param {'
|
|
200
|
-
* @param {string} [params.existingPhoneNumber] - Required existing five- or six-digit Short Code for INVENTORY.
|
|
210
|
+
* @param {'RANDOM'|'VANITY'|'EXTERNAL_LEASE'} params.requestType - Acquisition path.
|
|
201
211
|
* @param {number} [params.leaseTermMonths] - Required 3, 6, or 12-month term for RANDOM/VANITY.
|
|
202
212
|
* @param {string} [params.requestedVanityCode] - Required five- or six-digit desired code for VANITY.
|
|
203
213
|
* @param {string} [params.actualCode] - Required customer-owned five- or six-digit code for EXTERNAL_LEASE.
|
|
204
214
|
* @param {string} [params.orderId] - Required Registry order ID for EXTERNAL_LEASE.
|
|
205
|
-
|
|
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.
|
|
206
216
|
* @param {Buffer|Blob|File} [params.leaseReceiptFile] - Required PNG, JPEG, or PDF lease receipt for EXTERNAL_LEASE.
|
|
207
217
|
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
|
|
208
218
|
* @returns {Promise<Object>} A pending acquisition request or pending external-lease number.
|
|
@@ -212,7 +222,6 @@ export class Numbers {
|
|
|
212
222
|
brandId,
|
|
213
223
|
campaignId,
|
|
214
224
|
requestType,
|
|
215
|
-
existingPhoneNumber,
|
|
216
225
|
requestedVanityCode,
|
|
217
226
|
leaseTermMonths,
|
|
218
227
|
actualCode,
|
|
@@ -225,7 +234,7 @@ export class Numbers {
|
|
|
225
234
|
const formData = new FormData();
|
|
226
235
|
formData.append(
|
|
227
236
|
'acquisitionData',
|
|
228
|
-
JSON.stringify({ subgroupId, brandId, campaignId, requestType,
|
|
237
|
+
JSON.stringify({ subgroupId, brandId, campaignId, requestType, requestedVanityCode, leaseTermMonths, actualCode, orderId, leaseEndDate }),
|
|
229
238
|
);
|
|
230
239
|
if (leaseReceiptFile) formData.append('leaseReceipt', leaseReceiptFile);
|
|
231
240
|
return this.multipartClient(`/number/short-code`, {
|
|
@@ -351,9 +360,10 @@ export class Numbers {
|
|
|
351
360
|
|
|
352
361
|
/**
|
|
353
362
|
* 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,
|
|
355
|
-
*
|
|
356
|
-
*
|
|
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.
|
|
357
367
|
* @async
|
|
358
368
|
* @roles api, admin, developer, billing, user
|
|
359
369
|
* @param {Object} params - The parameters for assigning phone numbers to a campaign
|
|
@@ -361,7 +371,7 @@ export class Numbers {
|
|
|
361
371
|
* @param {string[]} params.phoneNumbers - The list of phone numbers to assign to the campaign
|
|
362
372
|
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
|
|
363
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
|
|
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).
|
|
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).
|
|
365
375
|
*/
|
|
366
376
|
async assignPhoneNumberToCampaign({ campaignId, phoneNumbers, options = {} }) {
|
|
367
377
|
this.client._require({ campaignId, phoneNumbers });
|
|
@@ -385,7 +395,7 @@ export class Numbers {
|
|
|
385
395
|
}
|
|
386
396
|
|
|
387
397
|
/**
|
|
388
|
-
* 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.
|
|
389
399
|
* @async
|
|
390
400
|
* @roles api, admin, developer, billing, user
|
|
391
401
|
* @param {Object} params - The parameters for deleting phone numbers
|
|
@@ -446,15 +456,15 @@ export class Numbers {
|
|
|
446
456
|
/**
|
|
447
457
|
* Search NPA/NXX lookup data with optional filters.
|
|
448
458
|
* At least one search parameter is required.
|
|
449
|
-
*
|
|
459
|
+
* Country may scope NPA/NXX filters; state and city cannot be combined with them.
|
|
450
460
|
* @async
|
|
451
461
|
* @roles api, admin, developer, billing, user
|
|
452
462
|
* @param {Object} params - The parameters for searching NPA/NXX data
|
|
453
463
|
* @param {string} [params.country] - Filter by country code
|
|
454
464
|
* @param {string} [params.state] - Filter by state code (2 characters)
|
|
455
465
|
* @param {string} [params.city] - Filter by city name (prefix match, case-insensitive; requires country and state)
|
|
456
|
-
* @param {string} [params.npa] - Area code filter (1-3 digits;
|
|
457
|
-
* @param {string} [params.nxx] - Central office code filter (1-3 digits;
|
|
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)
|
|
458
468
|
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
|
|
459
469
|
* @returns {Promise<Object>} A promise that resolves to matching NPA/NXX records or unique NPA/NXX arrays
|
|
460
470
|
*/
|
package/src/domains/Webhooks.js
CHANGED
|
@@ -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
|