@signalhousellc/sdk 1.0.61 → 1.0.63

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.
@@ -5,6 +5,7 @@ import { Calls } from "./voice/Calls.js";
5
5
  import { CallLogs } from "./voice/CallLogs.js";
6
6
  import { GlobalVoiceSettings } from "./voice/GlobalVoiceSettings.js";
7
7
  import { Tokens } from "./voice/Tokens.js";
8
+ import { Analytics } from "./voice/Analytics.js";
8
9
 
9
10
  /**
10
11
  * Voice domain — wraps the voice-backend service (mounted under /voice on the
@@ -19,6 +20,7 @@ import { Tokens } from "./voice/Tokens.js";
19
20
  * - `sdk.voice.callLogs` — Account-scoped call history: list/get + presigned recording.
20
21
  * - `sdk.voice.globalVoiceSettings` — Account-wide voice defaults (accepted regions, max spend, E911).
21
22
  * - `sdk.voice.tokens` — Mint ephemeral SIP credentials for the browser voice SDK.
23
+ * - `sdk.voice.analytics` — Aggregated call analytics (summary tiles + byDate/byNumber/byCarrier breakdowns).
22
24
  */
23
25
  export class Voice {
24
26
  constructor(client, enableAdmin) {
@@ -31,5 +33,6 @@ export class Voice {
31
33
  this.callLogs = new CallLogs(client, enableAdmin);
32
34
  this.globalVoiceSettings = new GlobalVoiceSettings(client, enableAdmin);
33
35
  this.tokens = new Tokens(client, enableAdmin);
36
+ this.analytics = new Analytics(client, enableAdmin);
34
37
  }
35
38
  }
@@ -0,0 +1,76 @@
1
+ /**
2
+ * @typedef {Object} VoiceAnalyticsFilters
3
+ * @property {string} [dateFrom] - ISO-8601 lower bound on call start time.
4
+ * @property {string} [dateTo] - ISO-8601 upper bound on call start time.
5
+ * @property {"day"|"week"|"month"} [groupBy] - Bucket size for the byDate breakdown (default "day").
6
+ * @property {"INBOUND"|"OUTBOUND"} [direction] - Restrict the breakdowns to one direction. Summary tiles always cover both.
7
+ * @property {string} [callSource] - Comma-separated CallLog.callSource list (SIP_TRUNK, PROGRAMMABLE_VOICE, AI_VOICE, WEBRTC, VOICEMAIL, CONFERENCE, PSTN).
8
+ * @property {string} [subgroupId] - Filter by owning subgroup.
9
+ * @property {string} [number] - Substring match against either leg (from OR to).
10
+ * @property {string} [carrier] - Filter by carrier.
11
+ */
12
+
13
+ /**
14
+ * @typedef {Object} VoiceDirectionSummary
15
+ * @property {number} totalCalls
16
+ * @property {number} successfulCalls
17
+ * @property {number} successRate - Percentage (0–100).
18
+ * @property {number} avgCallsPerDay
19
+ * @property {number|null} avgCallDurationSeconds
20
+ * @property {number} totalCallMinutes
21
+ * @property {number} answerRate - Percentage (ASR / answer seizure rate).
22
+ * @property {number} abandonmentRate - Percentage (CANCELED before answer).
23
+ * @property {number} failedCalls
24
+ * @property {number} failureRate - Percentage.
25
+ * @property {number} pctUnder6s - Percentage of answered calls under 6 seconds.
26
+ * @property {number|null} avgRingDurationSeconds - Average answer_time − start_time.
27
+ * @property {number|null} sentimentScore - Positive-sentiment percentage.
28
+ * @property {"Positive"|"Negative"|"Neutral"|null} sentimentLabel
29
+ */
30
+
31
+ /**
32
+ * @typedef {Object} VoiceBreakdownBucket
33
+ * @property {string} key - The date / number / carrier this bucket aggregates.
34
+ * @property {number} total
35
+ * @property {number} completed
36
+ * @property {number} failed
37
+ * @property {number} noAnswer
38
+ * @property {number} busy
39
+ * @property {number} canceled
40
+ * @property {number} inProgress
41
+ * @property {number} totalDurationSeconds
42
+ * @property {number|null} avgSentimentScore
43
+ */
44
+
45
+ /**
46
+ * Voice Analytics — aggregated call metrics for the portal Voice Analytics view
47
+ * (voice-backend `GET /voice/stats/voice-analytics`). Returns per-direction
48
+ * summary tiles (both directions) plus byDate / byNumber / byCarrier status
49
+ * breakdowns for charts. Distinct from `voice.callLogs`, which is the raw call
50
+ * history. Accessed via `sdk.voice.analytics`.
51
+ */
52
+ export class Analytics {
53
+ constructor(client, enableAdmin) {
54
+ this.client = client;
55
+ this.enableAdmin = enableAdmin;
56
+ }
57
+
58
+ /**
59
+ * Get aggregated voice analytics for the current account.
60
+ * @async
61
+ * @roles api, admin, developer, billing, user
62
+ * @param {Object} [params] - Request parameters.
63
+ * @param {VoiceAnalyticsFilters} [params.filters] - Optional filters. Summary tiles honor every filter except `direction`; breakdowns honor all filters.
64
+ * @param {import('../../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
65
+ * @returns {Promise<Object>} `{ success, range, outbound: VoiceDirectionSummary, inbound: VoiceDirectionSummary, byDate: VoiceBreakdownBucket[], byNumber: VoiceBreakdownBucket[], byCarrier: VoiceBreakdownBucket[], byChannel: VoiceBreakdownBucket[] }` (byChannel = per-callSource breakdown).
66
+ */
67
+ async get({ filters = {}, options = {} } = {}) {
68
+ const query = new URLSearchParams();
69
+ for (const [k, v] of Object.entries(filters)) {
70
+ if (v !== undefined && v !== null && v !== "") query.set(k, String(v));
71
+ }
72
+ const qs = query.toString();
73
+ const path = qs ? `/voice/stats/voice-analytics?${qs}` : `/voice/stats/voice-analytics`;
74
+ return this.client(path, { method: "GET", ...options });
75
+ }
76
+ }
@@ -157,4 +157,41 @@ export class SipTrunks {
157
157
  async getPops({ options = {} } = {}) {
158
158
  return this.client(`/voice/sip-trunks/pops`, { method: "GET", ...options });
159
159
  }
160
+
161
+ /**
162
+ * Attach one or more phone numbers (by E.164) to a SIP trunk — routes each
163
+ * DID down the trunk. Idempotent; numbers already configured on a SIP profile
164
+ * are skipped and returned in `skipped` with a reason.
165
+ * @async
166
+ * @roles api, admin, developer
167
+ * @param {Object} params - Request parameters.
168
+ * @param {string} params.id - The SIP trunk UUID.
169
+ * @param {string[]} params.phoneNumbers - Phone numbers in E.164 (a leading "+" is optional).
170
+ * @param {import('../../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
171
+ * @throws {Error} If id or phoneNumbers is missing.
172
+ * @returns {Promise<Object>} `{ assigned: string[], skipped: { e164, reason }[] }`.
173
+ */
174
+ async assignNumbers({ id, phoneNumbers, options = {} }) {
175
+ this.client._require({ id, phoneNumbers });
176
+ const safeId = encodeURIComponent(id);
177
+ return this.client(`/voice/sip-trunks/${safeId}/assign-numbers`, { method: "POST", body: { phoneNumbers }, ...options });
178
+ }
179
+
180
+ /**
181
+ * Detach one or more phone numbers (by E.164) from a SIP trunk — removes each
182
+ * number's SIP_TRUNK inbound route when it points at this trunk.
183
+ * @async
184
+ * @roles api, admin, developer
185
+ * @param {Object} params - Request parameters.
186
+ * @param {string} params.id - The SIP trunk UUID.
187
+ * @param {string[]} params.phoneNumbers - Phone numbers in E.164 (a leading "+" is optional).
188
+ * @param {import('../../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
189
+ * @throws {Error} If id or phoneNumbers is missing.
190
+ * @returns {Promise<Object>} `{ unassigned: string[] }`.
191
+ */
192
+ async unassignNumbers({ id, phoneNumbers, options = {} }) {
193
+ this.client._require({ id, phoneNumbers });
194
+ const safeId = encodeURIComponent(id);
195
+ return this.client(`/voice/sip-trunks/${safeId}/unassign-numbers`, { method: "POST", body: { phoneNumbers }, ...options });
196
+ }
160
197
  }