@vuevox/sdk 0.6.0 → 0.8.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.
package/README.md CHANGED
@@ -31,7 +31,10 @@ hello:read
31
31
  spaces:read
32
32
  agents:read
33
33
  calls:read
34
+ calls:write
34
35
  leads:read
36
+ leads:write
37
+ lead_custom_fields:manage
35
38
  ```
36
39
 
37
40
  The token request can only request scopes that were granted to that API client.
@@ -102,10 +105,18 @@ vuevox.agents.list();
102
105
  vuevox.agents.paginate();
103
106
  vuevox.calls.list();
104
107
  vuevox.calls.get("call-id");
108
+ vuevox.calls.upload({ idempotencyKey: "crm-call-123", spaceId: "space-id", agent: { externalId: "agent-1", name: "Morgan" }, lead: { externalId: "lead-1", firstName: "Ada", lastName: "Lovelace" }, audio: { file: audioBlob, filename: "call.mp3" } });
109
+ vuevox.calls.queueAnalysis("call-id");
110
+ vuevox.calls.waitForAnalysis("call-id");
105
111
  vuevox.calls.paginate();
106
112
  vuevox.leads.list();
107
113
  vuevox.leads.get("lead-id");
114
+ vuevox.leads.update("lead-id", { customFields: { crm_stage: "qualified" } });
115
+ vuevox.leads.upsertByExternalId("crm-lead-id", { firstName: "Ada", lastName: "Lovelace" });
108
116
  vuevox.leads.paginate();
117
+ vuevox.leadCustomFields.list();
118
+ vuevox.leadCustomFields.create({ key: "crm_stage", label: "CRM Stage", type: "select", options: ["new", "qualified"] });
119
+ vuevox.leadCustomFields.update("crm_stage", { label: "CRM Stage" });
109
120
  vuevox.raw.GET("/v1/hello", { headers: { Authorization: `Bearer ${await vuevox.getAccessToken()}` } });
110
121
  ```
111
122
 
@@ -273,12 +284,16 @@ Options: `ListCallsOptions`
273
284
  | `agentId` | `string` | Optional agent ID filter. |
274
285
  | `createdAfter` | `string` | Optional ISO 8601 lower bound for call creation time. |
275
286
  | `createdBefore` | `string` | Optional ISO 8601 upper bound for call creation time. |
287
+ | `leadCustomFields` | `Record<string, CustomFieldFilterValue>` | Optional filters on lead custom fields attached to calls. |
276
288
 
277
289
  ```ts
278
290
  const response = await vuevox.calls.list({
279
291
  limit: 50,
280
292
  spaceId: "space-id",
281
293
  createdAfter: "2026-01-01T00:00:00.000Z",
294
+ leadCustomFields: {
295
+ crm_stage: "qualified",
296
+ },
282
297
  });
283
298
 
284
299
  for (const call of response.data.data) {
@@ -301,6 +316,106 @@ console.log(response.data.data.transcript);
301
316
 
302
317
  Returns: `Promise<VueVoxApiResponse<CallDetailResponse>>`.
303
318
 
319
+ ### `vuevox.calls.upload(input)`
320
+
321
+ Uploads an audio recording, upserts the agent and lead by `externalId`, creates the call in an existing platform-managed space, and optionally queues analysis.
322
+
323
+ Required scope: `calls:write`.
324
+
325
+ The API requires an idempotency key for uploads. Reusing the same `idempotencyKey` with the same request returns the original response; reusing it with different metadata or audio returns an `idempotency_key_conflict` error.
326
+
327
+ Spaces are managed in VueVox. Use `vuevox.spaces.list()` to obtain the `spaceId`.
328
+
329
+ The maximum audio upload size is configured by a VueVox superadmin and defaults to 20 MB. Your server/proxy upload limits must also allow that size.
330
+
331
+ Options: `UploadCallInput`
332
+
333
+ | Option | Type | Description |
334
+ | --- | --- | --- |
335
+ | `idempotencyKey` | `string` | Required unique key for safe retries. |
336
+ | `spaceId` | `string` | Required existing VueVox space ID. |
337
+ | `externalId` | `string \| null` | Optional call ID from your system. |
338
+ | `queueAnalysis` | `boolean` | Optional. Defaults to `true`; set `false` to upload now and queue later. |
339
+ | `agent.externalId` | `string` | Required agent ID from your system. |
340
+ | `agent.name` | `string` | Required when creating a new agent. |
341
+ | `agent.email` | `string \| null` | Optional agent email. |
342
+ | `agent.phone` | `string \| null` | Optional agent phone. |
343
+ | `lead.externalId` | `string` | Required lead/prospect ID from your system. |
344
+ | `lead.firstName` | `string` | Required when creating a new lead. |
345
+ | `lead.lastName` | `string` | Required when creating a new lead. |
346
+ | `lead.email` | `string \| null` | Optional lead email. |
347
+ | `lead.phone` | `string \| null` | Optional lead phone. |
348
+ | `lead.customFields` | `Record<string, unknown>` | Optional organization-defined lead custom fields. |
349
+ | `audio.file` | `Blob` | Required audio file blob. In Node, use `new Blob([buffer], { type: "audio/mpeg" })`. |
350
+ | `audio.filename` | `string` | Optional filename sent in multipart upload. |
351
+
352
+ ```ts
353
+ import { readFile } from "node:fs/promises";
354
+
355
+ const buffer = await readFile("./call.mp3");
356
+
357
+ const response = await vuevox.calls.upload({
358
+ idempotencyKey: "crm-call-789",
359
+ externalId: "crm-call-789",
360
+ spaceId: "space-id",
361
+ queueAnalysis: true,
362
+ agent: {
363
+ externalId: "agent-123",
364
+ name: "Morgan Agent",
365
+ },
366
+ lead: {
367
+ externalId: "prospect-456",
368
+ firstName: "Ada",
369
+ lastName: "Lovelace",
370
+ email: "ada@example.com",
371
+ customFields: {
372
+ crm_stage: "qualified",
373
+ },
374
+ },
375
+ audio: {
376
+ file: new Blob([buffer], { type: "audio/mpeg" }),
377
+ filename: "call.mp3",
378
+ },
379
+ });
380
+
381
+ console.log(response.data.data.id, response.data.data.analysisStatus, response.requestId);
382
+ ```
383
+
384
+ Returns: `Promise<VueVoxApiResponse<CallResponse>>`.
385
+
386
+ ### `vuevox.calls.queueAnalysis(callId)`
387
+
388
+ Queues analysis for a call that was uploaded with `queueAnalysis: false`.
389
+
390
+ Required scope: `calls:write`.
391
+
392
+ ```ts
393
+ const response = await vuevox.calls.queueAnalysis("call-id");
394
+ console.log(response.data.data.analysisStatus, response.data.data.queueStatus);
395
+ ```
396
+
397
+ Returns: `Promise<VueVoxApiResponse<CallResponse>>`.
398
+
399
+ ### `vuevox.calls.waitForAnalysis(callId, options?)`
400
+
401
+ Polls `vuevox.calls.get(callId)` until the call analysis status is `completed` or `failed`.
402
+
403
+ Required scope: `calls:read`.
404
+
405
+ Options: `WaitForAnalysisOptions`
406
+
407
+ | Option | Type | Description |
408
+ | --- | --- | --- |
409
+ | `intervalMs` | `number` | Poll interval. Defaults to `2000`. |
410
+ | `timeoutMs` | `number` | Timeout before throwing `analysis_timeout`. Defaults to `120000`. |
411
+
412
+ ```ts
413
+ const response = await vuevox.calls.waitForAnalysis("call-id", { timeoutMs: 180000 });
414
+ console.log(response.data.data.analysis);
415
+ ```
416
+
417
+ Returns: `Promise<VueVoxApiResponse<CallDetailResponse>>`.
418
+
304
419
  ### `vuevox.calls.paginate(options?)`
305
420
 
306
421
  Iterates organization calls across all pages.
@@ -321,7 +436,7 @@ Returns: `AsyncGenerator<CallSummary>`.
321
436
 
322
437
  Lists organization leads. The `leads:read` scope includes lead email and phone contact details.
323
438
 
324
- Lead records include nullable `externalId` when you store an ID from another system.
439
+ Lead records include nullable `externalId` when you store an ID from another system, and a `customFields` object for organization-defined CRM fields.
325
440
 
326
441
  Required scope: `leads:read`.
327
442
 
@@ -334,12 +449,20 @@ Options: `ListLeadsOptions`
334
449
  | `spaceId` | `string` | Optional space ID filter. |
335
450
  | `createdAfter` | `string` | Optional ISO 8601 lower bound for lead creation time. |
336
451
  | `createdBefore` | `string` | Optional ISO 8601 upper bound for lead creation time. |
452
+ | `customFields` | `Record<string, CustomFieldFilterValue>` | Optional filters on lead custom fields. |
337
453
 
338
454
  ```ts
339
- const response = await vuevox.leads.list({ limit: 50, spaceId: "space-id" });
455
+ const response = await vuevox.leads.list({
456
+ limit: 50,
457
+ spaceId: "space-id",
458
+ customFields: {
459
+ crm_stage: "qualified",
460
+ deal_value: { gte: 10000 },
461
+ },
462
+ });
340
463
 
341
464
  for (const lead of response.data.data) {
342
- console.log(lead.id, lead.externalId, lead.email, lead.phone);
465
+ console.log(lead.id, lead.externalId, lead.email, lead.phone, lead.customFields);
343
466
  }
344
467
  ```
345
468
 
@@ -353,7 +476,53 @@ Required scope: `leads:read`.
353
476
 
354
477
  ```ts
355
478
  const response = await vuevox.leads.get("lead-id");
356
- console.log(response.data.externalId, response.data.email, response.data.phone);
479
+ console.log(response.data.data.externalId, response.data.data.email, response.data.data.phone, response.data.data.customFields);
480
+ ```
481
+
482
+ Returns: `Promise<VueVoxApiResponse<LeadDetailResponse>>`.
483
+
484
+ ### `vuevox.leads.update(leadId, input)`
485
+
486
+ Updates a lead and/or its custom fields.
487
+
488
+ Required scope: `leads:write`.
489
+
490
+ Input: `LeadUpdateRequest`
491
+
492
+ ```ts
493
+ const response = await vuevox.leads.update("lead-id", {
494
+ email: "ada@example.com",
495
+ customFields: {
496
+ crm_stage: "qualified",
497
+ renewal_date: "2026-09-01",
498
+ },
499
+ });
500
+
501
+ console.log(response.data.data.customFields);
502
+ ```
503
+
504
+ Returns: `Promise<VueVoxApiResponse<LeadDetailResponse>>`.
505
+
506
+ ### `vuevox.leads.upsertByExternalId(externalId, input)`
507
+
508
+ Creates or updates a lead by the integrating CRM/system ID. This is the preferred write method for CRM integrations because callers can use their own stable lead ID.
509
+
510
+ Required scope: `leads:write`.
511
+
512
+ Input: `LeadUpsertRequest`
513
+
514
+ ```ts
515
+ const response = await vuevox.leads.upsertByExternalId("hubspot_123", {
516
+ firstName: "Ada",
517
+ lastName: "Lovelace",
518
+ email: "ada@example.com",
519
+ customFields: {
520
+ crm_stage: "qualified",
521
+ deal_value: 12000,
522
+ },
523
+ });
524
+
525
+ console.log(response.data.data.id, response.data.data.customFields);
357
526
  ```
358
527
 
359
528
  Returns: `Promise<VueVoxApiResponse<LeadDetailResponse>>`.
@@ -374,6 +543,64 @@ for await (const lead of vuevox.leads.paginate({ createdAfter: "2026-01-01T00:00
374
543
 
375
544
  Returns: `AsyncGenerator<Lead>`.
376
545
 
546
+ ### `vuevox.leadCustomFields.list(options?)`
547
+
548
+ Lists organization lead custom field definitions.
549
+
550
+ Required scope: `leads:read`.
551
+
552
+ Options: `ListLeadCustomFieldsOptions`
553
+
554
+ | Option | Type | Description |
555
+ | --- | --- | --- |
556
+ | `includeArchived` | `boolean` | Include archived definitions. Defaults to `false`. |
557
+
558
+ ```ts
559
+ const response = await vuevox.leadCustomFields.list();
560
+ console.log(response.data.data);
561
+ ```
562
+
563
+ Returns: `Promise<VueVoxApiResponse<LeadCustomFieldsListResponse>>`.
564
+
565
+ ### `vuevox.leadCustomFields.create(input)`
566
+
567
+ Creates a lead custom field definition. Supported types are `text`, `number`, `boolean`, `date`, `datetime`, `select`, and `multi_select`.
568
+
569
+ Required scope: `lead_custom_fields:manage`.
570
+
571
+ Input: `LeadCustomFieldCreateRequest`
572
+
573
+ ```ts
574
+ const response = await vuevox.leadCustomFields.create({
575
+ key: "crm_stage",
576
+ label: "CRM Stage",
577
+ type: "select",
578
+ options: ["new", "qualified", "customer"],
579
+ isFilterable: true,
580
+ });
581
+
582
+ console.log(response.data.data.key);
583
+ ```
584
+
585
+ Returns: `Promise<VueVoxApiResponse<LeadCustomFieldResponse>>`.
586
+
587
+ ### `vuevox.leadCustomFields.update(key, input)`
588
+
589
+ Updates mutable metadata for a lead custom field definition. Field keys and types are immutable.
590
+
591
+ Required scope: `lead_custom_fields:manage`.
592
+
593
+ Input: `LeadCustomFieldUpdateRequest`
594
+
595
+ ```ts
596
+ await vuevox.leadCustomFields.update("crm_stage", {
597
+ label: "CRM Pipeline Stage",
598
+ archived: false,
599
+ });
600
+ ```
601
+
602
+ Returns: `Promise<VueVoxApiResponse<LeadCustomFieldResponse>>`.
603
+
377
604
  ## Lower-Level Calls
378
605
 
379
606
  For advanced integrations, `raw` exposes a typed lower-level OpenAPI client. You must attach authorization yourself.
@@ -428,7 +655,17 @@ insufficient_scope
428
655
  rate_limited
429
656
  invalid_request
430
657
  call_not_found
658
+ call_external_id_conflict
659
+ analysis_already_queued
660
+ analysis_timeout
661
+ ai_config_missing
662
+ evaluation_grid_missing
663
+ audio_not_found
664
+ idempotency_key_conflict
665
+ idempotency_key_in_progress
431
666
  lead_not_found
667
+ custom_field_not_found
668
+ custom_field_conflict
432
669
  ```
433
670
 
434
671
  ## Retries
@@ -483,23 +720,37 @@ import type {
483
720
  Agent,
484
721
  AgentsListResponse,
485
722
  CallDetailResponse,
723
+ CallResponse,
486
724
  CallsListResponse,
487
725
  CallSummary,
726
+ CallUploadMetadata,
727
+ CustomFieldFilters,
728
+ CustomFieldFilterValue,
488
729
  HelloResponse,
489
730
  Lead,
731
+ LeadCustomField,
732
+ LeadCustomFieldCreateRequest,
733
+ LeadCustomFieldResponse,
734
+ LeadCustomFieldUpdateRequest,
735
+ LeadCustomFieldsListResponse,
490
736
  LeadDetailResponse,
737
+ LeadUpdateRequest,
738
+ LeadUpsertRequest,
491
739
  LeadsListResponse,
492
740
  ListAgentsOptions,
493
741
  ListCallsOptions,
742
+ ListLeadCustomFieldsOptions,
494
743
  ListLeadsOptions,
495
744
  ListSpacesOptions,
496
745
  Space,
497
746
  SpacesListResponse,
747
+ UploadCallInput,
498
748
  VueVoxApiResponse,
499
749
  VueVoxClientOptions,
500
750
  VueVoxErrorResponse,
501
751
  VueVoxResponseEvent,
502
752
  VueVoxResponseMetadata,
753
+ WaitForAnalysisOptions,
503
754
  } from "@vuevox/sdk";
504
755
  ```
505
756
 
package/dist/client.d.ts CHANGED
@@ -1,15 +1,35 @@
1
1
  import type { components, paths } from "./generated/schema.js";
2
- type HelloResponse = components["schemas"]["HelloResponse"];
3
- type SpacesListResponse = components["schemas"]["SpacesListResponse"];
4
- type AgentsListResponse = components["schemas"]["AgentsListResponse"];
5
- type CallsListResponse = components["schemas"]["CallsListResponse"];
6
- type CallDetailResponse = components["schemas"]["CallDetailResponse"];
7
- type LeadsListResponse = components["schemas"]["LeadsListResponse"];
8
- type LeadDetailResponse = components["schemas"]["LeadDetailResponse"];
9
- type Space = components["schemas"]["Space"];
10
- type Agent = components["schemas"]["Agent"];
11
- type CallSummary = components["schemas"]["CallSummary"];
12
- type Lead = components["schemas"]["Lead"];
2
+ export type HelloResponse = components["schemas"]["HelloResponse"];
3
+ export type SpacesListResponse = components["schemas"]["SpacesListResponse"];
4
+ export type AgentsListResponse = components["schemas"]["AgentsListResponse"];
5
+ export type CallsListResponse = components["schemas"]["CallsListResponse"];
6
+ export type CallDetailResponse = components["schemas"]["CallDetailResponse"];
7
+ export type CallResponse = components["schemas"]["CallResponse"];
8
+ export type CallUploadMetadata = components["schemas"]["CallUploadMetadata"];
9
+ export type LeadsListResponse = components["schemas"]["LeadsListResponse"];
10
+ export type LeadDetailResponse = components["schemas"]["LeadDetailResponse"];
11
+ export type LeadCustomFieldsListResponse = components["schemas"]["LeadCustomFieldsListResponse"];
12
+ export type LeadCustomFieldResponse = components["schemas"]["LeadCustomFieldResponse"];
13
+ export type LeadCustomFieldCreateRequest = components["schemas"]["LeadCustomFieldCreateRequest"];
14
+ export type LeadCustomFieldUpdateRequest = components["schemas"]["LeadCustomFieldUpdateRequest"];
15
+ export type LeadUpsertRequest = components["schemas"]["LeadUpsertRequest"];
16
+ export type LeadUpdateRequest = components["schemas"]["LeadUpdateRequest"];
17
+ export type Space = components["schemas"]["Space"];
18
+ export type Agent = components["schemas"]["Agent"];
19
+ export type CallSummary = components["schemas"]["CallSummary"];
20
+ export type Lead = components["schemas"]["Lead"];
21
+ export type LeadCustomField = components["schemas"]["LeadCustomField"];
22
+ export type CustomFieldFilterValue = string | number | boolean | {
23
+ eq?: string | number | boolean;
24
+ gt?: string | number;
25
+ gte?: string | number;
26
+ lt?: string | number;
27
+ lte?: string | number;
28
+ before?: string;
29
+ after?: string;
30
+ contains?: string;
31
+ };
32
+ export type CustomFieldFilters = Record<string, CustomFieldFilterValue>;
13
33
  export interface ListSpacesOptions {
14
34
  limit?: number;
15
35
  cursor?: string;
@@ -20,6 +40,18 @@ export interface ListCallsOptions extends ListSpacesOptions {
20
40
  agentId?: string;
21
41
  createdAfter?: string;
22
42
  createdBefore?: string;
43
+ leadCustomFields?: CustomFieldFilters;
44
+ }
45
+ export interface UploadCallInput extends CallUploadMetadata {
46
+ idempotencyKey: string;
47
+ audio: {
48
+ file: Blob;
49
+ filename?: string;
50
+ };
51
+ }
52
+ export interface WaitForAnalysisOptions {
53
+ intervalMs?: number;
54
+ timeoutMs?: number;
23
55
  }
24
56
  export interface ListAgentsOptions extends ListSpacesOptions {
25
57
  spaceId?: string;
@@ -28,6 +60,10 @@ export interface ListLeadsOptions extends ListSpacesOptions {
28
60
  spaceId?: string;
29
61
  createdAfter?: string;
30
62
  createdBefore?: string;
63
+ customFields?: CustomFieldFilters;
64
+ }
65
+ export interface ListLeadCustomFieldsOptions {
66
+ includeArchived?: boolean;
31
67
  }
32
68
  export interface VueVoxResponseMetadata {
33
69
  requestId?: string;
@@ -81,8 +117,12 @@ export declare function createVueVoxClient(options: VueVoxClientOptions): {
81
117
  calls: {
82
118
  list: (listOptions?: ListCallsOptions) => Promise<VueVoxApiResponse<CallsListResponse>>;
83
119
  get: (callId: string) => Promise<VueVoxApiResponse<CallDetailResponse>>;
120
+ upload: (input: UploadCallInput) => Promise<VueVoxApiResponse<CallResponse>>;
121
+ queueAnalysis: (callId: string) => Promise<VueVoxApiResponse<CallResponse>>;
122
+ waitForAnalysis: (callId: string, waitOptions?: WaitForAnalysisOptions) => Promise<VueVoxApiResponse<CallDetailResponse>>;
84
123
  paginate: (listOptions?: ListCallsOptions) => AsyncGenerator<{
85
124
  id: string;
125
+ externalId: string | null;
86
126
  space: components["schemas"]["ResourceSummary"];
87
127
  lead: components["schemas"]["LeadSummary"];
88
128
  agent: components["schemas"]["AgentSummary"];
@@ -98,6 +138,8 @@ export declare function createVueVoxClient(options: VueVoxClientOptions): {
98
138
  leads: {
99
139
  list: (listOptions?: ListLeadsOptions) => Promise<VueVoxApiResponse<LeadsListResponse>>;
100
140
  get: (leadId: string) => Promise<VueVoxApiResponse<LeadDetailResponse>>;
141
+ update: (leadId: string, input: LeadUpdateRequest) => Promise<VueVoxApiResponse<LeadDetailResponse>>;
142
+ upsertByExternalId: (externalId: string, input: LeadUpsertRequest) => Promise<VueVoxApiResponse<LeadDetailResponse>>;
101
143
  paginate: (listOptions?: ListLeadsOptions) => AsyncGenerator<{
102
144
  id: string;
103
145
  externalId: string | null;
@@ -105,11 +147,16 @@ export declare function createVueVoxClient(options: VueVoxClientOptions): {
105
147
  lastName: string;
106
148
  email: string | null;
107
149
  phone: string | null;
150
+ customFields: components["schemas"]["CustomFields"];
108
151
  space: components["schemas"]["ResourceSummary"];
109
152
  createdAt: string;
110
153
  updatedAt: string;
111
154
  }, any, any>;
112
155
  };
156
+ leadCustomFields: {
157
+ list: (listOptions?: ListLeadCustomFieldsOptions) => Promise<VueVoxApiResponse<LeadCustomFieldsListResponse>>;
158
+ create: (input: LeadCustomFieldCreateRequest) => Promise<VueVoxApiResponse<LeadCustomFieldResponse>>;
159
+ update: (key: string, input: LeadCustomFieldUpdateRequest) => Promise<VueVoxApiResponse<LeadCustomFieldResponse>>;
160
+ };
113
161
  raw: import("openapi-fetch").Client<paths, `${string}/${string}`>;
114
162
  };
115
- export type { Agent, AgentsListResponse, CallDetailResponse, CallsListResponse, CallSummary, HelloResponse, Lead, LeadDetailResponse, LeadsListResponse, Space, SpacesListResponse };
package/dist/client.js CHANGED
@@ -46,12 +46,55 @@ export function createVueVoxClient(options) {
46
46
  async function getCall(callId) {
47
47
  return apiGet(`/v1/calls/${encodeURIComponent(callId)}`);
48
48
  }
49
+ async function uploadCall(input) {
50
+ const { audio, idempotencyKey, ...metadata } = input;
51
+ const formData = new FormData();
52
+ formData.set("metadata", JSON.stringify(metadata));
53
+ formData.set("audioFile", audio.file, audio.filename ?? "call-audio");
54
+ return apiMultipart("POST", "/v1/calls", formData, {
55
+ "Idempotency-Key": idempotencyKey,
56
+ });
57
+ }
58
+ async function queueCallAnalysis(callId) {
59
+ return apiJson("POST", `/v1/calls/${encodeURIComponent(callId)}/analysis-jobs`, {});
60
+ }
61
+ async function waitForCallAnalysis(callId, waitOptions = {}) {
62
+ const intervalMs = waitOptions.intervalMs ?? 2_000;
63
+ const timeoutMs = waitOptions.timeoutMs ?? 120_000;
64
+ const startedAt = Date.now();
65
+ for (;;) {
66
+ const response = await getCall(callId);
67
+ const status = response.data.data.analysisStatus;
68
+ if (status === "completed" || status === "failed") {
69
+ return response;
70
+ }
71
+ if (Date.now() - startedAt >= timeoutMs) {
72
+ throw new VueVoxApiError(408, "analysis_timeout", "Timed out waiting for call analysis.", undefined, response.requestId);
73
+ }
74
+ await sleep(intervalMs);
75
+ }
76
+ }
49
77
  async function listLeads(listOptions = {}) {
50
78
  return apiGet("/v1/leads", listOptions);
51
79
  }
52
80
  async function getLead(leadId) {
53
81
  return apiGet(`/v1/leads/${encodeURIComponent(leadId)}`);
54
82
  }
83
+ async function updateLead(leadId, input) {
84
+ return apiJson("PATCH", `/v1/leads/${encodeURIComponent(leadId)}`, input);
85
+ }
86
+ async function upsertLeadByExternalId(externalId, input) {
87
+ return apiJson("PUT", `/v1/leads/by-external-id/${encodeURIComponent(externalId)}`, input);
88
+ }
89
+ async function listLeadCustomFields(listOptions = {}) {
90
+ return apiGet("/v1/lead-custom-fields", listOptions);
91
+ }
92
+ async function createLeadCustomField(input) {
93
+ return apiJson("POST", "/v1/lead-custom-fields", input);
94
+ }
95
+ async function updateLeadCustomField(key, input) {
96
+ return apiJson("PATCH", `/v1/lead-custom-fields/${encodeURIComponent(key)}`, input);
97
+ }
55
98
  async function apiGet(path, query) {
56
99
  const accessToken = await getAccessToken();
57
100
  const result = await requestJson("GET", path, {
@@ -63,6 +106,30 @@ export function createVueVoxClient(options) {
63
106
  });
64
107
  return withMetadata(result.data, result.response, result.requestId);
65
108
  }
109
+ async function apiJson(method, path, body) {
110
+ const accessToken = await getAccessToken();
111
+ const result = await requestJson(method, path, {
112
+ method,
113
+ headers: {
114
+ Authorization: `Bearer ${accessToken}`,
115
+ "Content-Type": "application/json",
116
+ },
117
+ body: JSON.stringify(body),
118
+ });
119
+ return withMetadata(result.data, result.response, result.requestId);
120
+ }
121
+ async function apiMultipart(method, path, body, headers) {
122
+ const accessToken = await getAccessToken();
123
+ const result = await requestJson(method, path, {
124
+ method,
125
+ headers: {
126
+ Authorization: `Bearer ${accessToken}`,
127
+ ...headers,
128
+ },
129
+ body,
130
+ });
131
+ return withMetadata(result.data, result.response, result.requestId);
132
+ }
66
133
  async function requestJson(method, path, init) {
67
134
  for (let attempt = 0;; attempt++) {
68
135
  const response = await fetchFn(buildUrl(baseUrl, path, init.query), init);
@@ -76,7 +143,7 @@ export function createVueVoxClient(options) {
76
143
  }
77
144
  return { data: body, requestId, response };
78
145
  }
79
- if (attempt < retries && shouldRetry(response.status)) {
146
+ if (attempt < retries && (method === "GET" || path === "/oauth/token") && shouldRetry(response.status)) {
80
147
  await sleep(retryDelayMs(attempt, retryAfter));
81
148
  continue;
82
149
  }
@@ -106,13 +173,23 @@ export function createVueVoxClient(options) {
106
173
  calls: {
107
174
  list: listCalls,
108
175
  get: getCall,
176
+ upload: uploadCall,
177
+ queueAnalysis: queueCallAnalysis,
178
+ waitForAnalysis: waitForCallAnalysis,
109
179
  paginate: (listOptions = {}) => paginate(listCalls, listOptions),
110
180
  },
111
181
  leads: {
112
182
  list: listLeads,
113
183
  get: getLead,
184
+ update: updateLead,
185
+ upsertByExternalId: upsertLeadByExternalId,
114
186
  paginate: (listOptions = {}) => paginate(listLeads, listOptions),
115
187
  },
188
+ leadCustomFields: {
189
+ list: listLeadCustomFields,
190
+ create: createLeadCustomField,
191
+ update: updateLeadCustomField,
192
+ },
116
193
  raw,
117
194
  };
118
195
  }
@@ -127,12 +204,27 @@ function trimTrailingSlash(value) {
127
204
  }
128
205
  function buildUrl(baseUrl, path, query) {
129
206
  const url = new URL(`${baseUrl}${path}`);
130
- for (const [key, value] of Object.entries(query ?? {})) {
131
- if ((typeof value === "string" || typeof value === "number") && value !== "") {
132
- url.searchParams.set(key, String(value));
207
+ appendQueryParams(url.searchParams, query ?? {});
208
+ return url.toString();
209
+ }
210
+ function appendQueryParams(searchParams, query, prefix) {
211
+ for (const [rawKey, value] of Object.entries(query)) {
212
+ if (value === undefined || value === null || value === "") {
213
+ continue;
214
+ }
215
+ const key = queryKey(rawKey, prefix);
216
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
217
+ searchParams.set(key, String(value));
218
+ continue;
219
+ }
220
+ if (typeof value === "object" && !Array.isArray(value)) {
221
+ appendQueryParams(searchParams, value, key);
133
222
  }
134
223
  }
135
- return url.toString();
224
+ }
225
+ function queryKey(key, prefix) {
226
+ const publicKey = key === "customFields" ? "custom" : key === "leadCustomFields" ? "leadCustom" : key;
227
+ return prefix ? `${prefix}[${publicKey}]` : publicKey;
136
228
  }
137
229
  async function parseJson(response) {
138
230
  try {
@@ -97,7 +97,11 @@ export interface paths {
97
97
  */
98
98
  get: operations["listCalls"];
99
99
  put?: never;
100
- post?: never;
100
+ /**
101
+ * Upload a call and optionally queue analysis
102
+ * @description Uploads a call recording, upserts the agent and lead by externalId, creates the call in an existing platform-managed space, and optionally queues analysis. Requires an Idempotency-Key header for safe retries. The audio size limit is configured by a VueVox superadmin and defaults to 20 MB.
103
+ */
104
+ post: operations["uploadCall"];
101
105
  delete?: never;
102
106
  options?: never;
103
107
  head?: never;
@@ -124,6 +128,26 @@ export interface paths {
124
128
  patch?: never;
125
129
  trace?: never;
126
130
  };
131
+ "/v1/calls/{callId}/analysis-jobs": {
132
+ parameters: {
133
+ query?: never;
134
+ header?: never;
135
+ path?: never;
136
+ cookie?: never;
137
+ };
138
+ get?: never;
139
+ put?: never;
140
+ /**
141
+ * Queue analysis for a call
142
+ * @description Queues analysis for a previously uploaded organization call. Use this when a call was uploaded with queueAnalysis set to false.
143
+ */
144
+ post: operations["queueCallAnalysis"];
145
+ delete?: never;
146
+ options?: never;
147
+ head?: never;
148
+ patch?: never;
149
+ trace?: never;
150
+ };
127
151
  "/v1/leads": {
128
152
  parameters: {
129
153
  query?: never;
@@ -161,9 +185,77 @@ export interface paths {
161
185
  delete?: never;
162
186
  options?: never;
163
187
  head?: never;
188
+ /**
189
+ * Update a lead
190
+ * @description Updates an organization-scoped lead and its custom fields.
191
+ */
192
+ patch: operations["updateLead"];
193
+ trace?: never;
194
+ };
195
+ "/v1/leads/by-external-id/{externalId}": {
196
+ parameters: {
197
+ query?: never;
198
+ header?: never;
199
+ path?: never;
200
+ cookie?: never;
201
+ };
202
+ get?: never;
203
+ /**
204
+ * Upsert a lead by external ID
205
+ * @description Creates or updates a lead identified by the CRM/system external ID.
206
+ */
207
+ put: operations["upsertLeadByExternalId"];
208
+ post?: never;
209
+ delete?: never;
210
+ options?: never;
211
+ head?: never;
212
+ patch?: never;
213
+ trace?: never;
214
+ };
215
+ "/v1/lead-custom-fields": {
216
+ parameters: {
217
+ query?: never;
218
+ header?: never;
219
+ path?: never;
220
+ cookie?: never;
221
+ };
222
+ /**
223
+ * List lead custom field definitions
224
+ * @description Returns lead custom field definitions for the API client's organization.
225
+ */
226
+ get: operations["listLeadCustomFields"];
227
+ put?: never;
228
+ /**
229
+ * Create a lead custom field definition
230
+ * @description Creates a typed lead custom field definition for CRM integrations and platform filters.
231
+ */
232
+ post: operations["createLeadCustomField"];
233
+ delete?: never;
234
+ options?: never;
235
+ head?: never;
164
236
  patch?: never;
165
237
  trace?: never;
166
238
  };
239
+ "/v1/lead-custom-fields/{key}": {
240
+ parameters: {
241
+ query?: never;
242
+ header?: never;
243
+ path?: never;
244
+ cookie?: never;
245
+ };
246
+ get?: never;
247
+ put?: never;
248
+ post?: never;
249
+ delete?: never;
250
+ options?: never;
251
+ head?: never;
252
+ /**
253
+ * Update a lead custom field definition
254
+ * @description Updates mutable metadata for a lead custom field definition. Keys and types are immutable.
255
+ */
256
+ patch: operations["updateLeadCustomField"];
257
+ trace?: never;
258
+ };
167
259
  }
168
260
  export type webhooks = Record<string, never>;
169
261
  export interface components {
@@ -175,7 +267,7 @@ export interface components {
175
267
  client_secret: string;
176
268
  /**
177
269
  * @description Space-separated scopes requested for the access token.
178
- * @example hello:read spaces:read agents:read calls:read leads:read
270
+ * @example hello:read spaces:read agents:read calls:read calls:write leads:read leads:write lead_custom_fields:manage
179
271
  */
180
272
  scope?: string;
181
273
  };
@@ -185,7 +277,7 @@ export interface components {
185
277
  token_type: "Bearer";
186
278
  /** @example 3600 */
187
279
  expires_in: number;
188
- /** @example hello:read spaces:read agents:read calls:read leads:read */
280
+ /** @example hello:read spaces:read agents:read calls:read calls:write leads:read leads:write lead_custom_fields:manage */
189
281
  scope: string;
190
282
  };
191
283
  HelloResponse: {
@@ -237,6 +329,7 @@ export interface components {
237
329
  externalId: string | null;
238
330
  firstName: string;
239
331
  lastName: string;
332
+ customFields: components["schemas"]["CustomFields"];
240
333
  } | null;
241
334
  AgentSummary: {
242
335
  /** Format: uuid */
@@ -248,6 +341,8 @@ export interface components {
248
341
  CallSummary: {
249
342
  /** Format: uuid */
250
343
  id: string;
344
+ /** @description Optional ID from an external system. */
345
+ externalId: string | null;
251
346
  space: components["schemas"]["ResourceSummary"];
252
347
  lead: components["schemas"]["LeadSummary"];
253
348
  agent: components["schemas"]["AgentSummary"];
@@ -288,6 +383,44 @@ export interface components {
288
383
  CallDetailResponse: {
289
384
  data: components["schemas"]["CallDetail"];
290
385
  };
386
+ CallResponse: {
387
+ data: components["schemas"]["CallSummary"];
388
+ };
389
+ CallUploadMetadata: {
390
+ /** @description Optional call ID from your system. Must be unique within the organization when provided. */
391
+ externalId?: string | null;
392
+ /**
393
+ * Format: uuid
394
+ * @description Existing VueVox space ID. Spaces are managed in the VueVox platform.
395
+ */
396
+ spaceId: string;
397
+ /**
398
+ * @description When true or omitted, queues analysis immediately after upload. When false, queue later with queueCallAnalysis.
399
+ * @default true
400
+ */
401
+ queueAnalysis: boolean;
402
+ agent: components["schemas"]["CallUploadAgent"];
403
+ lead: components["schemas"]["CallUploadLead"];
404
+ };
405
+ CallUploadAgent: {
406
+ externalId: string;
407
+ /** @description Required when creating a new agent. */
408
+ name?: string;
409
+ /** Format: email */
410
+ email?: string | null;
411
+ phone?: string | null;
412
+ };
413
+ CallUploadLead: {
414
+ externalId: string;
415
+ /** @description Required when creating a new lead. */
416
+ firstName?: string;
417
+ /** @description Required when creating a new lead. */
418
+ lastName?: string;
419
+ /** Format: email */
420
+ email?: string | null;
421
+ phone?: string | null;
422
+ customFields?: components["schemas"]["CustomFields"];
423
+ };
291
424
  Lead: {
292
425
  /** Format: uuid */
293
426
  id: string;
@@ -298,6 +431,7 @@ export interface components {
298
431
  /** Format: email */
299
432
  email: string | null;
300
433
  phone: string | null;
434
+ customFields: components["schemas"]["CustomFields"];
301
435
  space: components["schemas"]["ResourceSummary"];
302
436
  /** Format: date-time */
303
437
  createdAt: string;
@@ -311,6 +445,72 @@ export interface components {
311
445
  LeadDetailResponse: {
312
446
  data: components["schemas"]["Lead"];
313
447
  };
448
+ LeadUpsertRequest: {
449
+ firstName: string;
450
+ lastName: string;
451
+ /** Format: email */
452
+ email?: string | null;
453
+ phone?: string | null;
454
+ /** Format: uuid */
455
+ spaceId?: string | null;
456
+ customFields?: components["schemas"]["CustomFields"];
457
+ };
458
+ LeadUpdateRequest: {
459
+ firstName?: string;
460
+ lastName?: string;
461
+ /** Format: email */
462
+ email?: string | null;
463
+ phone?: string | null;
464
+ /** Format: uuid */
465
+ spaceId?: string | null;
466
+ customFields?: components["schemas"]["CustomFields"];
467
+ };
468
+ /** @description Lead custom field values keyed by custom field key. */
469
+ CustomFields: {
470
+ [key: string]: string | number | boolean | string[] | null;
471
+ };
472
+ /** @description Custom field filters keyed by custom field key. Scalar values use equality; objects specify one operator. */
473
+ CustomFieldFilters: {
474
+ [key: string]: string | number | boolean | {
475
+ [key: string]: string | number | boolean;
476
+ };
477
+ };
478
+ LeadCustomField: {
479
+ /** @example crm_stage */
480
+ key: string;
481
+ /** @example CRM Stage */
482
+ label: string;
483
+ /** @enum {string} */
484
+ type: "text" | "number" | "boolean" | "date" | "datetime" | "select" | "multi_select";
485
+ options: string[];
486
+ isFilterable: boolean;
487
+ archived: boolean;
488
+ /** Format: date-time */
489
+ createdAt: string;
490
+ /** Format: date-time */
491
+ updatedAt: string;
492
+ };
493
+ LeadCustomFieldsListResponse: {
494
+ data: components["schemas"]["LeadCustomField"][];
495
+ };
496
+ LeadCustomFieldResponse: {
497
+ data: components["schemas"]["LeadCustomField"];
498
+ };
499
+ LeadCustomFieldCreateRequest: {
500
+ key: string;
501
+ label: string;
502
+ /** @enum {string} */
503
+ type: "text" | "number" | "boolean" | "date" | "datetime" | "select" | "multi_select";
504
+ options?: string[];
505
+ /** @default true */
506
+ isFilterable: boolean;
507
+ };
508
+ LeadCustomFieldUpdateRequest: {
509
+ label?: string;
510
+ options?: string[];
511
+ isFilterable?: boolean;
512
+ archived?: boolean;
513
+ };
314
514
  CursorPagination: {
315
515
  /** @example 50 */
316
516
  limit: number;
@@ -593,6 +793,8 @@ export interface operations {
593
793
  createdAfter?: string;
594
794
  /** @description Return calls created at or before this timestamp. */
595
795
  createdBefore?: string;
796
+ /** @description Filter calls by lead custom fields. Use equality by default, or one operator such as gte, lte, contains, before, or after. */
797
+ leadCustom?: components["schemas"]["CustomFieldFilters"];
596
798
  };
597
799
  header?: never;
598
800
  path?: never;
@@ -651,6 +853,77 @@ export interface operations {
651
853
  };
652
854
  };
653
855
  };
856
+ uploadCall: {
857
+ parameters: {
858
+ query?: never;
859
+ header: {
860
+ /** @description Unique key for this upload attempt. Reusing the same key with the same request returns the original response; reusing it with a different request returns a conflict. */
861
+ "Idempotency-Key": string;
862
+ };
863
+ path?: never;
864
+ cookie?: never;
865
+ };
866
+ requestBody: {
867
+ content: {
868
+ "multipart/form-data": {
869
+ /** @description JSON string matching CallUploadMetadata. */
870
+ metadata: string;
871
+ /**
872
+ * Format: binary
873
+ * @description Audio file. Supported extensions include wav, mp3, aac, m4a, amr, mpeg, mpga, x-wav, ogg, oga, mp4, and mp4a.
874
+ */
875
+ audioFile: string;
876
+ };
877
+ };
878
+ };
879
+ responses: {
880
+ /** @description Call uploaded. Analysis is queued when metadata.queueAnalysis is true. */
881
+ 201: {
882
+ headers: {
883
+ [name: string]: unknown;
884
+ };
885
+ content: {
886
+ "application/json": components["schemas"]["CallResponse"];
887
+ };
888
+ };
889
+ /** @description Bearer token is missing, invalid, or expired. */
890
+ 401: {
891
+ headers: {
892
+ [name: string]: unknown;
893
+ };
894
+ content: {
895
+ "application/json": components["schemas"]["ErrorResponse"];
896
+ };
897
+ };
898
+ /** @description Bearer token does not include the required scope. */
899
+ 403: {
900
+ headers: {
901
+ [name: string]: unknown;
902
+ };
903
+ content: {
904
+ "application/json": components["schemas"]["ErrorResponse"];
905
+ };
906
+ };
907
+ /** @description Idempotency key conflict, external call ID conflict, or analysis already queued. */
908
+ 409: {
909
+ headers: {
910
+ [name: string]: unknown;
911
+ };
912
+ content: {
913
+ "application/json": components["schemas"]["ErrorResponse"];
914
+ };
915
+ };
916
+ /** @description Multipart upload or metadata failed validation. */
917
+ 422: {
918
+ headers: {
919
+ [name: string]: unknown;
920
+ };
921
+ content: {
922
+ "application/json": components["schemas"]["ErrorResponse"];
923
+ };
924
+ };
925
+ };
926
+ };
654
927
  getCall: {
655
928
  parameters: {
656
929
  query?: never;
@@ -714,6 +987,74 @@ export interface operations {
714
987
  };
715
988
  };
716
989
  };
990
+ queueCallAnalysis: {
991
+ parameters: {
992
+ query?: never;
993
+ header?: never;
994
+ path: {
995
+ /** @description Call ID. */
996
+ callId: string;
997
+ };
998
+ cookie?: never;
999
+ };
1000
+ requestBody?: never;
1001
+ responses: {
1002
+ /** @description Analysis queued. */
1003
+ 200: {
1004
+ headers: {
1005
+ [name: string]: unknown;
1006
+ };
1007
+ content: {
1008
+ "application/json": components["schemas"]["CallResponse"];
1009
+ };
1010
+ };
1011
+ /** @description Bearer token is missing, invalid, or expired. */
1012
+ 401: {
1013
+ headers: {
1014
+ [name: string]: unknown;
1015
+ };
1016
+ content: {
1017
+ "application/json": components["schemas"]["ErrorResponse"];
1018
+ };
1019
+ };
1020
+ /** @description Bearer token does not include the required scope. */
1021
+ 403: {
1022
+ headers: {
1023
+ [name: string]: unknown;
1024
+ };
1025
+ content: {
1026
+ "application/json": components["schemas"]["ErrorResponse"];
1027
+ };
1028
+ };
1029
+ /** @description Call was not found in the API client's organization. */
1030
+ 404: {
1031
+ headers: {
1032
+ [name: string]: unknown;
1033
+ };
1034
+ content: {
1035
+ "application/json": components["schemas"]["ErrorResponse"];
1036
+ };
1037
+ };
1038
+ /** @description Analysis is already queued or processing. */
1039
+ 409: {
1040
+ headers: {
1041
+ [name: string]: unknown;
1042
+ };
1043
+ content: {
1044
+ "application/json": components["schemas"]["ErrorResponse"];
1045
+ };
1046
+ };
1047
+ /** @description Organization AI settings, evaluation grid, or audio file is missing. */
1048
+ 422: {
1049
+ headers: {
1050
+ [name: string]: unknown;
1051
+ };
1052
+ content: {
1053
+ "application/json": components["schemas"]["ErrorResponse"];
1054
+ };
1055
+ };
1056
+ };
1057
+ };
717
1058
  listLeads: {
718
1059
  parameters: {
719
1060
  query?: {
@@ -727,6 +1068,8 @@ export interface operations {
727
1068
  createdAfter?: string;
728
1069
  /** @description Return leads created at or before this timestamp. */
729
1070
  createdBefore?: string;
1071
+ /** @description Filter leads by custom fields. Use equality by default, or one operator such as gte, lte, contains, before, or after. */
1072
+ custom?: components["schemas"]["CustomFieldFilters"];
730
1073
  };
731
1074
  header?: never;
732
1075
  path?: never;
@@ -848,4 +1191,294 @@ export interface operations {
848
1191
  };
849
1192
  };
850
1193
  };
1194
+ updateLead: {
1195
+ parameters: {
1196
+ query?: never;
1197
+ header?: never;
1198
+ path: {
1199
+ /** @description Lead ID. */
1200
+ leadId: string;
1201
+ };
1202
+ cookie?: never;
1203
+ };
1204
+ requestBody: {
1205
+ content: {
1206
+ "application/json": components["schemas"]["LeadUpdateRequest"];
1207
+ };
1208
+ };
1209
+ responses: {
1210
+ /** @description Lead updated. */
1211
+ 200: {
1212
+ headers: {
1213
+ [name: string]: unknown;
1214
+ };
1215
+ content: {
1216
+ "application/json": components["schemas"]["LeadDetailResponse"];
1217
+ };
1218
+ };
1219
+ /** @description Bearer token is missing, invalid, or expired. */
1220
+ 401: {
1221
+ headers: {
1222
+ [name: string]: unknown;
1223
+ };
1224
+ content: {
1225
+ "application/json": components["schemas"]["ErrorResponse"];
1226
+ };
1227
+ };
1228
+ /** @description Bearer token does not include the required scope. */
1229
+ 403: {
1230
+ headers: {
1231
+ [name: string]: unknown;
1232
+ };
1233
+ content: {
1234
+ "application/json": components["schemas"]["ErrorResponse"];
1235
+ };
1236
+ };
1237
+ /** @description Lead was not found in the API client's organization. */
1238
+ 404: {
1239
+ headers: {
1240
+ [name: string]: unknown;
1241
+ };
1242
+ content: {
1243
+ "application/json": components["schemas"]["ErrorResponse"];
1244
+ };
1245
+ };
1246
+ /** @description Request body failed validation. */
1247
+ 422: {
1248
+ headers: {
1249
+ [name: string]: unknown;
1250
+ };
1251
+ content: {
1252
+ "application/json": components["schemas"]["ErrorResponse"];
1253
+ };
1254
+ };
1255
+ };
1256
+ };
1257
+ upsertLeadByExternalId: {
1258
+ parameters: {
1259
+ query?: never;
1260
+ header?: never;
1261
+ path: {
1262
+ /** @description External lead ID from the integrating system. */
1263
+ externalId: string;
1264
+ };
1265
+ cookie?: never;
1266
+ };
1267
+ requestBody: {
1268
+ content: {
1269
+ "application/json": components["schemas"]["LeadUpsertRequest"];
1270
+ };
1271
+ };
1272
+ responses: {
1273
+ /** @description Existing lead updated. */
1274
+ 200: {
1275
+ headers: {
1276
+ [name: string]: unknown;
1277
+ };
1278
+ content: {
1279
+ "application/json": components["schemas"]["LeadDetailResponse"];
1280
+ };
1281
+ };
1282
+ /** @description New lead created. */
1283
+ 201: {
1284
+ headers: {
1285
+ [name: string]: unknown;
1286
+ };
1287
+ content: {
1288
+ "application/json": components["schemas"]["LeadDetailResponse"];
1289
+ };
1290
+ };
1291
+ /** @description Bearer token is missing, invalid, or expired. */
1292
+ 401: {
1293
+ headers: {
1294
+ [name: string]: unknown;
1295
+ };
1296
+ content: {
1297
+ "application/json": components["schemas"]["ErrorResponse"];
1298
+ };
1299
+ };
1300
+ /** @description Bearer token does not include the required scope. */
1301
+ 403: {
1302
+ headers: {
1303
+ [name: string]: unknown;
1304
+ };
1305
+ content: {
1306
+ "application/json": components["schemas"]["ErrorResponse"];
1307
+ };
1308
+ };
1309
+ /** @description Request body failed validation. */
1310
+ 422: {
1311
+ headers: {
1312
+ [name: string]: unknown;
1313
+ };
1314
+ content: {
1315
+ "application/json": components["schemas"]["ErrorResponse"];
1316
+ };
1317
+ };
1318
+ };
1319
+ };
1320
+ listLeadCustomFields: {
1321
+ parameters: {
1322
+ query?: {
1323
+ /** @description Include archived field definitions. */
1324
+ includeArchived?: boolean;
1325
+ };
1326
+ header?: never;
1327
+ path?: never;
1328
+ cookie?: never;
1329
+ };
1330
+ requestBody?: never;
1331
+ responses: {
1332
+ /** @description Lead custom field definitions. */
1333
+ 200: {
1334
+ headers: {
1335
+ [name: string]: unknown;
1336
+ };
1337
+ content: {
1338
+ "application/json": components["schemas"]["LeadCustomFieldsListResponse"];
1339
+ };
1340
+ };
1341
+ /** @description Bearer token is missing, invalid, or expired. */
1342
+ 401: {
1343
+ headers: {
1344
+ [name: string]: unknown;
1345
+ };
1346
+ content: {
1347
+ "application/json": components["schemas"]["ErrorResponse"];
1348
+ };
1349
+ };
1350
+ /** @description Bearer token does not include the required scope. */
1351
+ 403: {
1352
+ headers: {
1353
+ [name: string]: unknown;
1354
+ };
1355
+ content: {
1356
+ "application/json": components["schemas"]["ErrorResponse"];
1357
+ };
1358
+ };
1359
+ };
1360
+ };
1361
+ createLeadCustomField: {
1362
+ parameters: {
1363
+ query?: never;
1364
+ header?: never;
1365
+ path?: never;
1366
+ cookie?: never;
1367
+ };
1368
+ requestBody: {
1369
+ content: {
1370
+ "application/json": components["schemas"]["LeadCustomFieldCreateRequest"];
1371
+ };
1372
+ };
1373
+ responses: {
1374
+ /** @description Lead custom field created. */
1375
+ 201: {
1376
+ headers: {
1377
+ [name: string]: unknown;
1378
+ };
1379
+ content: {
1380
+ "application/json": components["schemas"]["LeadCustomFieldResponse"];
1381
+ };
1382
+ };
1383
+ /** @description Bearer token is missing, invalid, or expired. */
1384
+ 401: {
1385
+ headers: {
1386
+ [name: string]: unknown;
1387
+ };
1388
+ content: {
1389
+ "application/json": components["schemas"]["ErrorResponse"];
1390
+ };
1391
+ };
1392
+ /** @description Bearer token does not include the required scope. */
1393
+ 403: {
1394
+ headers: {
1395
+ [name: string]: unknown;
1396
+ };
1397
+ content: {
1398
+ "application/json": components["schemas"]["ErrorResponse"];
1399
+ };
1400
+ };
1401
+ /** @description A custom field with this key already exists. */
1402
+ 409: {
1403
+ headers: {
1404
+ [name: string]: unknown;
1405
+ };
1406
+ content: {
1407
+ "application/json": components["schemas"]["ErrorResponse"];
1408
+ };
1409
+ };
1410
+ /** @description Request body failed validation. */
1411
+ 422: {
1412
+ headers: {
1413
+ [name: string]: unknown;
1414
+ };
1415
+ content: {
1416
+ "application/json": components["schemas"]["ErrorResponse"];
1417
+ };
1418
+ };
1419
+ };
1420
+ };
1421
+ updateLeadCustomField: {
1422
+ parameters: {
1423
+ query?: never;
1424
+ header?: never;
1425
+ path: {
1426
+ /** @description Custom field key. */
1427
+ key: string;
1428
+ };
1429
+ cookie?: never;
1430
+ };
1431
+ requestBody: {
1432
+ content: {
1433
+ "application/json": components["schemas"]["LeadCustomFieldUpdateRequest"];
1434
+ };
1435
+ };
1436
+ responses: {
1437
+ /** @description Lead custom field updated. */
1438
+ 200: {
1439
+ headers: {
1440
+ [name: string]: unknown;
1441
+ };
1442
+ content: {
1443
+ "application/json": components["schemas"]["LeadCustomFieldResponse"];
1444
+ };
1445
+ };
1446
+ /** @description Bearer token is missing, invalid, or expired. */
1447
+ 401: {
1448
+ headers: {
1449
+ [name: string]: unknown;
1450
+ };
1451
+ content: {
1452
+ "application/json": components["schemas"]["ErrorResponse"];
1453
+ };
1454
+ };
1455
+ /** @description Bearer token does not include the required scope. */
1456
+ 403: {
1457
+ headers: {
1458
+ [name: string]: unknown;
1459
+ };
1460
+ content: {
1461
+ "application/json": components["schemas"]["ErrorResponse"];
1462
+ };
1463
+ };
1464
+ /** @description Custom field was not found in the API client's organization. */
1465
+ 404: {
1466
+ headers: {
1467
+ [name: string]: unknown;
1468
+ };
1469
+ content: {
1470
+ "application/json": components["schemas"]["ErrorResponse"];
1471
+ };
1472
+ };
1473
+ /** @description Request body failed validation. */
1474
+ 422: {
1475
+ headers: {
1476
+ [name: string]: unknown;
1477
+ };
1478
+ content: {
1479
+ "application/json": components["schemas"]["ErrorResponse"];
1480
+ };
1481
+ };
1482
+ };
1483
+ };
851
1484
  }
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  export { createVueVoxClient } from "./client.js";
2
- export type { Agent, AgentsListResponse, CallDetailResponse, CallsListResponse, CallSummary, HelloResponse, Lead, LeadDetailResponse, LeadsListResponse, ListAgentsOptions, ListCallsOptions, ListLeadsOptions, ListSpacesOptions, Space, SpacesListResponse, VueVoxApiResponse, VueVoxClientOptions, VueVoxResponseEvent, VueVoxResponseMetadata, } from "./client.js";
2
+ export type { Agent, AgentsListResponse, CallDetailResponse, CallResponse, CallsListResponse, CallSummary, CallUploadMetadata, CustomFieldFilters, CustomFieldFilterValue, HelloResponse, Lead, LeadCustomField, LeadCustomFieldCreateRequest, LeadCustomFieldResponse, LeadCustomFieldUpdateRequest, LeadCustomFieldsListResponse, LeadDetailResponse, LeadUpdateRequest, LeadUpsertRequest, LeadsListResponse, ListAgentsOptions, ListCallsOptions, ListLeadCustomFieldsOptions, ListLeadsOptions, ListSpacesOptions, Space, SpacesListResponse, UploadCallInput, VueVoxApiResponse, VueVoxClientOptions, VueVoxResponseEvent, VueVoxResponseMetadata, WaitForAnalysisOptions, } from "./client.js";
3
3
  export { VueVoxApiError } from "./errors.js";
4
4
  export type { VueVoxErrorResponse } from "./errors.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vuevox/sdk",
3
- "version": "0.6.0",
3
+ "version": "0.8.0",
4
4
  "description": "TypeScript SDK for the VueVox Developer API.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",