@signalhousellc/sdk 1.0.52 → 1.0.54
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/package.json +11 -2
- package/src/SignalHouseSDK.js +5 -0
- package/src/domains/Auth.js +46 -0
- package/src/domains/Brands.js +23 -0
- package/src/domains/Campaigns.js +3 -3
- package/src/domains/Groups.js +24 -0
- package/src/domains/Numbers.js +23 -2
- package/src/domains/Voice.js +26 -0
- package/src/domains/voice/Calls.js +112 -0
- package/src/domains/voice/SipProfiles.js +191 -0
- package/src/domains/voice/SipTrunks.js +160 -0
- package/src/domains/voice/Tokens.js +64 -0
- package/src/domains/voice/browser/Call.js +364 -0
- package/src/domains/voice/browser/Device.js +226 -0
- package/src/domains/voice/browser/index.js +17 -0
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@signalhousellc/sdk",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.54",
|
|
4
4
|
"description": "Signal House SDK for use with the Signal House platform",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/SignalHouseSDK.js",
|
|
7
7
|
"exports": {
|
|
8
|
-
".": "./src/SignalHouseSDK.js"
|
|
8
|
+
".": "./src/SignalHouseSDK.js",
|
|
9
|
+
"./voice-browser": "./src/domains/voice/browser/index.js"
|
|
9
10
|
},
|
|
10
11
|
"files": [
|
|
11
12
|
"src/",
|
|
@@ -15,5 +16,13 @@
|
|
|
15
16
|
"license": "ISC",
|
|
16
17
|
"dependencies": {
|
|
17
18
|
"axios": "^1.13.5"
|
|
19
|
+
},
|
|
20
|
+
"peerDependencies": {
|
|
21
|
+
"jssip": "^3.13.0"
|
|
22
|
+
},
|
|
23
|
+
"peerDependenciesMeta": {
|
|
24
|
+
"jssip": {
|
|
25
|
+
"optional": true
|
|
26
|
+
}
|
|
18
27
|
}
|
|
19
28
|
}
|
package/src/SignalHouseSDK.js
CHANGED
|
@@ -22,6 +22,7 @@ import { Subscriptions } from "./domains/Subscriptions.js";
|
|
|
22
22
|
import { Users } from "./domains/Users.js";
|
|
23
23
|
import { Notifications } from "./domains/Notifications.js";
|
|
24
24
|
import { Webhooks } from "./domains/Webhooks.js";
|
|
25
|
+
import { Voice } from "./domains/Voice.js";
|
|
25
26
|
|
|
26
27
|
export class SignalHouseSDK {
|
|
27
28
|
/**
|
|
@@ -29,6 +30,7 @@ export class SignalHouseSDK {
|
|
|
29
30
|
* @param {Object} config - The configuration object for initializing the SDK
|
|
30
31
|
* @param {string} config.apiKey - The API key for authenticating requests to the SignalHouse API
|
|
31
32
|
* @param {string} config.baseUrl - The base URL for the SignalHouse API (e.g., "https://api.signalhouse.com")
|
|
33
|
+
* @param {boolean} [config.enableAdmin=false] - Enable admin-scoped behaviors on domains that support them.
|
|
32
34
|
* @throws {Error} Throws an error if the API key or base URL is missing from the configuration
|
|
33
35
|
* @returns {SignalHouseSDK} An instance of the SignalHouseSDK
|
|
34
36
|
*/
|
|
@@ -66,6 +68,9 @@ export class SignalHouseSDK {
|
|
|
66
68
|
this.users = new Users(client, this.enableAdmin);
|
|
67
69
|
this.notifications = new Notifications(client, this.enableAdmin);
|
|
68
70
|
this.webhooks = new Webhooks(client, this.enableAdmin);
|
|
71
|
+
// Voice domain targets the voice-backend service under /voice. Available
|
|
72
|
+
// like any other domain; gating (if any) will be decided later.
|
|
73
|
+
this.voice = new Voice(client, this.enableAdmin);
|
|
69
74
|
}
|
|
70
75
|
|
|
71
76
|
/**
|
package/src/domains/Auth.js
CHANGED
|
@@ -58,6 +58,37 @@ export class Auth {
|
|
|
58
58
|
return this.client(`/auth/verify-email`, { method: "POST", body: { token }, ...options });
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
+
/**
|
|
62
|
+
* Request a password-reset link be emailed to the given address (public). Always resolves
|
|
63
|
+
* successfully regardless of whether an account exists for the email, so it cannot be used to
|
|
64
|
+
* enumerate registered emails.
|
|
65
|
+
* @async
|
|
66
|
+
* @roles public
|
|
67
|
+
* @param {Object} params
|
|
68
|
+
* @param {string} params.email - The email address to send a reset link to
|
|
69
|
+
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
|
|
70
|
+
* @returns {Promise<Object>} The response from the server ({ success: true })
|
|
71
|
+
*/
|
|
72
|
+
async forgotPassword({ email, options = {} }) {
|
|
73
|
+
this.client._require({ email });
|
|
74
|
+
return this.client(`/auth/forgot-password`, { method: "POST", body: { email }, ...options });
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Reset a password using the single-use token from a password-reset email link (public)
|
|
79
|
+
* @async
|
|
80
|
+
* @roles public
|
|
81
|
+
* @param {Object} params
|
|
82
|
+
* @param {string} params.token - The single-use reset token from the email link
|
|
83
|
+
* @param {string} params.password - The new password to set (min 8 characters)
|
|
84
|
+
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
|
|
85
|
+
* @returns {Promise<Object>} The response from the server ({ success: true })
|
|
86
|
+
*/
|
|
87
|
+
async resetPasswordWithToken({ token, password, options = {} }) {
|
|
88
|
+
this.client._require({ token, password });
|
|
89
|
+
return this.client(`/auth/reset-password`, { method: "POST", body: { token, password }, ...options });
|
|
90
|
+
}
|
|
91
|
+
|
|
61
92
|
/**
|
|
62
93
|
* Resend the account verification email to the authenticated caller
|
|
63
94
|
* @async
|
|
@@ -115,4 +146,19 @@ export class Auth {
|
|
|
115
146
|
async logoutAll({ options = {} } = {}) {
|
|
116
147
|
return this.client(`/auth/logout-all`, { method: "POST", ...options });
|
|
117
148
|
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Mint a single-use, short-lived external-link token for the authenticated caller. The token is
|
|
152
|
+
* handed to the GHL/Shopify backend so it can link the caller's existing V2 group to its tenant.
|
|
153
|
+
* @async
|
|
154
|
+
* @roles admin, developer, billing, user
|
|
155
|
+
* @param {Object} params
|
|
156
|
+
* @param {string} params.product - The external system to link to ("ghl" or "shopify")
|
|
157
|
+
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
|
|
158
|
+
* @returns {Promise<Object>} The response from the server ({ token })
|
|
159
|
+
*/
|
|
160
|
+
async requestExternalLinkToken({ product, options = {} }) {
|
|
161
|
+
this.client._require({ product });
|
|
162
|
+
return this.client(`/auth/external-link-token`, { method: "POST", body: { product }, ...options });
|
|
163
|
+
}
|
|
118
164
|
}
|
package/src/domains/Brands.js
CHANGED
|
@@ -198,6 +198,29 @@ export class Brands {
|
|
|
198
198
|
return this.client(`/brand/externalvetting/${safeBrandId}`, { method: "POST", ...options });
|
|
199
199
|
}
|
|
200
200
|
|
|
201
|
+
/**
|
|
202
|
+
* Import an existing external vetting record for a brand
|
|
203
|
+
*
|
|
204
|
+
* Unlike createExternalVetting (which orders a new, billable vetting), this attaches a vetting the
|
|
205
|
+
* brand already completed directly with the provider, using the provider-issued vettingId and
|
|
206
|
+
* vettingToken. It is synchronous and not billable.
|
|
207
|
+
* @async
|
|
208
|
+
* @roles api, admin, developer, billing, user
|
|
209
|
+
* @param {Object} params - The parameters for importing external vetting
|
|
210
|
+
* @param {string} params.brandId - The ID of the brand to import external vetting for
|
|
211
|
+
* @param {string} params.vettingProviderId - The external vetting provider (AEGIS, WMC, CV)
|
|
212
|
+
* @param {string} params.vettingId - The provider-issued vetting / transaction ID to import
|
|
213
|
+
* @param {string} [params.vettingToken] - The provider-issued vetting token (required by some providers, e.g. AEGIS)
|
|
214
|
+
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
|
|
215
|
+
* @throws {Error} Throws an error if brandId, vettingProviderId, or vettingId is missing
|
|
216
|
+
* @returns {Promise<Object>} The response from the server
|
|
217
|
+
*/
|
|
218
|
+
async importExternalVetting({ brandId, vettingProviderId, vettingId, vettingToken, options = {} }) {
|
|
219
|
+
this.client._require({ brandId, vettingProviderId, vettingId });
|
|
220
|
+
const safeBrandId = encodeURIComponent(brandId);
|
|
221
|
+
return this.client(`/brand/externalvetting/import/${safeBrandId}`, { method: "POST", body: { vettingProviderId, vettingId, vettingToken }, ...options });
|
|
222
|
+
}
|
|
223
|
+
|
|
201
224
|
/**
|
|
202
225
|
* Update a brand's information
|
|
203
226
|
* @async
|
package/src/domains/Campaigns.js
CHANGED
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
* @property {string} [privacyPolicyLink] - A URL linking to the privacy policy for the campaign (optional, must be at most 2048 characters if provided)
|
|
65
65
|
* @property {string} [termsAndConditionsLink] - A URL linking to the terms and conditions for the campaign (optional, must be at most 2048 characters if provided)
|
|
66
66
|
* @property {string} [embeddedLinkSample] - A sample of the embedded link used in the campaign (optional, must be at most 255 characters if provided)
|
|
67
|
-
* @property {Object} [tollFree] - Toll-Free editable fields, used when updating a Toll-Free campaign. Mirrors the CreateTollFreeCampaignData `tollFree` object with every field optional (useCase, messageVolume, programSummary (≤500), exampleMessage, customerCareEmail, optInImageURLs, optIns,
|
|
67
|
+
* @property {Object} [tollFree] - Toll-Free editable fields, used when updating a Toll-Free campaign. Mirrors the CreateTollFreeCampaignData `tollFree` object with every field optional (useCase, messageVolume, programSummary (≤500), exampleMessage, customerCareEmail, optInImageURLs, optIns, multiNumberReason (≤500)). Phone numbers cannot be changed via update — Toll-Free numbers are locked to their campaign.
|
|
68
68
|
*/
|
|
69
69
|
|
|
70
70
|
/**
|
|
@@ -87,7 +87,7 @@
|
|
|
87
87
|
* @property {TollFreeOptIn} [optIns.web] - Online (web) opt-in details
|
|
88
88
|
* @property {TollFreeOptIn} [optIns.keyword] - Keyword opt-in details
|
|
89
89
|
* @property {TollFreeOptIn} [optIns.interactiveVoiceResponse] - IVR opt-in details
|
|
90
|
-
* @property {string} [
|
|
90
|
+
* @property {string} [multiNumberReason] - Internally-stored reason the customer requested more than one Toll-Free number on the campaign (optional, at most 500 characters). Required when more than one phone number is assigned; captured for Signal House review only and never sent to the carrier.
|
|
91
91
|
*/
|
|
92
92
|
|
|
93
93
|
/**
|
|
@@ -196,7 +196,7 @@ export class Campaigns {
|
|
|
196
196
|
/**
|
|
197
197
|
* Create a new Toll-Free (TFN) campaign and submit it for Signal House review
|
|
198
198
|
* @async
|
|
199
|
-
* @roles api, admin, developer,
|
|
199
|
+
* @roles api, admin, developer, user
|
|
200
200
|
* @param {Object} params - The parameters for creating the toll-free campaign
|
|
201
201
|
* @param {CreateTollFreeCampaignData} params.campaignData - The data for the toll-free campaign to be created (see CreateTollFreeCampaignData typedef for details)
|
|
202
202
|
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
|
package/src/domains/Groups.js
CHANGED
|
@@ -52,6 +52,30 @@ export class Groups {
|
|
|
52
52
|
const safeGroupId = encodeURIComponent(groupId);
|
|
53
53
|
return this.client(`/group/${safeGroupId}`, { method: "DELETE", ...options });
|
|
54
54
|
},
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Link an external tenant (GHL/Shopify) to a V2 group (server-to-server). Exchanges a
|
|
58
|
+
* single-use link token for a canonical group, adopting an empty portal group, repointing
|
|
59
|
+
* to an existing group, or flagging for manual review.
|
|
60
|
+
* @async
|
|
61
|
+
* @roles signalhouse
|
|
62
|
+
* @param {Object} params - The parameters for linking an external account
|
|
63
|
+
* @param {string} params.linkToken - The single-use external-link token minted by the portal user
|
|
64
|
+
* @param {string} params.externalSystem - The external system ("ghl" or "shopify")
|
|
65
|
+
* @param {string} params.externalId - The external tenant identifier
|
|
66
|
+
* @param {string} [params.existingGroupId] - An existing V2 group ID to repoint to, if any
|
|
67
|
+
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
|
|
68
|
+
* @throws {Error} Throws an error if linkToken, externalSystem, or externalId is missing
|
|
69
|
+
* @returns {Promise<Object>} - The link outcome ({ status, canonicalGroupId, ... })
|
|
70
|
+
*/
|
|
71
|
+
linkExternal: async ({ linkToken, externalSystem, externalId, existingGroupId, options = {} }) => {
|
|
72
|
+
this.client._require({ linkToken, externalSystem, externalId });
|
|
73
|
+
return this.client(`/group/link-external`, {
|
|
74
|
+
method: "POST",
|
|
75
|
+
body: { linkToken, externalSystem, externalId, ...(existingGroupId ? { existingGroupId } : {}) },
|
|
76
|
+
...options,
|
|
77
|
+
});
|
|
78
|
+
},
|
|
55
79
|
};
|
|
56
80
|
}
|
|
57
81
|
}
|
package/src/domains/Numbers.js
CHANGED
|
@@ -115,7 +115,8 @@ export class Numbers {
|
|
|
115
115
|
* Purchase one or more Toll-Free numbers via the asynchronous resource-request flow.
|
|
116
116
|
*
|
|
117
117
|
* Toll-Free numbers are ordered by quantity (not picked individually) and provisioned asynchronously;
|
|
118
|
-
* per-number completion is delivered via webhook/polling, not in this response.
|
|
118
|
+
* per-number completion is delivered via webhook/polling, not in this response. The returned `orderId`
|
|
119
|
+
* can be polled with {@link Numbers#getTollFreeOrderStatus} for the order's outcome.
|
|
119
120
|
* @async
|
|
120
121
|
* @roles api, admin, developer, billing, user
|
|
121
122
|
* @param {Object} params - The parameters for purchasing toll-free numbers
|
|
@@ -123,13 +124,33 @@ export class Numbers {
|
|
|
123
124
|
* @param {string} params.subgroupId - The subgroup the purchased numbers are assigned to
|
|
124
125
|
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
|
|
125
126
|
* @throws {Error} Throws an error if the quantity or subgroupId parameter is missing
|
|
126
|
-
* @returns {Promise<Object>} A promise that resolves to `{ message }` once the request is queued.
|
|
127
|
+
* @returns {Promise<Object>} A promise that resolves to `{ message, orderId }` once the request is queued.
|
|
127
128
|
*/
|
|
128
129
|
async purchaseTollFreeNumbers({ quantity, subgroupId, options = {} }) {
|
|
129
130
|
this.client._require({ quantity, subgroupId });
|
|
130
131
|
return this.client(`/number/toll-free`, { method: "POST", body: { quantity, subgroupId }, ...options });
|
|
131
132
|
}
|
|
132
133
|
|
|
134
|
+
/**
|
|
135
|
+
* Read the outcome of a Toll-Free number purchase by the `orderId` returned from
|
|
136
|
+
* {@link Numbers#purchaseTollFreeNumbers}. Reports per-number status as ready / provisioning / failed
|
|
137
|
+
* counts (plus failure reasons) so a client can poll until the order reaches a terminal state, and
|
|
138
|
+
* returns the provisioned phone numbers for the order so a client can act on exactly those numbers.
|
|
139
|
+
* `numbers` is empty until each number is provisioned (it fills in as the order completes).
|
|
140
|
+
* @async
|
|
141
|
+
* @roles api, admin, developer, billing, user
|
|
142
|
+
* @param {Object} params - The parameters for reading the order status
|
|
143
|
+
* @param {string} params.orderId - The order id returned by `purchaseTollFreeNumbers`
|
|
144
|
+
* @param {import('../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request
|
|
145
|
+
* @throws {Error} Throws an error if the orderId parameter is missing
|
|
146
|
+
* @returns {Promise<Object>} A promise that resolves to `{ orderId, counts: { ready, provisioning, failed }, failures: [{ reason }], numbers: string[] }`.
|
|
147
|
+
*/
|
|
148
|
+
async getTollFreeOrderStatus({ orderId, options = {} }) {
|
|
149
|
+
this.client._require({ orderId });
|
|
150
|
+
const safeOrderId = encodeURIComponent(orderId);
|
|
151
|
+
return this.client(`/number/toll-free/order/${safeOrderId}`, { method: "GET", ...options });
|
|
152
|
+
}
|
|
153
|
+
|
|
133
154
|
/**
|
|
134
155
|
* Update an existing phone number's details (e.g., setting a friendly name)
|
|
135
156
|
* @async
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { SipTrunks } from "./voice/SipTrunks.js";
|
|
2
|
+
import { SipProfiles } from "./voice/SipProfiles.js";
|
|
3
|
+
import { Calls } from "./voice/Calls.js";
|
|
4
|
+
import { Tokens } from "./voice/Tokens.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Voice domain — wraps the voice-backend service (mounted under /voice on the
|
|
8
|
+
* platform host). Groups all voice-service sub-resources under a single
|
|
9
|
+
* namespace, accessed via `sdk.voice.*`.
|
|
10
|
+
*
|
|
11
|
+
* 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.
|
|
16
|
+
*/
|
|
17
|
+
export class Voice {
|
|
18
|
+
constructor(client, enableAdmin) {
|
|
19
|
+
this.client = client;
|
|
20
|
+
this.enableAdmin = enableAdmin;
|
|
21
|
+
this.sipTrunks = new SipTrunks(client, enableAdmin);
|
|
22
|
+
this.sipProfiles = new SipProfiles(client, enableAdmin);
|
|
23
|
+
this.calls = new Calls(client, enableAdmin);
|
|
24
|
+
this.tokens = new Tokens(client, enableAdmin);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {Object} CreateCallData
|
|
3
|
+
* @property {string} to - Destination phone number in E.164 format (e.g. "+15551234567") or SIP URI.
|
|
4
|
+
* @property {string} from - Caller ID to present on the outbound leg. Must be an account-owned phone number when not using a SIP trunk.
|
|
5
|
+
* @property {string} [sip_trunk_id] - Route via a configured SIP trunk. Mutually exclusive with `sip_profile_id` and `to_identity` for the trunk path.
|
|
6
|
+
* @property {string} [sip_profile_id] - Two-leg-with-bridge: ring this persistent SIP profile first, then dial `to` and bridge. Mutually exclusive with `to_identity`.
|
|
7
|
+
* @property {string} [to_identity] - Two-leg-with-bridge: ring the SDK-registered identity by logical name (the value passed to `tokens.create({identity})`), then dial `to` and bridge. Mutually exclusive with `sip_profile_id`.
|
|
8
|
+
* @property {string} [answer_url] - Webhook URL fetched on call answer; returns call-control instructions.
|
|
9
|
+
* @property {"GET"|"POST"} [answer_method] - HTTP method for `answer_url`. Defaults to POST.
|
|
10
|
+
* @property {string} [status_callback] - Webhook URL for call status updates (QUEUED, RINGING, ANSWERED, COMPLETED, FAILED).
|
|
11
|
+
* @property {"GET"|"POST"} [status_callback_method] - HTTP method for `status_callback`. Defaults to POST.
|
|
12
|
+
* @property {boolean} [recording_enabled] - Record both legs of the call. Defaults to false.
|
|
13
|
+
* @property {boolean} [transcription_enabled] - Transcribe the recording. Defaults to false.
|
|
14
|
+
* @property {string} [ivr_flow_id] - Route the call into an AI IVR flow on answer instead of webhook control.
|
|
15
|
+
* @property {Object} [metadata] - Free-form metadata persisted on the call log.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @typedef {Object} ListCallsFilters
|
|
20
|
+
* @property {number} [page] - Page number (1-indexed). Defaults to 1.
|
|
21
|
+
* @property {number} [limit] - Page size (1-100). Defaults to 20.
|
|
22
|
+
* @property {"QUEUED"|"RINGING"|"IN_PROGRESS"|"COMPLETED"|"FAILED"|"BUSY"|"NO_ANSWER"|"CANCELED"} [status] - Filter by call status.
|
|
23
|
+
* @property {"INBOUND"|"OUTBOUND"} [direction] - Filter by call direction.
|
|
24
|
+
* @property {string} [from] - Filter by caller number.
|
|
25
|
+
* @property {string} [to] - Filter by destination number.
|
|
26
|
+
* @property {string} [date_from] - ISO-8601 lower bound on start_time.
|
|
27
|
+
* @property {string} [date_to] - ISO-8601 upper bound on start_time.
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Voice calls. REST API for placing outbound calls and inspecting call logs.
|
|
32
|
+
* Wraps voice-backend's `/voice/v1/calls` surface. Accessed via `sdk.voice.calls`.
|
|
33
|
+
*
|
|
34
|
+
* Origination modes:
|
|
35
|
+
* - **Single-leg** (no trunk/profile/identity): Twilio-style direct outbound — dial `to` from caller-ID `from`. Customer's `from` must be an account-owned number.
|
|
36
|
+
* - **SIP trunk** (`sip_trunk_id`): Route via a configured trunk; the trunk's auth/ACL governs caller-ID rules.
|
|
37
|
+
* - **Two-leg-with-bridge** (`sip_profile_id` OR `to_identity`): Ring the SDK-registered endpoint first, then dial `to` and bridge. `to_identity` resolves to the most recently-minted unexpired ephemeral identity for that name.
|
|
38
|
+
*/
|
|
39
|
+
export class Calls {
|
|
40
|
+
constructor(client, enableAdmin) {
|
|
41
|
+
this.client = client;
|
|
42
|
+
this.enableAdmin = enableAdmin;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Create an outbound call.
|
|
47
|
+
* @async
|
|
48
|
+
* @roles api, admin, developer, billing, user
|
|
49
|
+
* @param {Object} params - Request parameters.
|
|
50
|
+
* @param {CreateCallData} params.callData - The call to place.
|
|
51
|
+
* @param {import('../../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
|
|
52
|
+
* @throws {Error} If callData is missing.
|
|
53
|
+
* @returns {Promise<Object>} The created call: `{ call_id, status, direction, from, to, created_at }`.
|
|
54
|
+
*/
|
|
55
|
+
async create({ callData, options = {} }) {
|
|
56
|
+
this.client._require({ callData });
|
|
57
|
+
return this.client(`/voice/v1/calls`, { method: "POST", body: callData, ...options });
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* List call logs for the current account, paginated and filterable.
|
|
62
|
+
* @async
|
|
63
|
+
* @roles api, admin, developer, billing, user
|
|
64
|
+
* @param {Object} [params] - Request parameters.
|
|
65
|
+
* @param {ListCallsFilters} [params.filters] - Optional filters.
|
|
66
|
+
* @param {import('../../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
|
|
67
|
+
* @returns {Promise<Object>} `{ calls: [...], total, page, limit }`.
|
|
68
|
+
*/
|
|
69
|
+
async list({ filters = {}, options = {} } = {}) {
|
|
70
|
+
const query = new URLSearchParams();
|
|
71
|
+
for (const [k, v] of Object.entries(filters)) {
|
|
72
|
+
if (v !== undefined && v !== null && v !== "") query.set(k, String(v));
|
|
73
|
+
}
|
|
74
|
+
const qs = query.toString();
|
|
75
|
+
const path = qs ? `/voice/v1/calls?${qs}` : `/voice/v1/calls`;
|
|
76
|
+
return this.client(path, { method: "GET", ...options });
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Get a single call log by ID.
|
|
81
|
+
* @async
|
|
82
|
+
* @roles api, admin, developer, billing, user
|
|
83
|
+
* @param {Object} params - Request parameters.
|
|
84
|
+
* @param {string} params.id - The call log UUID (the value returned as `call_id` from `create`).
|
|
85
|
+
* @param {import('../../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
|
|
86
|
+
* @throws {Error} If id is missing.
|
|
87
|
+
* @returns {Promise<Object>} The call log.
|
|
88
|
+
*/
|
|
89
|
+
async get({ id, options = {} }) {
|
|
90
|
+
this.client._require({ id });
|
|
91
|
+
const safeId = encodeURIComponent(id);
|
|
92
|
+
return this.client(`/voice/v1/calls/${safeId}`, { method: "GET", ...options });
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Hang up an in-progress call.
|
|
97
|
+
* @async
|
|
98
|
+
* @roles api, admin, developer, billing, user
|
|
99
|
+
* @param {Object} params - Request parameters.
|
|
100
|
+
* @param {string} params.id - The call log UUID.
|
|
101
|
+
* @param {"NORMAL"|"BUSY"|"NO_ANSWER"|"REJECTED"} [params.reason] - Hangup reason recorded on the call log. Defaults to NORMAL.
|
|
102
|
+
* @param {import('../../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
|
|
103
|
+
* @throws {Error} If id is missing.
|
|
104
|
+
* @returns {Promise<Object>} `{ success: boolean, message: string }`.
|
|
105
|
+
*/
|
|
106
|
+
async hangup({ id, reason, options = {} }) {
|
|
107
|
+
this.client._require({ id });
|
|
108
|
+
const safeId = encodeURIComponent(id);
|
|
109
|
+
const body = reason ? { reason } : {};
|
|
110
|
+
return this.client(`/voice/v1/calls/${safeId}/hangup`, { method: "POST", body, ...options });
|
|
111
|
+
}
|
|
112
|
+
}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {Object} CreateSipProfileData
|
|
3
|
+
* @property {string} name - Profile name (required).
|
|
4
|
+
* @property {boolean} [recordingAllowed] - Permit call recording on this endpoint.
|
|
5
|
+
* @property {boolean} [transcriptionEnabled] - Permit transcription on calls to/from this endpoint.
|
|
6
|
+
* @property {boolean} [sentimentFlag] - Permit sentiment analysis on this endpoint.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @typedef {Object} UpdateSipProfileData
|
|
11
|
+
* @property {string} [name] - Profile name.
|
|
12
|
+
* @property {string} [sipUsername] - SIP username override.
|
|
13
|
+
* @property {string} [password] - New password (also the way to "regenerate" — pass a fresh value).
|
|
14
|
+
* @property {"UDP"|"TCP"|"TLS"} [transport] - SIP transport.
|
|
15
|
+
* @property {boolean} [recordingAllowed] - Permit call recording.
|
|
16
|
+
* @property {boolean} [transcriptionEnabled] - Permit transcription.
|
|
17
|
+
* @property {boolean} [sentimentFlag] - Permit sentiment analysis.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* SIP Profile / endpoint management. A SIP profile is a single registerable
|
|
22
|
+
* UA — a desk phone, a softphone, a SIP-capable device — that registers to
|
|
23
|
+
* Signal House with a username and password. Distinct from a SIP trunk,
|
|
24
|
+
* which represents a peer-to-peer link to another PBX or carrier.
|
|
25
|
+
*
|
|
26
|
+
* Calls the voice-backend service mounted under /voice. Accessed via
|
|
27
|
+
* `sdk.voice.sipProfiles`.
|
|
28
|
+
*/
|
|
29
|
+
export class SipProfiles {
|
|
30
|
+
constructor(client, enableAdmin) {
|
|
31
|
+
this.client = client;
|
|
32
|
+
this.enableAdmin = enableAdmin;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* List all SIP profiles belonging to the current account.
|
|
37
|
+
* @async
|
|
38
|
+
* @roles api, admin, developer, billing, user
|
|
39
|
+
* @param {Object} [params] - Request parameters.
|
|
40
|
+
* @param {import('../../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
|
|
41
|
+
* @returns {Promise<Object>} `{ sipProfiles: [...] }`.
|
|
42
|
+
*/
|
|
43
|
+
async list({ options = {} } = {}) {
|
|
44
|
+
return this.client(`/voice/sip-profiles`, { method: "GET", ...options });
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Get a single SIP profile by ID. NOTE: response does NOT include the
|
|
49
|
+
* password — use `getPassword({ id })` to retrieve it.
|
|
50
|
+
* @async
|
|
51
|
+
* @roles api, admin, developer, billing, user
|
|
52
|
+
* @param {Object} params - Request parameters.
|
|
53
|
+
* @param {string} params.id - The SIP profile UUID.
|
|
54
|
+
* @param {import('../../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
|
|
55
|
+
* @throws {Error} If id is missing.
|
|
56
|
+
* @returns {Promise<Object>} `{ sipProfile: {...} }`.
|
|
57
|
+
*/
|
|
58
|
+
async get({ id, options = {} }) {
|
|
59
|
+
this.client._require({ id });
|
|
60
|
+
const safeId = encodeURIComponent(id);
|
|
61
|
+
return this.client(`/voice/sip-profiles/${safeId}`, { method: "GET", ...options });
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Get the password for a SIP profile. The password is generated by the
|
|
66
|
+
* server on create and stored; this endpoint returns the stored value
|
|
67
|
+
* (it is NOT one-time-visible like the create response — calling getPassword
|
|
68
|
+
* later still returns the password as long as it has not been replaced).
|
|
69
|
+
* @async
|
|
70
|
+
* @roles api, admin, developer, billing, user
|
|
71
|
+
* @param {Object} params - Request parameters.
|
|
72
|
+
* @param {string} params.id - The SIP profile UUID.
|
|
73
|
+
* @param {import('../../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
|
|
74
|
+
* @throws {Error} If id is missing.
|
|
75
|
+
* @returns {Promise<Object>} `{ password: string|null }`.
|
|
76
|
+
*/
|
|
77
|
+
async getPassword({ id, options = {} }) {
|
|
78
|
+
this.client._require({ id });
|
|
79
|
+
const safeId = encodeURIComponent(id);
|
|
80
|
+
return this.client(`/voice/sip-profiles/${safeId}/password`, { method: "GET", ...options });
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* List valid SIP transports + their address/port per region from the DB.
|
|
85
|
+
* Used by edit-profile UI to populate transport selectors.
|
|
86
|
+
* @async
|
|
87
|
+
* @roles api, admin, developer, billing, user
|
|
88
|
+
* @param {Object} [params] - Request parameters.
|
|
89
|
+
* @param {import('../../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
|
|
90
|
+
* @returns {Promise<Object>} `{ transports: [{ transport, address, port }, ...] }`.
|
|
91
|
+
*/
|
|
92
|
+
async getTransports({ options = {} } = {}) {
|
|
93
|
+
return this.client(`/voice/sip-profiles/transports`, { method: "GET", ...options });
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Create a new SIP profile. The server generates the SIP username and
|
|
98
|
+
* password; the password is returned on the create response at the top
|
|
99
|
+
* level (NOT nested inside `sipProfile`) and is the only chance to surface
|
|
100
|
+
* it without an explicit `getPassword` lookup.
|
|
101
|
+
* @async
|
|
102
|
+
* @roles api, admin, developer, billing, user
|
|
103
|
+
* @param {Object} params - Request parameters.
|
|
104
|
+
* @param {CreateSipProfileData} params.profileData - The SIP profile to create.
|
|
105
|
+
* @param {import('../../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
|
|
106
|
+
* @throws {Error} If profileData is missing.
|
|
107
|
+
* @returns {Promise<Object>} `{ sipProfile: {...}, password: string, sipServer: string, message: string }`.
|
|
108
|
+
*/
|
|
109
|
+
async create({ profileData, options = {} }) {
|
|
110
|
+
this.client._require({ profileData });
|
|
111
|
+
return this.client(`/voice/sip-profiles`, { method: "POST", body: profileData, ...options });
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Update an existing SIP profile. To rotate the password, pass a new
|
|
116
|
+
* `password` value here — there is no dedicated regenerate endpoint.
|
|
117
|
+
* @async
|
|
118
|
+
* @roles api, admin, developer, billing, user
|
|
119
|
+
* @param {Object} params - Request parameters.
|
|
120
|
+
* @param {string} params.id - The SIP profile UUID.
|
|
121
|
+
* @param {UpdateSipProfileData} params.updateData - Fields to update.
|
|
122
|
+
* @param {import('../../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
|
|
123
|
+
* @throws {Error} If id or updateData is missing.
|
|
124
|
+
* @returns {Promise<Object>} `{ sipProfile: {...} }`.
|
|
125
|
+
*/
|
|
126
|
+
async update({ id, updateData, options = {} }) {
|
|
127
|
+
this.client._require({ id, updateData });
|
|
128
|
+
const safeId = encodeURIComponent(id);
|
|
129
|
+
return this.client(`/voice/sip-profiles/${safeId}`, { method: "PATCH", body: updateData, ...options });
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Delete a SIP profile by ID. Unassigns any linked numbers and frees the
|
|
134
|
+
* extension as a side-effect.
|
|
135
|
+
* @async
|
|
136
|
+
* @roles api, admin, developer, billing, user
|
|
137
|
+
* @param {Object} params - Request parameters.
|
|
138
|
+
* @param {string} params.id - The SIP profile UUID.
|
|
139
|
+
* @param {import('../../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
|
|
140
|
+
* @throws {Error} If id is missing.
|
|
141
|
+
* @returns {Promise<Object>} `{ message: string }`.
|
|
142
|
+
*/
|
|
143
|
+
async delete({ id, options = {} }) {
|
|
144
|
+
this.client._require({ id });
|
|
145
|
+
const safeId = encodeURIComponent(id);
|
|
146
|
+
return this.client(`/voice/sip-profiles/${safeId}`, { method: "DELETE", ...options });
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Assign a phone number to this SIP profile (routes inbound calls on that
|
|
151
|
+
* number to the endpoint).
|
|
152
|
+
* @async
|
|
153
|
+
* @roles api, admin, developer, billing, user
|
|
154
|
+
* @param {Object} params - Request parameters.
|
|
155
|
+
* @param {string} params.id - The SIP profile UUID.
|
|
156
|
+
* @param {string} params.phoneNumberId - The phone number UUID to assign.
|
|
157
|
+
* @param {import('../../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
|
|
158
|
+
* @throws {Error} If id or phoneNumberId is missing.
|
|
159
|
+
* @returns {Promise<Object>} `{ sipProfile: {...} }`.
|
|
160
|
+
*/
|
|
161
|
+
async assignNumber({ id, phoneNumberId, options = {} }) {
|
|
162
|
+
this.client._require({ id, phoneNumberId });
|
|
163
|
+
const safeId = encodeURIComponent(id);
|
|
164
|
+
return this.client(`/voice/sip-profiles/${safeId}/assign-number`, {
|
|
165
|
+
method: "POST",
|
|
166
|
+
body: { phoneNumberId },
|
|
167
|
+
...options,
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Unassign a phone number from this SIP profile.
|
|
173
|
+
* @async
|
|
174
|
+
* @roles api, admin, developer, billing, user
|
|
175
|
+
* @param {Object} params - Request parameters.
|
|
176
|
+
* @param {string} params.id - The SIP profile UUID.
|
|
177
|
+
* @param {string} params.phoneNumberId - The phone number UUID to unassign.
|
|
178
|
+
* @param {import('../../SignalHouseSDK').RequestOptions} [params.options] - Additional options for the request.
|
|
179
|
+
* @throws {Error} If id or phoneNumberId is missing.
|
|
180
|
+
* @returns {Promise<Object>} `{ sipProfile: {...} }`.
|
|
181
|
+
*/
|
|
182
|
+
async unassignNumber({ id, phoneNumberId, options = {} }) {
|
|
183
|
+
this.client._require({ id, phoneNumberId });
|
|
184
|
+
const safeId = encodeURIComponent(id);
|
|
185
|
+
return this.client(`/voice/sip-profiles/${safeId}/unassign-number`, {
|
|
186
|
+
method: "POST",
|
|
187
|
+
body: { phoneNumberId },
|
|
188
|
+
...options,
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
}
|