@fonoster/sdk 0.30.0 → 0.31.0

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.
Files changed (54) hide show
  1. package/README.md +6 -4
  2. package/dist/node/Agents.js +5 -20
  3. package/dist/node/Applications.js +13 -5
  4. package/dist/node/Billing.d.ts +50 -0
  5. package/dist/node/Billing.js +84 -0
  6. package/dist/node/CallRecords.js +5 -2
  7. package/dist/node/Calls.d.ts +3 -1
  8. package/dist/node/Calls.js +3 -1
  9. package/dist/node/Numbers.js +2 -7
  10. package/dist/node/Providers.js +4 -2
  11. package/dist/node/Regions.js +5 -2
  12. package/dist/node/Usage.d.ts +44 -0
  13. package/dist/node/Usage.js +41 -0
  14. package/dist/node/client/AbstractClient.d.ts +11 -0
  15. package/dist/node/client/AbstractClient.js +5 -1
  16. package/dist/node/client/Client.d.ts +2 -0
  17. package/dist/node/client/Client.js +13 -1
  18. package/dist/node/client/types/BillingClient.d.ts +28 -0
  19. package/dist/node/client/types/BillingClient.js +2 -0
  20. package/dist/node/client/types/FonosterClient.d.ts +5 -1
  21. package/dist/node/client/types/UsageClient.d.ts +24 -0
  22. package/dist/node/client/types/UsageClient.js +2 -0
  23. package/dist/node/client/types/index.d.ts +2 -0
  24. package/dist/node/client/types/index.js +2 -0
  25. package/dist/node/generated/node/applications_pb.js +368 -6
  26. package/dist/node/generated/node/billing_grpc_pb.js +169 -0
  27. package/dist/node/generated/node/billing_pb.js +1720 -0
  28. package/dist/node/generated/node/calls_pb.js +62 -2
  29. package/dist/node/generated/node/capabilities_pb.js +204 -1
  30. package/dist/node/generated/node/providers_pb.js +61 -1
  31. package/dist/node/generated/node/usage_grpc_pb.js +64 -0
  32. package/dist/node/generated/node/usage_pb.js +866 -0
  33. package/dist/node/generated/web/BillingServiceClientPb.ts +258 -0
  34. package/dist/node/generated/web/UsageServiceClientPb.ts +86 -0
  35. package/dist/node/generated/web/applications_pb.d.ts +42 -0
  36. package/dist/node/generated/web/applications_pb.js +368 -6
  37. package/dist/node/generated/web/billing_pb.d.ts +210 -0
  38. package/dist/node/generated/web/billing_pb.js +1720 -0
  39. package/dist/node/generated/web/calls_pb.d.ts +8 -0
  40. package/dist/node/generated/web/calls_pb.js +62 -2
  41. package/dist/node/generated/web/capabilities_pb.d.ts +24 -0
  42. package/dist/node/generated/web/capabilities_pb.js +204 -1
  43. package/dist/node/generated/web/providers_pb.d.ts +8 -0
  44. package/dist/node/generated/web/providers_pb.js +61 -1
  45. package/dist/node/generated/web/usage_pb.d.ts +106 -0
  46. package/dist/node/generated/web/usage_pb.js +866 -0
  47. package/dist/node/node.d.ts +2 -0
  48. package/dist/node/node.js +2 -0
  49. package/dist/node/tsconfig.tsbuildinfo +1 -1
  50. package/dist/node/utils.d.ts +8 -1
  51. package/dist/node/utils.js +18 -2
  52. package/dist/web/fonoster.min.js +1 -1
  53. package/dist/web/index.esm.js +1 -1
  54. package/package.json +7 -12
package/README.md CHANGED
@@ -64,7 +64,7 @@ In Node.js:
64
64
  ```typescript
65
65
  const SDK = require("@fonoster/sdk");
66
66
  const ACCESS_KEY_ID = "WO00000000000000000000000000000000";
67
- const ENDPOINT = "api.fonoster.com";
67
+ const ENDPOINT = "api.fonoster.ai";
68
68
  const client = new SDK.Client({ accessKeyId: ACCESS_KEY_ID, endpoint: ENDPOINT });
69
69
  ```
70
70
 
@@ -75,7 +75,7 @@ In the browser:
75
75
  ```typescript
76
76
  const SDK = require("@fonoster/sdk");
77
77
  const ACCESS_KEY_ID = "WO00000000000000000000000000000000";
78
- const URL = "https://api.fonoster.com/v1beta2";
78
+ const URL = "https://api.fonoster.ai/v1beta2";
79
79
  const client = new SDK.WebClient({ accessKeyId: ACCESS_KEY_ID, url: URL });
80
80
  ```
81
81
 
@@ -956,7 +956,7 @@ const request = {
956
956
  config: {
957
957
  conversationSettings: {
958
958
  firstMessage: "Hello, how can I help you today?",
959
- systemPrompt: "You are a helpful assistant.",
959
+ systemPrompt: "You are a helpful agent.",
960
960
  systemErrorMessage: "I'm sorry, I didn't catch that. Can you say that again?",
961
961
  goodbyeMessage: "Thank you for calling. Have a great day!",
962
962
  languageModel: {
@@ -1140,6 +1140,7 @@ Retrieves a list of Calls from a Workspace.
1140
1140
  | request | <code>ListCallsRequest</code> | The request object that contains the necessary information to retrieve a list of Calls |
1141
1141
  | request.pageSize | <code>number</code> | The number of Calls to retrieve |
1142
1142
  | request.pageToken | <code>string</code> | The token to retrieve the next page of Calls |
1143
+ | request.appRef | <code>string</code> | Optional. Lists only the Calls the App with this reference handled |
1143
1144
 
1144
1145
  **Example**
1145
1146
  ```js
@@ -1147,7 +1148,8 @@ const calls = new SDK.Calls(client); // Existing client object
1147
1148
 
1148
1149
  const request = {
1149
1150
  pageSize: 10,
1150
- pageToken: "00000000-0000-0000-0000-000000000000"
1151
+ pageToken: "00000000-0000-0000-0000-000000000000",
1152
+ appRef: "00000000-0000-0000-0000-000000000000" // Optional: only this App's Calls
1151
1153
  };
1152
1154
 
1153
1155
  calls
@@ -114,15 +114,8 @@ class Agents {
114
114
  request: { ref },
115
115
  enumMapping: [["privacy", agents_pb_1.Privacy]]
116
116
  });
117
- const credentials = response?.credentials?.toObject();
118
- const domain = response?.domain?.toObject();
119
- return response
120
- ? {
121
- ...response,
122
- credentials,
123
- domain
124
- }
125
- : null;
117
+ // The domain and credentials come back as plain objects (objectToJson).
118
+ return response ?? null;
126
119
  }
127
120
  /**
128
121
  * Updates an existing Agent in the Workspace.
@@ -192,19 +185,11 @@ class Agents {
192
185
  enumMapping: [["privacy", agents_pb_1.Privacy]],
193
186
  repeatableObjectMapping: [["itemsList", agents_pb_1.Agent]]
194
187
  });
195
- // Manually extract nested objects for each agent
196
- const processedItems = response.items?.map((agent) => {
197
- const credentials = agent?.credentials?.toObject();
198
- const domain = agent?.domain?.toObject();
199
- return {
200
- ...agent,
201
- credentials,
202
- domain
203
- };
204
- });
188
+ // Each agent's domain and credentials come back as plain objects
189
+ // (objectToJson); calling toObject() on them threw "toObject is not a function".
205
190
  return {
206
191
  ...response,
207
- items: processedItems || []
192
+ items: response.items ?? []
208
193
  };
209
194
  }
210
195
  /**
@@ -69,14 +69,18 @@ const REQUEST_OBJECTS = [
69
69
  ["speech", applications_pb_1.SpeechDefaults],
70
70
  ["audio", applications_pb_1.AudioFormat],
71
71
  ["listeners", applications_pb_1.Listener],
72
- ["amd", applications_pb_1.AmdSettings]
72
+ ["amd", applications_pb_1.AmdSettings],
73
+ ["filters", applications_pb_1.AudioFilter]
73
74
  ];
75
+ /** Repeated messages of an Application in responses (their options Structs are converted after). */
76
+ const RESPONSE_REPEATED = [["filtersList", applications_pb_1.AudioFilter]];
74
77
  /** Repeated fields come back as `listenersList` when empty; always return `listeners`. */
75
78
  function withSessionFields(app) {
76
- const { listenersList, ...rest } = app;
79
+ const { listenersList, filtersList, ...rest } = app;
77
80
  return {
78
81
  ...rest,
79
- listeners: (rest.listeners ?? listenersList ?? [])
82
+ listeners: (rest.listeners ?? listenersList ?? []),
83
+ filters: (rest.filters ?? filtersList ?? [])
80
84
  };
81
85
  }
82
86
  class Applications {
@@ -151,7 +155,8 @@ class Applications {
151
155
  metadata: this.client.getMetadata(),
152
156
  request: { ref },
153
157
  enumMapping: [["type", applications_pb_1.ApplicationType]],
154
- objectMapping: [["intelligence", applications_pb_1.ProductContainer]]
158
+ objectMapping: [["intelligence", applications_pb_1.ProductContainer]],
159
+ repeatableObjectMapping: RESPONSE_REPEATED
155
160
  });
156
161
  return withSessionFields((0, utils_1.buildStructOverrideReverse)(response));
157
162
  }
@@ -220,7 +225,10 @@ class Applications {
220
225
  request,
221
226
  enumMapping: [["type", applications_pb_1.ApplicationType]],
222
227
  objectMapping: [["intelligence", applications_pb_1.ProductContainer]],
223
- repeatableObjectMapping: [["itemsList", applications_pb_1.Application]]
228
+ repeatableObjectMapping: [
229
+ ["itemsList", applications_pb_1.Application],
230
+ ...RESPONSE_REPEATED
231
+ ]
224
232
  });
225
233
  return {
226
234
  items: response.items.map((item) => withSessionFields((0, utils_1.buildStructOverrideReverse)(item))),
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Copyright (C) 2025 by Fonoster Inc (https://fonoster.com)
3
+ * http://github.com/fonoster/fonoster
4
+ *
5
+ * This file is part of Fonoster
6
+ *
7
+ * Licensed under the MIT License (the "License");
8
+ * you may not use this file except in compliance with
9
+ * the License. You may obtain a copy of the License at
10
+ *
11
+ * https://opensource.org/licenses/MIT
12
+ *
13
+ * Unless required by applicable law or agreed to in writing, software
14
+ * distributed under the License is distributed on an "AS IS" BASIS,
15
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ * See the License for the specific language governing permissions and
17
+ * limitations under the License.
18
+ */
19
+ import { BillingSummary, CreatePortalSessionRequest, CreatePortalSessionResponse, CreateTopUpRequest, UpdateAutoRechargeRequest } from "@fonoster/types";
20
+ import { FonosterClient } from "./client/types";
21
+ /**
22
+ * @classdesc Fonoster Cloud's billing for the owner signed in: the balance in credits
23
+ * (1 credit = $0.01) by source, the plan, top-ups, auto-recharge and the Stripe Customer Portal.
24
+ * Only workspace owners may call it, and only on Fonoster Cloud (the capabilities say
25
+ * `billing.enabled`). The account is always the caller's: it covers every workspace they own.
26
+ *
27
+ * @example
28
+ * const billing = new SDK.Billing(client);
29
+ * const { balance, sources } = await billing.getBilling();
30
+ * await billing.createTopUp({ credits: 1000 });
31
+ */
32
+ declare class Billing {
33
+ private readonly client;
34
+ constructor(client: FonosterClient);
35
+ /** The balance by source, the plan and auto-recharge. */
36
+ getBilling(): Promise<BillingSummary>;
37
+ /** Turns auto-recharge on or off, with its threshold and amount in credits. */
38
+ updateAutoRecharge(request: UpdateAutoRechargeRequest): Promise<BillingSummary>;
39
+ /**
40
+ * Buys top-up credits, charged to the payment method added in the Customer Portal, with tax on
41
+ * top. The credits appear once the payment succeeds.
42
+ */
43
+ createTopUp(request: CreateTopUpRequest): Promise<BillingSummary>;
44
+ /** Moves the owner from the Trial to Pay-as-you-go. Needs a payment method first. */
45
+ subscribe(): Promise<BillingSummary>;
46
+ /** A Stripe Customer Portal link for payment methods and invoices. */
47
+ createPortalSession(request: CreatePortalSessionRequest): Promise<CreatePortalSessionResponse>;
48
+ private summary;
49
+ }
50
+ export { Billing };
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Billing = void 0;
4
+ const makeRpcRequest_1 = require("./client/makeRpcRequest");
5
+ const billing_pb_1 = require("./generated/node/billing_pb");
6
+ /**
7
+ * @classdesc Fonoster Cloud's billing for the owner signed in: the balance in credits
8
+ * (1 credit = $0.01) by source, the plan, top-ups, auto-recharge and the Stripe Customer Portal.
9
+ * Only workspace owners may call it, and only on Fonoster Cloud (the capabilities say
10
+ * `billing.enabled`). The account is always the caller's: it covers every workspace they own.
11
+ *
12
+ * @example
13
+ * const billing = new SDK.Billing(client);
14
+ * const { balance, sources } = await billing.getBilling();
15
+ * await billing.createTopUp({ credits: 1000 });
16
+ */
17
+ class Billing {
18
+ client;
19
+ constructor(client) {
20
+ this.client = client;
21
+ }
22
+ /** The balance by source, the plan and auto-recharge. */
23
+ async getBilling() {
24
+ const client = this.client.getBillingClient();
25
+ return this.summary((0, makeRpcRequest_1.makeRpcRequest)({
26
+ method: client.getBilling.bind(client),
27
+ requestPBObjectConstructor: billing_pb_1.GetBillingRequest,
28
+ metadata: this.client.getMetadata(),
29
+ request: {},
30
+ repeatableObjectMapping: [["sourcesList", billing_pb_1.CreditSource]]
31
+ }));
32
+ }
33
+ /** Turns auto-recharge on or off, with its threshold and amount in credits. */
34
+ async updateAutoRecharge(request) {
35
+ const client = this.client.getBillingClient();
36
+ return this.summary((0, makeRpcRequest_1.makeRpcRequest)({
37
+ method: client.updateAutoRecharge.bind(client),
38
+ requestPBObjectConstructor: billing_pb_1.UpdateAutoRechargeRequest,
39
+ metadata: this.client.getMetadata(),
40
+ request,
41
+ repeatableObjectMapping: [["sourcesList", billing_pb_1.CreditSource]]
42
+ }));
43
+ }
44
+ /**
45
+ * Buys top-up credits, charged to the payment method added in the Customer Portal, with tax on
46
+ * top. The credits appear once the payment succeeds.
47
+ */
48
+ async createTopUp(request) {
49
+ const client = this.client.getBillingClient();
50
+ return this.summary((0, makeRpcRequest_1.makeRpcRequest)({
51
+ method: client.createTopUp.bind(client),
52
+ requestPBObjectConstructor: billing_pb_1.CreateTopUpRequest,
53
+ metadata: this.client.getMetadata(),
54
+ request,
55
+ repeatableObjectMapping: [["sourcesList", billing_pb_1.CreditSource]]
56
+ }));
57
+ }
58
+ /** Moves the owner from the Trial to Pay-as-you-go. Needs a payment method first. */
59
+ async subscribe() {
60
+ const client = this.client.getBillingClient();
61
+ return this.summary((0, makeRpcRequest_1.makeRpcRequest)({
62
+ method: client.subscribe.bind(client),
63
+ requestPBObjectConstructor: billing_pb_1.SubscribeRequest,
64
+ metadata: this.client.getMetadata(),
65
+ request: {},
66
+ repeatableObjectMapping: [["sourcesList", billing_pb_1.CreditSource]]
67
+ }));
68
+ }
69
+ /** A Stripe Customer Portal link for payment methods and invoices. */
70
+ async createPortalSession(request) {
71
+ const client = this.client.getBillingClient();
72
+ return (0, makeRpcRequest_1.makeRpcRequest)({
73
+ method: client.createPortalSession.bind(client),
74
+ requestPBObjectConstructor: billing_pb_1.CreatePortalSessionRequest,
75
+ metadata: this.client.getMetadata(),
76
+ request
77
+ });
78
+ }
79
+ async summary(raw) {
80
+ const { sources, ...rest } = await raw;
81
+ return { ...rest, sources: sources ?? [] };
82
+ }
83
+ }
84
+ exports.Billing = Billing;
@@ -33,11 +33,14 @@ class CallRecords {
33
33
  constructor(client, options = {}) {
34
34
  this.client = client;
35
35
  this.baseUrl = options.baseUrl?.replace(/\/+$/, "");
36
+ // Called as a method below, so never store the global unbound: in browsers a detached
37
+ // `fetch` throws "Illegal invocation".
36
38
  this.fetchFn =
37
- options.fetch ?? globalThis.fetch;
39
+ options.fetch ??
40
+ ((input, init) => globalThis.fetch(input, init));
38
41
  }
39
42
  url(path, query = {}) {
40
- const base = this.baseUrl ?? this.client.getHttpUrl?.() ?? "https://api.fonoster.com";
43
+ const base = this.baseUrl ?? this.client.getHttpUrl?.() ?? "https://api.fonoster.ai";
41
44
  const qs = Object.entries(query)
42
45
  .filter(([, v]) => v !== undefined && v !== null && v !== "")
43
46
  .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`)
@@ -126,13 +126,15 @@ declare class Calls {
126
126
  * @param {ListCallsRequest} request - The request object that contains the necessary information to retrieve a list of Calls
127
127
  * @param {number} request.pageSize - The number of Calls to retrieve
128
128
  * @param {string} request.pageToken - The token to retrieve the next page of Calls
129
+ * @param {string} request.appRef - Optional. Lists only the Calls the App with this reference handled
129
130
  * @return {Promise<ListCallsResponse>} - The response object that contains the list of Calls
130
131
  * @example
131
132
  * const calls = new SDK.Calls(client); // Existing client object
132
133
  *
133
134
  * const request = {
134
135
  * pageSize: 10,
135
- * pageToken: "00000000-0000-0000-0000-000000000000"
136
+ * pageToken: "00000000-0000-0000-0000-000000000000",
137
+ * appRef: "00000000-0000-0000-0000-000000000000" // Optional: only this App's Calls
136
138
  * };
137
139
  *
138
140
  * calls
@@ -175,13 +175,15 @@ class Calls {
175
175
  * @param {ListCallsRequest} request - The request object that contains the necessary information to retrieve a list of Calls
176
176
  * @param {number} request.pageSize - The number of Calls to retrieve
177
177
  * @param {string} request.pageToken - The token to retrieve the next page of Calls
178
+ * @param {string} request.appRef - Optional. Lists only the Calls the App with this reference handled
178
179
  * @return {Promise<ListCallsResponse>} - The response object that contains the list of Calls
179
180
  * @example
180
181
  * const calls = new SDK.Calls(client); // Existing client object
181
182
  *
182
183
  * const request = {
183
184
  * pageSize: 10,
184
- * pageToken: "00000000-0000-0000-0000-000000000000"
185
+ * pageToken: "00000000-0000-0000-0000-000000000000",
186
+ * appRef: "00000000-0000-0000-0000-000000000000" // Optional: only this App's Calls
185
187
  * };
186
188
  *
187
189
  * calls
@@ -110,13 +110,8 @@ class Numbers {
110
110
  metadata: this.client.getMetadata(),
111
111
  request: { ref }
112
112
  });
113
- const trunk = response?.trunk?.toObject();
114
- return response
115
- ? {
116
- ...response,
117
- trunk
118
- }
119
- : null;
113
+ // The trunk comes back as a plain object (objectToJson).
114
+ return response ?? null;
120
115
  }
121
116
  /**
122
117
  * Updates an existing Number in the Workspace.
@@ -8,7 +8,8 @@ function toItem(raw) {
8
8
  const out = {};
9
9
  for (const [key, value] of Object.entries(raw)) {
10
10
  const name = key.endsWith("List") ? key.slice(0, -4) : key;
11
- if (value === "")
11
+ // Proto3 defaults: "" is unset, and keyless is false for anything but a keyless provider.
12
+ if (value === "" || (name === "keyless" && !value))
12
13
  continue;
13
14
  out[name] = value;
14
15
  }
@@ -82,7 +83,8 @@ class Providers {
82
83
  const out = {};
83
84
  for (const [key, value] of Object.entries(w)) {
84
85
  const name = key.endsWith("List") ? key.slice(0, -4) : key;
85
- if (value === "")
86
+ // Proto3 defaults: "" is unset, and keyless is false for anything but a keyless provider.
87
+ if (value === "" || (name === "keyless" && !value))
86
88
  continue;
87
89
  out[name] = value;
88
90
  }
@@ -33,8 +33,11 @@ class Regions {
33
33
  constructor(client, options = {}) {
34
34
  this.client = client;
35
35
  this.baseUrl = options.baseUrl?.replace(/\/+$/, "");
36
+ // Called as a method below, so never store the global unbound: in browsers a detached
37
+ // `fetch` throws "Illegal invocation".
36
38
  this.fetchFn =
37
- options.fetch ?? globalThis.fetch;
39
+ options.fetch ??
40
+ ((input, init) => globalThis.fetch(input, init));
38
41
  }
39
42
  headers(auth, body) {
40
43
  const h = {};
@@ -51,7 +54,7 @@ class Regions {
51
54
  return h;
52
55
  }
53
56
  async json(path, method = "GET", body, auth = true) {
54
- const base = this.baseUrl ?? this.client.getHttpUrl?.() ?? "https://api.fonoster.com";
57
+ const base = this.baseUrl ?? this.client.getHttpUrl?.() ?? "https://api.fonoster.ai";
55
58
  const attempt = () => this.fetchFn(`${base}/api/regions${path}`, {
56
59
  method,
57
60
  headers: this.headers(auth, body),
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Copyright (C) 2025 by Fonoster Inc (https://fonoster.com)
3
+ * http://github.com/fonoster/fonoster
4
+ *
5
+ * This file is part of Fonoster
6
+ *
7
+ * Licensed under the MIT License (the "License");
8
+ * you may not use this file except in compliance with
9
+ * the License. You may obtain a copy of the License at
10
+ *
11
+ * https://opensource.org/licenses/MIT
12
+ *
13
+ * Unless required by applicable law or agreed to in writing, software
14
+ * distributed under the License is distributed on an "AS IS" BASIS,
15
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ * See the License for the specific language governing permissions and
17
+ * limitations under the License.
18
+ */
19
+ import { GetUsageRequest, GetUsageResponse } from "@fonoster/types";
20
+ import { FonosterClient } from "./client/types";
21
+ /**
22
+ * @classdesc What the workspace consumed: call minutes, speech, language-model tokens, noise
23
+ * cancelling, answering-machine detections, recordings and storage. Quantities only, never money.
24
+ * Each total says whose key a vendor was called with (`keySource`: `workspace` or `platform`).
25
+ *
26
+ * @example
27
+ * const usage = new SDK.Usage(client);
28
+ * const { rows } = await usage.getUsage({
29
+ * fromDay: "2026-10-01",
30
+ * toDay: "2026-10-31",
31
+ * groupBy: ["key_source"]
32
+ * });
33
+ */
34
+ declare class Usage {
35
+ private readonly client;
36
+ constructor(client: FonosterClient);
37
+ /**
38
+ * Usage totals for a range of days (UTC, inclusive), split by meter and by the dimensions in
39
+ * `groupBy` (day, workspace, provider, model, key_source, origin). With `allOwned`, a workspace
40
+ * owner gets every workspace they own.
41
+ */
42
+ getUsage(request: GetUsageRequest): Promise<GetUsageResponse>;
43
+ }
44
+ export { Usage };
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Usage = void 0;
4
+ const makeRpcRequest_1 = require("./client/makeRpcRequest");
5
+ const usage_pb_1 = require("./generated/node/usage_pb");
6
+ /**
7
+ * @classdesc What the workspace consumed: call minutes, speech, language-model tokens, noise
8
+ * cancelling, answering-machine detections, recordings and storage. Quantities only, never money.
9
+ * Each total says whose key a vendor was called with (`keySource`: `workspace` or `platform`).
10
+ *
11
+ * @example
12
+ * const usage = new SDK.Usage(client);
13
+ * const { rows } = await usage.getUsage({
14
+ * fromDay: "2026-10-01",
15
+ * toDay: "2026-10-31",
16
+ * groupBy: ["key_source"]
17
+ * });
18
+ */
19
+ class Usage {
20
+ client;
21
+ constructor(client) {
22
+ this.client = client;
23
+ }
24
+ /**
25
+ * Usage totals for a range of days (UTC, inclusive), split by meter and by the dimensions in
26
+ * `groupBy` (day, workspace, provider, model, key_source, origin). With `allOwned`, a workspace
27
+ * owner gets every workspace they own.
28
+ */
29
+ async getUsage(request) {
30
+ const client = this.client.getUsageClient();
31
+ const raw = await (0, makeRpcRequest_1.makeRpcRequest)({
32
+ method: client.getUsage.bind(client),
33
+ requestPBObjectConstructor: usage_pb_1.GetUsageRequest,
34
+ metadata: this.client.getMetadata(),
35
+ request: { groupBy: [], ...request },
36
+ repeatableObjectMapping: [["rowsList", usage_pb_1.UsageRow]]
37
+ });
38
+ return { rows: raw.rows ?? [] };
39
+ }
40
+ }
41
+ exports.Usage = Usage;
@@ -21,11 +21,13 @@ import { GetCapabilitiesResponse as GetCapabilitiesResponsePB } from "../generat
21
21
  import { ApplicationsClient, CallsClient, CapabilitiesClient, FonosterClient, IdentityClient, SecretsClient } from "./types";
22
22
  import { AclsClient } from "./types/AclsClient";
23
23
  import { AgentsClient } from "./types/AgentsClient";
24
+ import { BillingClient } from "./types/BillingClient";
24
25
  import { CredentialsClient } from "./types/CredentialsClient";
25
26
  import { DomainsClient } from "./types/DomainsClient";
26
27
  import { NumbersClient } from "./types/NumbersClient";
27
28
  import { ProvidersClient } from "./types/ProvidersClient";
28
29
  import { TrunksClient } from "./types/TrunksClient";
30
+ import { UsageClient } from "./types/UsageClient";
29
31
  import { WebhooksClient } from "./types/WebhooksClient";
30
32
  type AuthMethod = "password" | "email_code" | "github";
31
33
  /** The deployment's capabilities, from the Capabilities service. */
@@ -60,6 +62,13 @@ type Capabilities = {
60
62
  * Empty lists when the operator listed none or the server is older.
61
63
  */
62
64
  connection: ConnectionDetails;
65
+ /**
66
+ * How SIP names (trunk inbound URIs, domains) are checked: "domain" (one
67
+ * label under `sip.<domain>`, the default) or "any" (any host or IP).
68
+ */
69
+ sip: {
70
+ names: "domain" | "any";
71
+ };
63
72
  };
64
73
  type SipTransport = "udp" | "tcp" | "tls" | "ws" | "wss";
65
74
  type ConnectionDetails = {
@@ -143,6 +152,8 @@ declare abstract class AbstractClient implements FonosterClient {
143
152
  abstract getCallsClient(): CallsClient;
144
153
  abstract getWebhooksClient(): WebhooksClient;
145
154
  abstract getProvidersClient(): ProvidersClient;
155
+ abstract getUsageClient(): UsageClient;
156
+ abstract getBillingClient(): BillingClient;
146
157
  abstract getHttpUrl(): string;
147
158
  }
148
159
  export { AbstractClient, AuthMethod, Capabilities, ConnectionDetails, toConnectionDetails };
@@ -168,7 +168,11 @@ class AbstractClient {
168
168
  regions: {
169
169
  private: response.getRegions()?.getPrivate() ?? false
170
170
  },
171
- connection: toConnectionDetails(response)
171
+ connection: toConnectionDetails(response),
172
+ sip: {
173
+ // Older servers don't send it; they checked nothing.
174
+ names: response.getSip()?.getNames() === "domain" ? "domain" : "any"
175
+ }
172
176
  });
173
177
  });
174
178
  });
@@ -44,6 +44,8 @@ export declare class Client extends AbstractClient {
44
44
  getNumbersClient(): any;
45
45
  getWebhooksClient(): any;
46
46
  getProvidersClient(): any;
47
+ getUsageClient(): any;
48
+ getBillingClient(): any;
47
49
  getHttpUrl(): string;
48
50
  getCredentialsClient(): any;
49
51
  }
@@ -23,6 +23,7 @@ const grpc_js_1 = require("@grpc/grpc-js");
23
23
  const acls_grpc_pb_1 = require("../generated/node/acls_grpc_pb");
24
24
  const agents_grpc_pb_1 = require("../generated/node/agents_grpc_pb");
25
25
  const applications_grpc_pb_1 = require("../generated/node/applications_grpc_pb");
26
+ const billing_grpc_pb_1 = require("../generated/node/billing_grpc_pb");
26
27
  const calls_grpc_pb_1 = require("../generated/node/calls_grpc_pb");
27
28
  const capabilities_grpc_pb_1 = require("../generated/node/capabilities_grpc_pb");
28
29
  const credentials_grpc_pb_1 = require("../generated/node/credentials_grpc_pb");
@@ -32,10 +33,11 @@ const numbers_grpc_pb_1 = require("../generated/node/numbers_grpc_pb");
32
33
  const providers_grpc_pb_1 = require("../generated/node/providers_grpc_pb");
33
34
  const secrets_grpc_pb_1 = require("../generated/node/secrets_grpc_pb");
34
35
  const trunks_grpc_pb_1 = require("../generated/node/trunks_grpc_pb");
36
+ const usage_grpc_pb_1 = require("../generated/node/usage_grpc_pb");
35
37
  const webhooks_grpc_pb_1 = require("../generated/node/webhooks_grpc_pb");
36
38
  const AbstractClient_1 = require("./AbstractClient");
37
39
  const TokenRefresherNode_1 = require("./TokenRefresherNode");
38
- const DEFAULT_ENDPOINT = "api.fonoster.com";
40
+ const DEFAULT_ENDPOINT = "api.fonoster.ai";
39
41
  class Client extends AbstractClient_1.AbstractClient {
40
42
  endpoint;
41
43
  httpUrl;
@@ -123,6 +125,16 @@ class Client extends AbstractClient_1.AbstractClient {
123
125
  interceptors: [this.tokenRefresherInterceptor]
124
126
  });
125
127
  }
128
+ getUsageClient() {
129
+ return new usage_grpc_pb_1.UsageClient(this.endpoint, this.channelCredentials, {
130
+ interceptors: [this.tokenRefresherInterceptor]
131
+ });
132
+ }
133
+ getBillingClient() {
134
+ return new billing_grpc_pb_1.BillingClient(this.endpoint, this.channelCredentials, {
135
+ interceptors: [this.tokenRefresherInterceptor]
136
+ });
137
+ }
126
138
  getHttpUrl() {
127
139
  return (this.httpUrl ?? `https://${this.endpoint.replace(/:\d+$/, "")}`).replace(/\/+$/, "");
128
140
  }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Copyright (C) 2025 by Fonoster Inc (https://fonoster.com)
3
+ * http://github.com/fonoster/fonoster
4
+ *
5
+ * This file is part of Fonoster
6
+ *
7
+ * Licensed under the MIT License (the "License");
8
+ * you may not use this file except in compliance with
9
+ * the License. You may obtain a copy of the License at
10
+ *
11
+ * https://opensource.org/licenses/MIT
12
+ *
13
+ * Unless required by applicable law or agreed to in writing, software
14
+ * distributed under the License is distributed on an "AS IS" BASIS,
15
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ * See the License for the specific language governing permissions and
17
+ * limitations under the License.
18
+ */
19
+ import { BillingSummary, CreatePortalSessionRequest, CreatePortalSessionResponse, CreateTopUpRequest, GetBillingRequest, SubscribeRequest, UpdateAutoRechargeRequest } from "../../generated/web/billing_pb";
20
+ import { ClientFunction } from "./common";
21
+ type BillingClient = {
22
+ getBilling: ClientFunction<GetBillingRequest, BillingSummary>;
23
+ updateAutoRecharge: ClientFunction<UpdateAutoRechargeRequest, BillingSummary>;
24
+ createTopUp: ClientFunction<CreateTopUpRequest, BillingSummary>;
25
+ subscribe: ClientFunction<SubscribeRequest, BillingSummary>;
26
+ createPortalSession: ClientFunction<CreatePortalSessionRequest, CreatePortalSessionResponse>;
27
+ };
28
+ export { BillingClient };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -19,6 +19,7 @@
19
19
  import { AclsClient } from "./AclsClient";
20
20
  import { AgentsClient } from "./AgentsClient";
21
21
  import { ApplicationsClient } from "./ApplicationsClient";
22
+ import { BillingClient } from "./BillingClient";
22
23
  import { CallsClient } from "./CallsClient";
23
24
  import { CapabilitiesClient } from "./CapabilitiesClient";
24
25
  import { CredentialsClient } from "./CredentialsClient";
@@ -28,6 +29,7 @@ import { NumbersClient } from "./NumbersClient";
28
29
  import { ProvidersClient } from "./ProvidersClient";
29
30
  import { SecretsClient } from "./SecretsClient";
30
31
  import { TrunksClient } from "./TrunksClient";
32
+ import { UsageClient } from "./UsageClient";
31
33
  import { WebhooksClient } from "./WebhooksClient";
32
34
  interface FonosterClient {
33
35
  getAccessToken(): string;
@@ -45,7 +47,9 @@ interface FonosterClient {
45
47
  getAclsClient(): AclsClient;
46
48
  getWebhooksClient(): WebhooksClient;
47
49
  getProvidersClient(): ProvidersClient;
48
- /** Base URL of the HTTP API (/api/records), e.g. https://api.fonoster.com. */
50
+ getUsageClient(): UsageClient;
51
+ getBillingClient(): BillingClient;
52
+ /** Base URL of the HTTP API (/api/records), e.g. https://api.fonoster.ai. */
49
53
  getHttpUrl?(): string;
50
54
  getMetadata(): unknown;
51
55
  refreshToken(): Promise<void>;
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Copyright (C) 2025 by Fonoster Inc (https://fonoster.com)
3
+ * http://github.com/fonoster/fonoster
4
+ *
5
+ * This file is part of Fonoster
6
+ *
7
+ * Licensed under the MIT License (the "License");
8
+ * you may not use this file except in compliance with
9
+ * the License. You may obtain a copy of the License at
10
+ *
11
+ * https://opensource.org/licenses/MIT
12
+ *
13
+ * Unless required by applicable law or agreed to in writing, software
14
+ * distributed under the License is distributed on an "AS IS" BASIS,
15
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ * See the License for the specific language governing permissions and
17
+ * limitations under the License.
18
+ */
19
+ import { GetUsageRequest, GetUsageResponse } from "../../generated/web/usage_pb";
20
+ import { ClientFunction } from "./common";
21
+ type UsageClient = {
22
+ getUsage: ClientFunction<GetUsageRequest, GetUsageResponse>;
23
+ };
24
+ export { UsageClient };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });