@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 CHANGED
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "name": "@signalhousellc/sdk",
3
- "version": "1.0.52",
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
  }
@@ -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
  /**
@@ -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
  }
@@ -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
@@ -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, additionalInformation (≤500)). Phone numbers cannot be changed via update — Toll-Free numbers are locked to their campaign.
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} [additionalInformation] - Free-text justification sent upstream to the carrier (optional, at most 500 characters). Required when more than one phone number is assigned to the campaign.
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, billing, user
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
@@ -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
  }
@@ -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
+ }