@signalhousellc/sdk 1.0.56 → 1.0.62

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,9 @@
1
1
  import { SipTrunks } from "./voice/SipTrunks.js";
2
2
  import { SipProfiles } from "./voice/SipProfiles.js";
3
+ import { ProgrammableVoiceProfiles } from "./voice/ProgrammableVoiceProfiles.js";
3
4
  import { Calls } from "./voice/Calls.js";
5
+ import { CallLogs } from "./voice/CallLogs.js";
6
+ import { GlobalVoiceSettings } from "./voice/GlobalVoiceSettings.js";
4
7
  import { Tokens } from "./voice/Tokens.js";
5
8
 
6
9
  /**
@@ -9,10 +12,13 @@ import { Tokens } from "./voice/Tokens.js";
9
12
  * namespace, accessed via `sdk.voice.*`.
10
13
  *
11
14
  * Sub-resources:
12
- * - `sdk.voice.sipTrunks` — SIP trunk (peer-to-peer connections to PBX/carrier).
13
- * - `sdk.voice.sipProfiles` — SIP profile / endpoint (single registerable UA).
14
- * - `sdk.voice.calls` — Outbound call origination + call log queries.
15
- * - `sdk.voice.tokens` — Mint ephemeral SIP credentials for the browser voice SDK.
15
+ * - `sdk.voice.sipTrunks` — SIP trunk (peer-to-peer connections to PBX/carrier).
16
+ * - `sdk.voice.sipProfiles` — SIP profile / endpoint (single registerable UA).
17
+ * - `sdk.voice.programmableVoiceProfiles` — Programmable Voice Profile (route a set of numbers through Signal House).
18
+ * - `sdk.voice.calls` — Twilio-compat programmatic call control (create/hangup/etc.).
19
+ * - `sdk.voice.callLogs` — Account-scoped call history: list/get + presigned recording.
20
+ * - `sdk.voice.globalVoiceSettings` — Account-wide voice defaults (accepted regions, max spend, E911).
21
+ * - `sdk.voice.tokens` — Mint ephemeral SIP credentials for the browser voice SDK.
16
22
  */
17
23
  export class Voice {
18
24
  constructor(client, enableAdmin) {
@@ -20,7 +26,10 @@ export class Voice {
20
26
  this.enableAdmin = enableAdmin;
21
27
  this.sipTrunks = new SipTrunks(client, enableAdmin);
22
28
  this.sipProfiles = new SipProfiles(client, enableAdmin);
29
+ this.programmableVoiceProfiles = new ProgrammableVoiceProfiles(client, enableAdmin);
23
30
  this.calls = new Calls(client, enableAdmin);
31
+ this.callLogs = new CallLogs(client, enableAdmin);
32
+ this.globalVoiceSettings = new GlobalVoiceSettings(client, enableAdmin);
24
33
  this.tokens = new Tokens(client, enableAdmin);
25
34
  }
26
35
  }
@@ -0,0 +1,105 @@
1
+ /**
2
+ * @typedef {Object} ListCallLogsFilters
3
+ * @property {number} [page] - 1-indexed page (default 1).
4
+ * @property {number} [limit] - Page size (default 20, max 1000).
5
+ * @property {"INBOUND"|"OUTBOUND"|"INTERNAL"} [direction] - Filter by direction.
6
+ * @property {"QUEUED"|"RINGING"|"IN_PROGRESS"|"COMPLETED"|"FAILED"|"BUSY"|"NO_ANSWER"|"CANCELED"} [status] - Filter by status.
7
+ * @property {"SIP_TRUNK"|"PROGRAMMABLE_VOICE"|"AI_VOICE"|"WEBRTC"|"VOICEMAIL"|"CONFERENCE"|"PSTN"} [callSource] - Filter by how the call was handled.
8
+ * @property {string} [subgroupId] - Filter by owning subgroup.
9
+ * @property {string} [sipTrunkId] - Filter by SIP trunk id.
10
+ * @property {string} [programmableVoiceProfileId] - Filter by Programmable Voice Profile id.
11
+ * @property {string} [from] - Filter by caller number (contains).
12
+ * @property {string} [to] - Filter by called number (contains).
13
+ * @property {string} [q] - Free-text search over callId / from / to.
14
+ * @property {"positive"|"negative"|"neutral"} [sentiment] - Filter by sentiment.
15
+ * @property {boolean} [voicemail] - When true, return only voicemails (metadata.voicemail=true).
16
+ * @property {boolean} [hasRecording] - When true, only calls that have a recording (callRecordingUrl set).
17
+ * @property {boolean} [excludeVoicemail] - When true, exclude voicemails (used by the Call Recordings view).
18
+ * @property {string} [dateFrom] - ISO-8601 lower bound on start time.
19
+ * @property {string} [dateTo] - ISO-8601 upper bound on start time.
20
+ * @property {string} [sort] - Sort field (default startTime).
21
+ * @property {"asc"|"desc"} [order] - Sort order (default desc).
22
+ */
23
+
24
+ /**
25
+ * Call Logs — the account-scoped voice call history (voice-backend
26
+ * `/voice/api/v1/call-logs`). Distinct from `voice.calls`, which is the
27
+ * Twilio-compatible programmatic call-control surface; this is the richer log
28
+ * read surface with cost, recording, and voice-config attribution used by the
29
+ * portal Call Logs view. Accessed via `sdk.voice.callLogs`.
30
+ */
31
+ export class CallLogs {
32
+ constructor(client, enableAdmin) {
33
+ this.client = client;
34
+ this.enableAdmin = enableAdmin;
35
+ }
36
+
37
+ /**
38
+ * List call logs for the current account, paginated and filterable.
39
+ * @async
40
+ * @roles api, admin, developer, billing, user
41
+ * @param {Object} [params] - Request parameters.
42
+ * @param {ListCallLogsFilters} [params.filters] - Optional filters.
43
+ * @param {import('../../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
44
+ * @returns {Promise<Object>} `{ success, data: [...call logs], meta: { total, page, limit, totalPages } }`.
45
+ */
46
+ async list({ filters = {}, options = {} } = {}) {
47
+ const query = new URLSearchParams();
48
+ for (const [k, v] of Object.entries(filters)) {
49
+ if (v !== undefined && v !== null && v !== "") query.set(k, String(v));
50
+ }
51
+ const qs = query.toString();
52
+ const path = qs ? `/voice/api/v1/call-logs?${qs}` : `/voice/api/v1/call-logs`;
53
+ return this.client(path, { method: "GET", ...options });
54
+ }
55
+
56
+ /**
57
+ * Get a single call log by its UUID or callId.
58
+ * @async
59
+ * @roles api, admin, developer, billing, user
60
+ * @param {Object} params - Request parameters.
61
+ * @param {string} params.id - The call log UUID or callId.
62
+ * @param {import('../../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
63
+ * @throws {Error} If id is missing.
64
+ * @returns {Promise<Object>} `{ success, data: { ...call log } }`.
65
+ */
66
+ async get({ id, options = {} }) {
67
+ this.client._require({ id });
68
+ const safeId = encodeURIComponent(id);
69
+ return this.client(`/voice/api/v1/call-logs/${safeId}`, { method: "GET", ...options });
70
+ }
71
+
72
+ /**
73
+ * Get a short-TTL presigned playback URL for a call's recording. Account-scoped
74
+ * — only the owning account can presign. 404 if the call has no recording.
75
+ * @async
76
+ * @roles api, admin, developer, billing, user
77
+ * @param {Object} params - Request parameters.
78
+ * @param {string} params.id - The call log UUID or callId.
79
+ * @param {import('../../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
80
+ * @throws {Error} If id is missing.
81
+ * @returns {Promise<Object>} `{ success, data: { callId, url, expiresIn } }`.
82
+ */
83
+ async getRecording({ id, options = {} }) {
84
+ this.client._require({ id });
85
+ const safeId = encodeURIComponent(id);
86
+ return this.client(`/voice/api/v1/call-logs/${safeId}/recording`, { method: "GET", ...options });
87
+ }
88
+
89
+ /**
90
+ * Mark a voicemail (a call log with a recording) read or unread. Account-scoped.
91
+ * @async
92
+ * @roles api, admin, developer
93
+ * @param {Object} params - Request parameters.
94
+ * @param {string} params.id - The call log UUID or callId.
95
+ * @param {boolean} [params.read=true] - true = read, false = unread.
96
+ * @param {import('../../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
97
+ * @throws {Error} If id is missing.
98
+ * @returns {Promise<Object>} `{ success, data: { id, voicemailReadAt } }`.
99
+ */
100
+ async markVoicemailRead({ id, read = true, options = {} }) {
101
+ this.client._require({ id });
102
+ const safeId = encodeURIComponent(id);
103
+ return this.client(`/voice/api/v1/call-logs/${safeId}/voicemail-read`, { method: "PATCH", body: { read }, ...options });
104
+ }
105
+ }
@@ -0,0 +1,48 @@
1
+ /**
2
+ * @typedef {Object} GlobalVoiceSettingsData
3
+ * @property {string[]} [acceptedRegions] - Accepted regions as country calling codes; empty = all allowed.
4
+ * @property {number|null} [maxSpendPerMinute] - Baseline max spend per minute (dollars); null = no limit.
5
+ * @property {boolean} [e911Enabled] - Whether numbers may dial 911.
6
+ */
7
+
8
+ /**
9
+ * Global Voice Settings — account-wide voice defaults (accepted regions, max
10
+ * spend per minute, E911). SIP trunks and Programmable Voice Profiles override
11
+ * these. Calls the voice-backend service mounted under /voice. Accessed via
12
+ * `sdk.voice.globalVoiceSettings`.
13
+ */
14
+ export class GlobalVoiceSettings {
15
+ constructor(client, enableAdmin) {
16
+ this.client = client;
17
+ this.enableAdmin = enableAdmin;
18
+ }
19
+
20
+ /**
21
+ * Get the current account's global voice settings. Returns `data: null` if the
22
+ * account has never configured them (defaults apply).
23
+ * @async
24
+ * @roles api, admin, developer, billing, user
25
+ * @param {Object} [params] - Request parameters.
26
+ * @param {import('../../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
27
+ * @returns {Promise<Object>} `{ success, data: { accountId, acceptedRegions, maxSpendPerMinute, e911Enabled, ... } | null }`.
28
+ */
29
+ async get({ options = {} } = {}) {
30
+ return this.client(`/voice/api/v1/global-voice-settings`, { method: "GET", ...options });
31
+ }
32
+
33
+ /**
34
+ * Upsert the account's global voice settings. Partial — only the fields you
35
+ * provide are written; omitted fields are preserved.
36
+ * @async
37
+ * @roles api, admin, developer
38
+ * @param {Object} params - Request parameters.
39
+ * @param {GlobalVoiceSettingsData} params.settingsData - Fields to set.
40
+ * @param {import('../../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
41
+ * @throws {Error} If settingsData is missing.
42
+ * @returns {Promise<Object>} `{ success, data: { ...settings } }`.
43
+ */
44
+ async update({ settingsData, options = {} }) {
45
+ this.client._require({ settingsData });
46
+ return this.client(`/voice/api/v1/global-voice-settings`, { method: "PUT", body: settingsData, ...options });
47
+ }
48
+ }
@@ -0,0 +1,181 @@
1
+ /**
2
+ * @typedef {Object} CreateProgrammableVoiceProfileData
3
+ * @property {string} name - Profile name (required).
4
+ * @property {string[]} subgroupIds - Subgroups this profile spans (required, at least one).
5
+ * @property {string} [region] - Region/POP label.
6
+ * @property {"FORWARD"|"WEBRTC"|"SIP_TRUNK"|"SIP_PROFILE"} [routeAction] - Inbound call action (default "FORWARD"). Deliver the call to a PSTN number (FORWARD), ring the profile's subgroup registered softphones (WEBRTC), send to a SIP trunk (SIP_TRUNK), or ring a registered SIP endpoint (SIP_PROFILE).
7
+ * @property {string} [forwardToE164] - Destination number, required when routeAction is "FORWARD".
8
+ * @property {number} [forwardAfterSeconds] - Ring seconds before the action fires.
9
+ * @property {string} [routeSipTrunkId] - SIP trunk id, required when routeAction is "SIP_TRUNK".
10
+ * @property {string} [routeSipProfileId] - SIP endpoint id, required when routeAction is "SIP_PROFILE".
11
+ * @property {boolean} [recordingEnabled] - Record calls on this profile.
12
+ * @property {boolean} [enabled] - Active state (default true).
13
+ */
14
+
15
+ /**
16
+ * @typedef {Object} UpdateProgrammableVoiceProfileData
17
+ * @property {string} [name] - Profile name.
18
+ * @property {string[]} [subgroupIds] - Subgroups this profile spans.
19
+ * @property {string|null} [region] - Region/POP label.
20
+ * @property {"FORWARD"|"WEBRTC"|"SIP_TRUNK"|"SIP_PROFILE"} [routeAction] - Inbound call action (FORWARD | WEBRTC | SIP_TRUNK | SIP_PROFILE).
21
+ * @property {string|null} [forwardToE164] - FORWARD destination.
22
+ * @property {number|null} [forwardAfterSeconds] - Ring seconds before the action fires.
23
+ * @property {string|null} [routeSipTrunkId] - SIP trunk id (required when routeAction is "SIP_TRUNK").
24
+ * @property {string|null} [routeSipProfileId] - SIP endpoint id (required when routeAction is "SIP_PROFILE").
25
+ * @property {boolean} [recordingEnabled] - Record calls on this profile.
26
+ * @property {boolean} [enabled] - Active state.
27
+ */
28
+
29
+ /**
30
+ * Programmable Voice Profile management. A Programmable Voice Profile groups a
31
+ * set of the account's numbers (across one or more subgroups) under a single
32
+ * inbound call-handling decision routed through Signal House's own voice servers
33
+ * — the same idea as a SIP trunk, but without a customer SBC. A number can
34
+ * belong to at most one profile and is mutually exclusive with SIP trunks.
35
+ *
36
+ * Calls the voice-backend service mounted under /voice. Accessed via
37
+ * `sdk.voice.programmableVoiceProfiles`.
38
+ */
39
+ export class ProgrammableVoiceProfiles {
40
+ constructor(client, enableAdmin) {
41
+ this.client = client;
42
+ this.enableAdmin = enableAdmin;
43
+ }
44
+
45
+ /**
46
+ * List all Programmable Voice Profiles for the current account.
47
+ * @async
48
+ * @roles api, admin, developer, billing, user
49
+ * @param {Object} [params] - Request parameters.
50
+ * @param {import('../../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
51
+ * @returns {Promise<Object>} `{ profiles: [...] }`.
52
+ */
53
+ async list({ options = {} } = {}) {
54
+ return this.client(`/voice/api/v1/programmable-voice-profiles`, { method: "GET", ...options });
55
+ }
56
+
57
+ /**
58
+ * Get a single Programmable Voice Profile by ID.
59
+ * @async
60
+ * @roles api, admin, developer, billing, user
61
+ * @param {Object} params - Request parameters.
62
+ * @param {string} params.id - The profile UUID.
63
+ * @param {import('../../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
64
+ * @throws {Error} If id is missing.
65
+ * @returns {Promise<Object>} `{ profile: {...} }`.
66
+ */
67
+ async get({ id, options = {} }) {
68
+ this.client._require({ id });
69
+ const safeId = encodeURIComponent(id);
70
+ return this.client(`/voice/api/v1/programmable-voice-profiles/${safeId}`, { method: "GET", ...options });
71
+ }
72
+
73
+ /**
74
+ * Create a Programmable Voice Profile.
75
+ * @async
76
+ * @roles api, admin, developer
77
+ * @param {Object} params - Request parameters.
78
+ * @param {CreateProgrammableVoiceProfileData} params.profileData - The profile to create.
79
+ * @param {import('../../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
80
+ * @throws {Error} If profileData is missing.
81
+ * @returns {Promise<Object>} `{ profile: {...} }`.
82
+ */
83
+ async create({ profileData, options = {} }) {
84
+ this.client._require({ profileData });
85
+ return this.client(`/voice/api/v1/programmable-voice-profiles`, { method: "POST", body: profileData, ...options });
86
+ }
87
+
88
+ /**
89
+ * Update an existing Programmable Voice Profile (partial).
90
+ * @async
91
+ * @roles api, admin, developer
92
+ * @param {Object} params - Request parameters.
93
+ * @param {string} params.id - The profile UUID.
94
+ * @param {UpdateProgrammableVoiceProfileData} params.updateData - Fields to update.
95
+ * @param {import('../../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
96
+ * @throws {Error} If id or updateData is missing.
97
+ * @returns {Promise<Object>} `{ profile: {...} }`.
98
+ */
99
+ async update({ id, updateData, options = {} }) {
100
+ this.client._require({ id, updateData });
101
+ const safeId = encodeURIComponent(id);
102
+ return this.client(`/voice/api/v1/programmable-voice-profiles/${safeId}`, { method: "PATCH", body: updateData, ...options });
103
+ }
104
+
105
+ /**
106
+ * Toggle a profile active/inactive.
107
+ * @async
108
+ * @roles api, admin, developer
109
+ * @param {Object} params - Request parameters.
110
+ * @param {string} params.id - The profile UUID.
111
+ * @param {import('../../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
112
+ * @throws {Error} If id is missing.
113
+ * @returns {Promise<Object>} `{ profile: {...} }`.
114
+ */
115
+ async toggleActive({ id, options = {} }) {
116
+ this.client._require({ id });
117
+ const safeId = encodeURIComponent(id);
118
+ return this.client(`/voice/api/v1/programmable-voice-profiles/${safeId}/toggle-active`, { method: "POST", ...options });
119
+ }
120
+
121
+ /**
122
+ * Delete a Programmable Voice Profile. Its number assignments cascade away,
123
+ * so those numbers fall back to subgroup/global routing.
124
+ * @async
125
+ * @roles api, admin, developer
126
+ * @param {Object} params - Request parameters.
127
+ * @param {string} params.id - The profile UUID.
128
+ * @param {import('../../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
129
+ * @throws {Error} If id is missing.
130
+ * @returns {Promise<Object>} `{ message: string }`.
131
+ */
132
+ async delete({ id, options = {} }) {
133
+ this.client._require({ id });
134
+ const safeId = encodeURIComponent(id);
135
+ return this.client(`/voice/api/v1/programmable-voice-profiles/${safeId}`, { method: "DELETE", ...options });
136
+ }
137
+
138
+ /**
139
+ * Assign a phone number (by E.164) to this profile. Rejected if the number is
140
+ * already configured on a SIP trunk/endpoint or another profile — it must be
141
+ * de-configured there first (mutual exclusivity).
142
+ * @async
143
+ * @roles api, admin, developer
144
+ * @param {Object} params - Request parameters.
145
+ * @param {string} params.id - The profile UUID.
146
+ * @param {string} params.e164 - The phone number in E.164 (a leading "+" is optional).
147
+ * @param {import('../../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
148
+ * @throws {Error} If id or e164 is missing.
149
+ * @returns {Promise<Object>} `{ profile: {...} }`.
150
+ */
151
+ async assignNumber({ id, e164, options = {} }) {
152
+ this.client._require({ id, e164 });
153
+ const safeId = encodeURIComponent(id);
154
+ return this.client(`/voice/api/v1/programmable-voice-profiles/${safeId}/assign-number`, {
155
+ method: "POST",
156
+ body: { e164 },
157
+ ...options,
158
+ });
159
+ }
160
+
161
+ /**
162
+ * Unassign a phone number (by E.164) from this profile.
163
+ * @async
164
+ * @roles api, admin, developer
165
+ * @param {Object} params - Request parameters.
166
+ * @param {string} params.id - The profile UUID.
167
+ * @param {string} params.e164 - The phone number in E.164 (a leading "+" is optional).
168
+ * @param {import('../../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
169
+ * @throws {Error} If id or e164 is missing.
170
+ * @returns {Promise<Object>} `{ profile: {...} }`.
171
+ */
172
+ async unassignNumber({ id, e164, options = {} }) {
173
+ this.client._require({ id, e164 });
174
+ const safeId = encodeURIComponent(id);
175
+ return this.client(`/voice/api/v1/programmable-voice-profiles/${safeId}/unassign-number`, {
176
+ method: "POST",
177
+ body: { e164 },
178
+ ...options,
179
+ });
180
+ }
181
+ }
@@ -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
  }