@openpets/quo 1.0.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.
@@ -0,0 +1,2079 @@
1
+ /**
2
+ * Auto-generated OpenAPI tools
3
+ *
4
+ * Source: https://openphone-public-api-prod.s3.us-west-2.amazonaws.com/public/openphone-public-api-v1-prod.json
5
+ * API: OpenPhone Public API v1.0.0
6
+ *
7
+ * This file contains tool definitions that import client utilities from ./openapi-client.ts.
8
+ * Custom tools can also import { getBaseUrl, getAuthHeaders, fetchAPI } from "./openapi-client".
9
+ *
10
+ * Tools by category:
11
+ * Calls: 6 tools (CORE)
12
+ * Contact Custom Fields: 1 tools (CORE)
13
+ * Contacts: 5 tools (CORE)
14
+ * Conversations: 1 tools (CORE)
15
+ * Messages: 3 tools (CORE)
16
+ * Phone Numbers: 2 tools (CORE)
17
+ * Users: 2 tools (CORE)
18
+ * Webhooks: 7 tools (CORE)
19
+ *
20
+ * Total: 27 tools (18 read-only, 9 write)
21
+ * Tools: 27 generated endpoint tools (always loaded)
22
+
23
+ *
24
+ * DO NOT EDIT MANUALLY - Regenerate with: pets generate-openapi
25
+ */
26
+
27
+ import { config as loadDotenv } from "dotenv"
28
+ import { z, type ToolDefinition, createLogger, isReadOnly } from "openpets-sdk"
29
+
30
+ loadDotenv()
31
+
32
+ import { getBaseUrl, getAuthHeaders, fetchAPI } from "./openapi-client"
33
+
34
+ const logger = createLogger("quo-client")
35
+
36
+
37
+ // Tools marked as write operations (filtered in read-only mode)
38
+ // Based on HTTP method: POST, PUT, PATCH, DELETE are write operations
39
+ const writeToolNames = new Set([
40
+ "quo-create-contact-v1",
41
+ "quo-update-contact-by-id-v1",
42
+ "quo-delete-contact-v1",
43
+ "quo-send-message-v1",
44
+ "quo-delete-webhook-by-id-v1",
45
+ "quo-create-message-webhook-v1",
46
+ "quo-create-call-webhook-v1",
47
+ "quo-create-call-summary-webhook-v1",
48
+ "quo-create-call-transcript-webhook-v1"
49
+ ])
50
+
51
+ // ============================================================================
52
+ // CORE TOOLS - Always loaded (27 tools)
53
+ // ============================================================================
54
+ const coreTools: ToolDefinition[] = [
55
+ {
56
+ name: "quo-get-call-recordings-v1",
57
+ description: "Get recordings for a call",
58
+ schema: z.object({
59
+ callId: z.string().describe("The unique identifier of the call for which recordings are being retrieved.")
60
+ }),
61
+ search: {
62
+ capabilities: ["quo-get-call-recordings-v1","getcallrecordings","get","recordings","for","call","call-recordings","callid","calls"],
63
+ intents: []
64
+ },
65
+ async execute(args: any, context?: any) {
66
+ const url = `${getBaseUrl()}/v1/call-recordings/${args.callId}`
67
+ let fullUrl = url
68
+
69
+ const options: RequestInit = {
70
+ method: "GET",
71
+ headers: {}
72
+ }
73
+
74
+ return fetchAPI(fullUrl, options, context)
75
+ }
76
+ },
77
+
78
+ {
79
+ name: "quo-list-calls-v1",
80
+ description: "List calls",
81
+ schema: z.object({
82
+ phoneNumberId: z.string().describe("The unique identifier of the OpenPhone number associated with the call."),
83
+ userId: z.string().describe("The unique identifier of the OpenPhone user who either placed or received the call. Defaults to the workspace owner.").optional(),
84
+ participants: z.array(z.string()).describe("The phone numbers of participants involved in the call conversation, excluding your OpenPhone number. Each number should contain the country code and conform to the E.164 format. Currently limited to one-to-one (1:1) conversations only."),
85
+ since: z.string().describe("ISO 8601 datetime: DEPRECATED, use \"createdAfter\" or \"createdBefore\" instead. \"since\" incorrectly behaves as \"createdBefore\" and will be removed in an upcoming release.").optional(),
86
+ createdAfter: z.string().describe("ISO 8601 datetime: Filter results to only include calls created after the specified date and time, in ISO 8601 format.").optional(),
87
+ createdBefore: z.string().describe("ISO 8601 datetime: Filter results to only include calls created before the specified date and time, in ISO 8601 format.").optional(),
88
+ maxResults: z.number().describe("Maximum number of results to return per page."),
89
+ pageToken: z.string().optional()
90
+ }),
91
+ search: {
92
+ capabilities: ["quo-list-calls-v1","listcalls","list","calls"],
93
+ intents: []
94
+ },
95
+ async execute(args: any, context?: any) {
96
+ const url = `${getBaseUrl()}/v1/calls`
97
+ const params = new URLSearchParams()
98
+ if (args.phoneNumberId !== undefined) params.append("phoneNumberId", String(args.phoneNumberId))
99
+ if (args.userId !== undefined) params.append("userId", String(args.userId))
100
+ if (args.participants !== undefined) params.append("participants", String(args.participants))
101
+ if (args.since !== undefined) params.append("since", String(args.since))
102
+ if (args.createdAfter !== undefined) params.append("createdAfter", String(args.createdAfter))
103
+ if (args.createdBefore !== undefined) params.append("createdBefore", String(args.createdBefore))
104
+ if (args.maxResults !== undefined) params.append("maxResults", String(args.maxResults))
105
+ if (args.pageToken !== undefined) params.append("pageToken", String(args.pageToken))
106
+ const queryString = params.toString()
107
+ let fullUrl = queryString ? `${url}?${queryString}` : url
108
+
109
+ const options: RequestInit = {
110
+ method: "GET",
111
+ headers: {}
112
+ }
113
+
114
+ return fetchAPI(fullUrl, options, context)
115
+ }
116
+ },
117
+
118
+ {
119
+ name: "quo-get-call-by-id-v1",
120
+ description: "Get a call by ID",
121
+ schema: z.object({
122
+ callId: z.string().describe("Unique identifier of the call.")
123
+ }),
124
+ search: {
125
+ capabilities: ["quo-get-call-by-id-v1","getcallbyid","get","call","calls","callid"],
126
+ intents: []
127
+ },
128
+ async execute(args: any, context?: any) {
129
+ const url = `${getBaseUrl()}/v1/calls/${args.callId}`
130
+ let fullUrl = url
131
+
132
+ const options: RequestInit = {
133
+ method: "GET",
134
+ headers: {}
135
+ }
136
+
137
+ return fetchAPI(fullUrl, options, context)
138
+ }
139
+ },
140
+
141
+ {
142
+ name: "quo-get-call-summary-v1",
143
+ description: "Get a summary for a call",
144
+ schema: z.object({
145
+ callId: z.string().describe("The unique identifier of the call associated with the summary.")
146
+ }),
147
+ search: {
148
+ capabilities: ["quo-get-call-summary-v1","getcallsummary","get","summary","for","call","call-summaries","callid","calls"],
149
+ intents: []
150
+ },
151
+ async execute(args: any, context?: any) {
152
+ const url = `${getBaseUrl()}/v1/call-summaries/${args.callId}`
153
+ let fullUrl = url
154
+
155
+ const options: RequestInit = {
156
+ method: "GET",
157
+ headers: {}
158
+ }
159
+
160
+ return fetchAPI(fullUrl, options, context)
161
+ }
162
+ },
163
+
164
+ {
165
+ name: "quo-get-call-transcript-v1",
166
+ description: "Get a transcription for a call",
167
+ schema: z.object({
168
+ id: z.string().describe("Unique identifier of the call associated with this transcript.")
169
+ }),
170
+ search: {
171
+ capabilities: ["quo-get-call-transcript-v1","getcalltranscript","get","transcription","for","call","call-transcripts","calls"],
172
+ intents: []
173
+ },
174
+ async execute(args: any, context?: any) {
175
+ const url = `${getBaseUrl()}/v1/call-transcripts/${args.id}`
176
+ let fullUrl = url
177
+
178
+ const options: RequestInit = {
179
+ method: "GET",
180
+ headers: {}
181
+ }
182
+
183
+ return fetchAPI(fullUrl, options, context)
184
+ }
185
+ },
186
+
187
+ {
188
+ name: "quo-get-call-voicemails-v1",
189
+ description: "Get a voicemail for a call",
190
+ schema: z.object({
191
+ callId: z.string().describe("The unique identifier of the call for which a voicemail is being retrieved.")
192
+ }),
193
+ search: {
194
+ capabilities: ["quo-get-call-voicemails-v1","getcallvoicemails","get","voicemail","for","call","call-voicemails","callid","calls"],
195
+ intents: []
196
+ },
197
+ async execute(args: any, context?: any) {
198
+ const url = `${getBaseUrl()}/v1/call-voicemails/${args.callId}`
199
+ let fullUrl = url
200
+
201
+ const options: RequestInit = {
202
+ method: "GET",
203
+ headers: {}
204
+ }
205
+
206
+ return fetchAPI(fullUrl, options, context)
207
+ }
208
+ },
209
+
210
+ {
211
+ name: "quo-get-contact-custom-fields-v1",
212
+ description: "Get contact custom fields",
213
+ schema: z.object({}),
214
+ search: {
215
+ capabilities: ["quo-get-contact-custom-fields-v1","getcontactcustomfields","get","contact","custom","fields","contact-custom-fields"],
216
+ intents: []
217
+ },
218
+ async execute(args: any, context?: any) {
219
+ const url = `${getBaseUrl()}/v1/contact-custom-fields`
220
+ let fullUrl = url
221
+
222
+ const options: RequestInit = {
223
+ method: "GET",
224
+ headers: {}
225
+ }
226
+
227
+ return fetchAPI(fullUrl, options, context)
228
+ }
229
+ },
230
+
231
+ {
232
+ name: "quo-list-contacts-v1",
233
+ description: "List contacts",
234
+ schema: z.object({
235
+ externalIds: z.array(z.string()).describe("Optional list of unique identifiers from an external system used to retrieve specific contacts. When provided, the result set is limited to contacts associated with the provided `externalIds`. These IDs must match those supplied during contact creation via the \"Create Contacts\" endpoint. When omitted, returns all contacts for the organization. Use this parameter to cross-reference and fetch contacts linked to external systems.").optional(),
236
+ sources: z.array(z.string()).optional(),
237
+ maxResults: z.number().describe("Maximum number of results to return per page."),
238
+ pageToken: z.string().optional()
239
+ }),
240
+ search: {
241
+ capabilities: ["quo-list-contacts-v1","listcontacts","list","contacts"],
242
+ intents: []
243
+ },
244
+ async execute(args: any, context?: any) {
245
+ const url = `${getBaseUrl()}/v1/contacts`
246
+ const params = new URLSearchParams()
247
+ if (args.externalIds !== undefined) params.append("externalIds", String(args.externalIds))
248
+ if (args.sources !== undefined) params.append("sources", String(args.sources))
249
+ if (args.maxResults !== undefined) params.append("maxResults", String(args.maxResults))
250
+ if (args.pageToken !== undefined) params.append("pageToken", String(args.pageToken))
251
+ const queryString = params.toString()
252
+ let fullUrl = queryString ? `${url}?${queryString}` : url
253
+
254
+ const options: RequestInit = {
255
+ method: "GET",
256
+ headers: {}
257
+ }
258
+
259
+ return fetchAPI(fullUrl, options, context)
260
+ }
261
+ },
262
+
263
+ {
264
+ name: "quo-create-contact-v1",
265
+ description: "Create a contact",
266
+ schema: z.object({
267
+ defaultFields: z.object({
268
+ company: z.string().optional(),
269
+ emails: z.string().describe("JSON array").optional(),
270
+ firstName: z.string(),
271
+ lastName: z.string().optional(),
272
+ phoneNumbers: z.string().describe("JSON array").optional(),
273
+ role: z.string().optional()
274
+ }),
275
+ customFields: z.string().describe("JSON array").optional(),
276
+ createdByUserId: z.string().describe("The unique identifier of the user who created the contact.").optional(),
277
+ source: z.string().describe("The contact's source. Defaults to `null` for contacts created in the UI. Defaults to `public-api` for contacts created via the public API. Cannot be one of the following reserved words: `openphone`, `device`, `csv`, `zapier`, `google-people`, `other` or start with one of the following reserved prefixes: `openphone`, `csv`.").optional(),
278
+ sourceUrl: z.string().describe("A link to the contact in the source system.").optional(),
279
+ externalId: z.string().optional()
280
+ }),
281
+ search: {
282
+ capabilities: ["quo-create-contact-v1","createcontact","create","contact","contacts"],
283
+ intents: []
284
+ },
285
+ async execute(args: any, context?: any) {
286
+ const url = `${getBaseUrl()}/v1/contacts`
287
+ let fullUrl = url
288
+
289
+ const options: RequestInit = {
290
+ method: "POST",
291
+ headers: {},
292
+ body: JSON.stringify({
293
+ ...(args.defaultFields !== undefined ? { defaultFields: args.defaultFields } : {}),
294
+ ...(args.customFields !== undefined ? { customFields: args.customFields } : {}),
295
+ ...(args.createdByUserId !== undefined ? { createdByUserId: args.createdByUserId } : {}),
296
+ ...(args.source !== undefined ? { source: args.source } : {}),
297
+ ...(args.sourceUrl !== undefined ? { sourceUrl: args.sourceUrl } : {}),
298
+ ...(args.externalId !== undefined ? { externalId: args.externalId } : {})
299
+ })
300
+ }
301
+
302
+ return fetchAPI(fullUrl, options, context)
303
+ }
304
+ },
305
+
306
+ {
307
+ name: "quo-get-contact-by-id-v1",
308
+ description: "Get a contact by ID",
309
+ schema: z.object({
310
+ id: z.string().describe("The unique identifier of the contact.")
311
+ }),
312
+ search: {
313
+ capabilities: ["quo-get-contact-by-id-v1","getcontactbyid","get","contact","contacts"],
314
+ intents: []
315
+ },
316
+ async execute(args: any, context?: any) {
317
+ const url = `${getBaseUrl()}/v1/contacts/${args.id}`
318
+ let fullUrl = url
319
+
320
+ const options: RequestInit = {
321
+ method: "GET",
322
+ headers: {}
323
+ }
324
+
325
+ return fetchAPI(fullUrl, options, context)
326
+ }
327
+ },
328
+
329
+ {
330
+ name: "quo-update-contact-by-id-v1",
331
+ description: "Update a contact by ID",
332
+ schema: z.object({
333
+ id: z.string().describe("The unique identifier of the contact."),
334
+ externalId: z.string().optional(),
335
+ source: z.string().optional(),
336
+ sourceUrl: z.string().optional(),
337
+ defaultFields: z.object({
338
+ company: z.string().optional(),
339
+ emails: z.string().describe("JSON array").optional(),
340
+ firstName: z.string().optional(),
341
+ lastName: z.string().optional(),
342
+ phoneNumbers: z.string().describe("JSON array").optional(),
343
+ role: z.string().optional()
344
+ }),
345
+ customFields: z.string().describe("JSON array").optional()
346
+ }),
347
+ search: {
348
+ capabilities: ["quo-update-contact-by-id-v1","updatecontactbyid","update","contact","contacts"],
349
+ intents: []
350
+ },
351
+ async execute(args: any, context?: any) {
352
+ const url = `${getBaseUrl()}/v1/contacts/${args.id}`
353
+ let fullUrl = url
354
+
355
+ const options: RequestInit = {
356
+ method: "PATCH",
357
+ headers: {},
358
+ body: JSON.stringify({
359
+ ...(args.externalId !== undefined ? { externalId: args.externalId } : {}),
360
+ ...(args.source !== undefined ? { source: args.source } : {}),
361
+ ...(args.sourceUrl !== undefined ? { sourceUrl: args.sourceUrl } : {}),
362
+ ...(args.defaultFields !== undefined ? { defaultFields: args.defaultFields } : {}),
363
+ ...(args.customFields !== undefined ? { customFields: args.customFields } : {})
364
+ })
365
+ }
366
+
367
+ return fetchAPI(fullUrl, options, context)
368
+ }
369
+ },
370
+
371
+ {
372
+ name: "quo-delete-contact-v1",
373
+ description: "Delete a contact",
374
+ schema: z.object({
375
+ id: z.string().describe("The unique identifier of the contact.")
376
+ }),
377
+ search: {
378
+ capabilities: ["quo-delete-contact-v1","deletecontact","delete","contact","contacts"],
379
+ intents: []
380
+ },
381
+ async execute(args: any, context?: any) {
382
+ const url = `${getBaseUrl()}/v1/contacts/${args.id}`
383
+ let fullUrl = url
384
+
385
+ const options: RequestInit = {
386
+ method: "DELETE",
387
+ headers: {}
388
+ }
389
+
390
+ return fetchAPI(fullUrl, options, context)
391
+ }
392
+ },
393
+
394
+ {
395
+ name: "quo-list-conversations-v1",
396
+ description: "List Conversations",
397
+ schema: z.object({
398
+ phoneNumber: z.any().describe("DEPRECATED, use `phoneNumbers` instead. If both `phoneNumber` and `phoneNumbers` are provided, `phoneNumbers` will be used. Filters results to only include conversations with the specified OpenPhone phone number. Can be either your OpenPhone phone number ID or the full phone number in E.164 format.").optional(),
399
+ phoneNumbers: z.string().describe("JSON array: Filters results to only include conversations with the specified OpenPhone phone numbers. Each item can be either an OpenPhone phone number ID or a full phone number in E.164 format.").optional(),
400
+ userId: z.string().describe("The unique identifier of the user the making the request. Used to filter results to only include the user's conversations.").optional(),
401
+ createdAfter: z.string().describe("ISO 8601 datetime: Filter results to only include conversations created after the specified date and time, in ISO_8601 format.").optional(),
402
+ createdBefore: z.string().describe("ISO 8601 datetime: Filter results to only include conversations created before the specified date and time, in ISO_8601 format.").optional(),
403
+ excludeInactive: z.boolean().describe("Exclude inactive conversations from the results.").optional(),
404
+ updatedAfter: z.string().describe("ISO 8601 datetime: Filter results to only include conversations updated after the specified date and time, in ISO_8601 format.").optional(),
405
+ updatedBefore: z.string().describe("ISO 8601 datetime: Filter results to only include conversations updated before the specified date and time, in ISO_8601 format.").optional(),
406
+ maxResults: z.number().describe("Maximum number of results to return per page."),
407
+ pageToken: z.string().optional()
408
+ }),
409
+ search: {
410
+ capabilities: ["quo-list-conversations-v1","listconversations","list","conversations"],
411
+ intents: []
412
+ },
413
+ async execute(args: any, context?: any) {
414
+ const url = `${getBaseUrl()}/v1/conversations`
415
+ const params = new URLSearchParams()
416
+ if (args.phoneNumber !== undefined) params.append("phoneNumber", String(args.phoneNumber))
417
+ if (args.phoneNumbers !== undefined) params.append("phoneNumbers", String(args.phoneNumbers))
418
+ if (args.userId !== undefined) params.append("userId", String(args.userId))
419
+ if (args.createdAfter !== undefined) params.append("createdAfter", String(args.createdAfter))
420
+ if (args.createdBefore !== undefined) params.append("createdBefore", String(args.createdBefore))
421
+ if (args.excludeInactive !== undefined) params.append("excludeInactive", String(args.excludeInactive))
422
+ if (args.updatedAfter !== undefined) params.append("updatedAfter", String(args.updatedAfter))
423
+ if (args.updatedBefore !== undefined) params.append("updatedBefore", String(args.updatedBefore))
424
+ if (args.maxResults !== undefined) params.append("maxResults", String(args.maxResults))
425
+ if (args.pageToken !== undefined) params.append("pageToken", String(args.pageToken))
426
+ const queryString = params.toString()
427
+ let fullUrl = queryString ? `${url}?${queryString}` : url
428
+
429
+ const options: RequestInit = {
430
+ method: "GET",
431
+ headers: {}
432
+ }
433
+
434
+ return fetchAPI(fullUrl, options, context)
435
+ }
436
+ },
437
+
438
+ {
439
+ name: "quo-list-messages-v1",
440
+ description: "List messages",
441
+ schema: z.object({
442
+ phoneNumberId: z.string().describe("The unique identifier of the OpenPhone number used to send or receive the messages. PhoneNumberID can be retrieved via the Get Phone Numbers endpoint."),
443
+ userId: z.string().describe("The unique identifier of the user the message was sent from.").optional(),
444
+ participants: z.array(z.string()).describe("Array of phone numbers involved in the conversation, excluding your OpenPhone number, in E.164 format."),
445
+ since: z.string().describe("ISO 8601 datetime: DEPRECATED, use \"createdAfter\" or \"createdBefore\" instead. \"since\" currently behaves as \"createdBefore\" and will be removed in an upcoming release.").optional(),
446
+ createdAfter: z.string().describe("ISO 8601 datetime: Filter results to only include messages created after the specified date and time, in ISO_8601 format.").optional(),
447
+ createdBefore: z.string().describe("ISO 8601 datetime: Filter results to only include messages created before the specified date and time, in ISO_8601 format.").optional(),
448
+ maxResults: z.number().describe("Maximum number of results to return per page."),
449
+ pageToken: z.string().optional()
450
+ }),
451
+ search: {
452
+ capabilities: ["quo-list-messages-v1","listmessages","list","messages"],
453
+ intents: []
454
+ },
455
+ async execute(args: any, context?: any) {
456
+ const url = `${getBaseUrl()}/v1/messages`
457
+ const params = new URLSearchParams()
458
+ if (args.phoneNumberId !== undefined) params.append("phoneNumberId", String(args.phoneNumberId))
459
+ if (args.userId !== undefined) params.append("userId", String(args.userId))
460
+ if (args.participants !== undefined) params.append("participants", String(args.participants))
461
+ if (args.since !== undefined) params.append("since", String(args.since))
462
+ if (args.createdAfter !== undefined) params.append("createdAfter", String(args.createdAfter))
463
+ if (args.createdBefore !== undefined) params.append("createdBefore", String(args.createdBefore))
464
+ if (args.maxResults !== undefined) params.append("maxResults", String(args.maxResults))
465
+ if (args.pageToken !== undefined) params.append("pageToken", String(args.pageToken))
466
+ const queryString = params.toString()
467
+ let fullUrl = queryString ? `${url}?${queryString}` : url
468
+
469
+ const options: RequestInit = {
470
+ method: "GET",
471
+ headers: {}
472
+ }
473
+
474
+ return fetchAPI(fullUrl, options, context)
475
+ }
476
+ },
477
+
478
+ {
479
+ name: "quo-send-message-v1",
480
+ description: "Send a text message",
481
+ schema: z.object({
482
+ content: z.string().describe("The text content of the message to be sent."),
483
+ phoneNumberId: z.string().describe("DEPRECATED, use \"from\" instead. OpenPhone phone number ID to send a message from").optional(),
484
+ from: z.any(),
485
+ to: z.string().describe("JSON array"),
486
+ userId: z.string().describe("The unique identifier of the OpenPhone user sending the message. If not provided, defaults to the phone number owner.").optional(),
487
+ setInboxStatus: z.enum(["done"]).describe("Used to set the status of the related OpenPhone inbox conversation. The default behavior without setting this parameter will be for the message sent to show up as an open conversation in the user's inbox. Setting the parameter to `'done'` would move the conversation to the Done inbox view.").optional()
488
+ }),
489
+ search: {
490
+ capabilities: ["quo-send-message-v1","sendmessage","send","text","message","messages"],
491
+ intents: []
492
+ },
493
+ async execute(args: any, context?: any) {
494
+ const url = `${getBaseUrl()}/v1/messages`
495
+ let fullUrl = url
496
+
497
+ const options: RequestInit = {
498
+ method: "POST",
499
+ headers: {},
500
+ body: JSON.stringify({
501
+ ...(args.content !== undefined ? { content: args.content } : {}),
502
+ ...(args.phoneNumberId !== undefined ? { phoneNumberId: args.phoneNumberId } : {}),
503
+ ...(args.from !== undefined ? { from: args.from } : {}),
504
+ ...(args.to !== undefined ? { to: args.to } : {}),
505
+ ...(args.userId !== undefined ? { userId: args.userId } : {}),
506
+ ...(args.setInboxStatus !== undefined ? { setInboxStatus: args.setInboxStatus } : {})
507
+ })
508
+ }
509
+
510
+ return fetchAPI(fullUrl, options, context)
511
+ }
512
+ },
513
+
514
+ {
515
+ name: "quo-get-message-by-id-v1",
516
+ description: "Get a message by ID",
517
+ schema: z.object({
518
+ id: z.string().describe("The unique identifier of a message")
519
+ }),
520
+ search: {
521
+ capabilities: ["quo-get-message-by-id-v1","getmessagebyid","get","message","messages"],
522
+ intents: []
523
+ },
524
+ async execute(args: any, context?: any) {
525
+ const url = `${getBaseUrl()}/v1/messages/${args.id}`
526
+ let fullUrl = url
527
+
528
+ const options: RequestInit = {
529
+ method: "GET",
530
+ headers: {}
531
+ }
532
+
533
+ return fetchAPI(fullUrl, options, context)
534
+ }
535
+ },
536
+
537
+ {
538
+ name: "quo-list-phone-numbers-v1",
539
+ description: "List phone numbers",
540
+ schema: z.object({
541
+ userId: z.string().describe("Filter results to return only phone numbers associated with the specified user\"s unique identifier.").optional()
542
+ }),
543
+ search: {
544
+ capabilities: ["quo-list-phone-numbers-v1","listphonenumbers","list","phone","numbers","phone-numbers"],
545
+ intents: []
546
+ },
547
+ async execute(args: any, context?: any) {
548
+ const url = `${getBaseUrl()}/v1/phone-numbers`
549
+ const params = new URLSearchParams()
550
+ if (args.userId !== undefined) params.append("userId", String(args.userId))
551
+ const queryString = params.toString()
552
+ let fullUrl = queryString ? `${url}?${queryString}` : url
553
+
554
+ const options: RequestInit = {
555
+ method: "GET",
556
+ headers: {}
557
+ }
558
+
559
+ return fetchAPI(fullUrl, options, context)
560
+ }
561
+ },
562
+
563
+ {
564
+ name: "quo-get-phone-number-by-id-v1",
565
+ description: "Get a phone number by ID",
566
+ schema: z.object({
567
+ phoneNumberId: z.string().describe("Unique identifier of the phone number.")
568
+ }),
569
+ search: {
570
+ capabilities: ["quo-get-phone-number-by-id-v1","getphonenumberbyid","get","phone","number","phone-numbers","phonenumberid","numbers"],
571
+ intents: []
572
+ },
573
+ async execute(args: any, context?: any) {
574
+ const url = `${getBaseUrl()}/v1/phone-numbers/${args.phoneNumberId}`
575
+ let fullUrl = url
576
+
577
+ const options: RequestInit = {
578
+ method: "GET",
579
+ headers: {}
580
+ }
581
+
582
+ return fetchAPI(fullUrl, options, context)
583
+ }
584
+ },
585
+
586
+ {
587
+ name: "quo-list-users-v1",
588
+ description: "List users",
589
+ schema: z.object({
590
+ maxResults: z.number().describe("Maximum number of results to return per page."),
591
+ pageToken: z.string().optional()
592
+ }),
593
+ search: {
594
+ capabilities: ["quo-list-users-v1","listusers","list","users"],
595
+ intents: []
596
+ },
597
+ async execute(args: any, context?: any) {
598
+ const url = `${getBaseUrl()}/v1/users`
599
+ const params = new URLSearchParams()
600
+ if (args.maxResults !== undefined) params.append("maxResults", String(args.maxResults))
601
+ if (args.pageToken !== undefined) params.append("pageToken", String(args.pageToken))
602
+ const queryString = params.toString()
603
+ let fullUrl = queryString ? `${url}?${queryString}` : url
604
+
605
+ const options: RequestInit = {
606
+ method: "GET",
607
+ headers: {}
608
+ }
609
+
610
+ return fetchAPI(fullUrl, options, context)
611
+ }
612
+ },
613
+
614
+ {
615
+ name: "quo-get-user-by-id-v1",
616
+ description: "Get a user by ID",
617
+ schema: z.object({
618
+ userId: z.string().describe("The unique identifier of the user being retrieved.")
619
+ }),
620
+ search: {
621
+ capabilities: ["quo-get-user-by-id-v1","getuserbyid","get","user","users","userid"],
622
+ intents: []
623
+ },
624
+ async execute(args: any, context?: any) {
625
+ const url = `${getBaseUrl()}/v1/users/${args.userId}`
626
+ let fullUrl = url
627
+
628
+ const options: RequestInit = {
629
+ method: "GET",
630
+ headers: {}
631
+ }
632
+
633
+ return fetchAPI(fullUrl, options, context)
634
+ }
635
+ },
636
+
637
+ {
638
+ name: "quo-list-webhooks-v1",
639
+ description: "Lists all webhooks",
640
+ schema: z.object({
641
+ userId: z.string().describe("The unique identifier the user. Defaults to the workspace owner.").optional()
642
+ }),
643
+ search: {
644
+ capabilities: ["quo-list-webhooks-v1","listwebhooks","lists","all","webhooks"],
645
+ intents: []
646
+ },
647
+ async execute(args: any, context?: any) {
648
+ const url = `${getBaseUrl()}/v1/webhooks`
649
+ const params = new URLSearchParams()
650
+ if (args.userId !== undefined) params.append("userId", String(args.userId))
651
+ const queryString = params.toString()
652
+ let fullUrl = queryString ? `${url}?${queryString}` : url
653
+
654
+ const options: RequestInit = {
655
+ method: "GET",
656
+ headers: {}
657
+ }
658
+
659
+ return fetchAPI(fullUrl, options, context)
660
+ }
661
+ },
662
+
663
+ {
664
+ name: "quo-get-webhook-by-id-v1",
665
+ description: "Get a webhook by ID",
666
+ schema: z.object({
667
+ id: z.string().describe("The unique identifier of a webhook")
668
+ }),
669
+ search: {
670
+ capabilities: ["quo-get-webhook-by-id-v1","getwebhookbyid","get","webhook","webhooks"],
671
+ intents: []
672
+ },
673
+ async execute(args: any, context?: any) {
674
+ const url = `${getBaseUrl()}/v1/webhooks/${args.id}`
675
+ let fullUrl = url
676
+
677
+ const options: RequestInit = {
678
+ method: "GET",
679
+ headers: {}
680
+ }
681
+
682
+ return fetchAPI(fullUrl, options, context)
683
+ }
684
+ },
685
+
686
+ {
687
+ name: "quo-delete-webhook-by-id-v1",
688
+ description: "Delete a webhook by ID",
689
+ schema: z.object({
690
+ id: z.string().describe("The unique identifier of a webhook")
691
+ }),
692
+ search: {
693
+ capabilities: ["quo-delete-webhook-by-id-v1","deletewebhookbyid","delete","webhook","webhooks"],
694
+ intents: []
695
+ },
696
+ async execute(args: any, context?: any) {
697
+ const url = `${getBaseUrl()}/v1/webhooks/${args.id}`
698
+ let fullUrl = url
699
+
700
+ const options: RequestInit = {
701
+ method: "DELETE",
702
+ headers: {}
703
+ }
704
+
705
+ return fetchAPI(fullUrl, options, context)
706
+ }
707
+ },
708
+
709
+ {
710
+ name: "quo-create-message-webhook-v1",
711
+ description: "Create a new webhook for messages",
712
+ schema: z.object({
713
+ events: z.array(z.string()),
714
+ label: z.string().describe("Webhook's label").optional(),
715
+ resourceIds: z.any().optional(),
716
+ status: z.enum(["enabled", "disabled"]).describe("The status of the webhook.").optional(),
717
+ url: z.string().describe("The endpoint that receives events from the webhook."),
718
+ userId: z.string().describe("The unique identifier of the user that creates the webhook. If not provided, default to workspace owner.").optional()
719
+ }),
720
+ search: {
721
+ capabilities: ["quo-create-message-webhook-v1","createmessagewebhook","create","new","webhook","for","messages","webhooks"],
722
+ intents: []
723
+ },
724
+ async execute(args: any, context?: any) {
725
+ const url = `${getBaseUrl()}/v1/webhooks/messages`
726
+ let fullUrl = url
727
+
728
+ const options: RequestInit = {
729
+ method: "POST",
730
+ headers: {},
731
+ body: JSON.stringify({
732
+ ...(args.events !== undefined ? { events: args.events } : {}),
733
+ ...(args.label !== undefined ? { label: args.label } : {}),
734
+ ...(args.resourceIds !== undefined ? { resourceIds: args.resourceIds } : {}),
735
+ ...(args.status !== undefined ? { status: args.status } : {}),
736
+ ...(args.url !== undefined ? { url: args.url } : {}),
737
+ ...(args.userId !== undefined ? { userId: args.userId } : {})
738
+ })
739
+ }
740
+
741
+ return fetchAPI(fullUrl, options, context)
742
+ }
743
+ },
744
+
745
+ {
746
+ name: "quo-create-call-webhook-v1",
747
+ description: "Create a new webhook for calls",
748
+ schema: z.object({
749
+ url: z.string().describe("The endpoint that receives events from the webhook."),
750
+ events: z.array(z.string()),
751
+ resourceIds: z.any().optional(),
752
+ userId: z.string().describe("The unique identifier of the user that creates the webhook. If not provided, default to workspace owner.").optional(),
753
+ label: z.string().describe("Webhook's label").optional(),
754
+ status: z.enum(["enabled", "disabled"]).describe("The status of the webhook.").optional()
755
+ }),
756
+ search: {
757
+ capabilities: ["quo-create-call-webhook-v1","createcallwebhook","create","new","webhook","for","calls","webhooks"],
758
+ intents: []
759
+ },
760
+ async execute(args: any, context?: any) {
761
+ const url = `${getBaseUrl()}/v1/webhooks/calls`
762
+ let fullUrl = url
763
+
764
+ const options: RequestInit = {
765
+ method: "POST",
766
+ headers: {},
767
+ body: JSON.stringify({
768
+ ...(args.url !== undefined ? { url: args.url } : {}),
769
+ ...(args.events !== undefined ? { events: args.events } : {}),
770
+ ...(args.resourceIds !== undefined ? { resourceIds: args.resourceIds } : {}),
771
+ ...(args.userId !== undefined ? { userId: args.userId } : {}),
772
+ ...(args.label !== undefined ? { label: args.label } : {}),
773
+ ...(args.status !== undefined ? { status: args.status } : {})
774
+ })
775
+ }
776
+
777
+ return fetchAPI(fullUrl, options, context)
778
+ }
779
+ },
780
+
781
+ {
782
+ name: "quo-create-call-summary-webhook-v1",
783
+ description: "Create a new webhook for call summaries",
784
+ schema: z.object({
785
+ events: z.array(z.string()),
786
+ label: z.string().describe("Webhook's label").optional(),
787
+ resourceIds: z.any().optional(),
788
+ status: z.enum(["enabled", "disabled"]).describe("The status of the webhook.").optional(),
789
+ url: z.string().describe("The endpoint that receives events from the webhook."),
790
+ userId: z.string().describe("The unique identifier of the user that creates the webhook. If not provided, default to workspace owner.").optional()
791
+ }),
792
+ search: {
793
+ capabilities: ["quo-create-call-summary-webhook-v1","createcallsummarywebhook","create","new","webhook","for","call","summaries","webhooks","call-summaries"],
794
+ intents: []
795
+ },
796
+ async execute(args: any, context?: any) {
797
+ const url = `${getBaseUrl()}/v1/webhooks/call-summaries`
798
+ let fullUrl = url
799
+
800
+ const options: RequestInit = {
801
+ method: "POST",
802
+ headers: {},
803
+ body: JSON.stringify({
804
+ ...(args.events !== undefined ? { events: args.events } : {}),
805
+ ...(args.label !== undefined ? { label: args.label } : {}),
806
+ ...(args.resourceIds !== undefined ? { resourceIds: args.resourceIds } : {}),
807
+ ...(args.status !== undefined ? { status: args.status } : {}),
808
+ ...(args.url !== undefined ? { url: args.url } : {}),
809
+ ...(args.userId !== undefined ? { userId: args.userId } : {})
810
+ })
811
+ }
812
+
813
+ return fetchAPI(fullUrl, options, context)
814
+ }
815
+ },
816
+
817
+ {
818
+ name: "quo-create-call-transcript-webhook-v1",
819
+ description: "Create a new webhook for call transcripts",
820
+ schema: z.object({
821
+ events: z.array(z.string()),
822
+ label: z.string().describe("The webhook's label.").optional(),
823
+ resourceIds: z.any().optional(),
824
+ status: z.enum(["enabled", "disabled"]).describe("The status of the webhook.").optional(),
825
+ url: z.string().describe("The endpoint that receives events from the webhook."),
826
+ userId: z.string().describe("The ID of the user that creates the webhook. If not provided, default to workspace owner.").optional()
827
+ }),
828
+ search: {
829
+ capabilities: ["quo-create-call-transcript-webhook-v1","createcalltranscriptwebhook","create","new","webhook","for","call","transcripts","webhooks","call-transcripts"],
830
+ intents: []
831
+ },
832
+ async execute(args: any, context?: any) {
833
+ const url = `${getBaseUrl()}/v1/webhooks/call-transcripts`
834
+ let fullUrl = url
835
+
836
+ const options: RequestInit = {
837
+ method: "POST",
838
+ headers: {},
839
+ body: JSON.stringify({
840
+ ...(args.events !== undefined ? { events: args.events } : {}),
841
+ ...(args.label !== undefined ? { label: args.label } : {}),
842
+ ...(args.resourceIds !== undefined ? { resourceIds: args.resourceIds } : {}),
843
+ ...(args.status !== undefined ? { status: args.status } : {}),
844
+ ...(args.url !== undefined ? { url: args.url } : {}),
845
+ ...(args.userId !== undefined ? { userId: args.userId } : {})
846
+ })
847
+ }
848
+
849
+ return fetchAPI(fullUrl, options, context)
850
+ }
851
+ }
852
+ ]
853
+
854
+
855
+
856
+ /**
857
+ * Build the OpenAPI tool list lazily.
858
+ * Pass explicit env/readOnly values to override defaults (useful for composite pets).
859
+ */
860
+ export function createOpenAPITools(options?: {
861
+ readOnlyMode?: boolean
862
+ }): ToolDefinition[] {
863
+ const readOnlyMode = options?.readOnlyMode ?? isReadOnly("quo")
864
+
865
+ if (readOnlyMode) {
866
+ logger.info("READ-ONLY MODE - write operations disabled")
867
+ }
868
+
869
+ const allTools: ToolDefinition[] = [
870
+ ...coreTools
871
+ ]
872
+
873
+
874
+ // ============================================================================
875
+ // TEST CONNECTION TOOL - Auto-generated for API health check
876
+ // ============================================================================
877
+ const testConnectionTool: ToolDefinition = {
878
+ name: "quo-test-connection",
879
+ description: "Test API connection and verify credentials are configured",
880
+ schema: z.object({}),
881
+ async execute(_args: any, context?: any) {
882
+ try {
883
+ const currentBaseUrl = getBaseUrl()
884
+ const testUrl = `${currentBaseUrl}/v1/call-recordings/{callId}`
885
+ context?.debugLog?.("openapi api request", {
886
+ method: "GET",
887
+ url: testUrl
888
+ })
889
+ const response = await fetch(testUrl, {
890
+ method: "GET",
891
+ headers: getAuthHeaders()
892
+ })
893
+ const responseText = await response.text()
894
+ context?.debugLog?.("openapi api response", {
895
+ method: "GET",
896
+ url: testUrl,
897
+ status: response.status,
898
+ ok: response.ok,
899
+ body: responseText
900
+ })
901
+
902
+ if (response.ok) {
903
+ return JSON.stringify({
904
+ success: true,
905
+ status: "connected",
906
+ api: "OpenPhone Public API",
907
+ version: "1.0.0",
908
+ baseUrl: currentBaseUrl
909
+ }, null, 2)
910
+ }
911
+
912
+ return JSON.stringify({
913
+ success: false,
914
+ status: "error",
915
+ error: `HTTP ${response.status}: ${responseText}`,
916
+ api: "OpenPhone Public API",
917
+ baseUrl: currentBaseUrl
918
+ }, null, 2)
919
+ } catch (error: any) {
920
+ return JSON.stringify({
921
+ success: false,
922
+ status: "connection_failed",
923
+ error: error.message,
924
+ api: "OpenPhone Public API",
925
+ baseUrl: getBaseUrl()
926
+ }, null, 2)
927
+ }
928
+ }
929
+ }
930
+
931
+
932
+
933
+ /**
934
+ * Filter tools by read-only mode using HTTP method classification
935
+ */
936
+ function filterByReadOnlyMode(tools: ToolDefinition[]): ToolDefinition[] {
937
+ if (!readOnlyMode) return tools
938
+
939
+ const filtered = tools.filter(t => !writeToolNames.has(t.name))
940
+ const excluded = tools.length - filtered.length
941
+
942
+ if (excluded > 0) {
943
+ logger.info(`Filtered ${excluded} write tools in read-only mode`)
944
+ }
945
+
946
+ return filtered
947
+ }
948
+
949
+ // Final combined tools array
950
+ const finalTools: ToolDefinition[] = [
951
+ ...allTools,
952
+ testConnectionTool
953
+ ]
954
+
955
+ logger.info(`Loaded ${finalTools.length} tools`)
956
+
957
+ return filterByReadOnlyMode(finalTools)
958
+ }
959
+
960
+ let cachedOpenAPITools: ToolDefinition[] | null = null
961
+
962
+ function getCachedOpenAPITools(): ToolDefinition[] {
963
+ if (!cachedOpenAPITools) {
964
+ cachedOpenAPITools = createOpenAPITools()
965
+ }
966
+ return cachedOpenAPITools
967
+ }
968
+
969
+ // Backward-compatible default export: behaves like ToolDefinition[] while loading lazily.
970
+ export const openAPITools: ToolDefinition[] = new Proxy([] as ToolDefinition[], {
971
+ get(_target, prop) {
972
+ const tools = getCachedOpenAPITools() as any
973
+ const value = tools[prop as keyof typeof tools]
974
+ return typeof value === "function" ? value.bind(tools) : value
975
+ },
976
+ has(_target, prop) {
977
+ return prop in getCachedOpenAPITools()
978
+ },
979
+ ownKeys() {
980
+ return Reflect.ownKeys(getCachedOpenAPITools())
981
+ },
982
+ getOwnPropertyDescriptor(_target, prop) {
983
+ return Object.getOwnPropertyDescriptor(getCachedOpenAPITools(), prop)
984
+ }
985
+ })
986
+
987
+ export const toolsMetadata = [
988
+ {
989
+ "name": "quo-get-call-recordings-v1",
990
+ "description": "Get recordings for a call",
991
+ "schema": {
992
+ "type": "object",
993
+ "properties": {
994
+ "callId": {
995
+ "type": "string",
996
+ "description": "The unique identifier of the call for which recordings are being retrieved.",
997
+ "optional": false
998
+ }
999
+ },
1000
+ "required": [
1001
+ "callId"
1002
+ ]
1003
+ },
1004
+ "search": {
1005
+ "capabilities": [
1006
+ "quo-get-call-recordings-v1",
1007
+ "getcallrecordings",
1008
+ "get",
1009
+ "recordings",
1010
+ "for",
1011
+ "call",
1012
+ "call-recordings",
1013
+ "callid",
1014
+ "calls"
1015
+ ],
1016
+ "intents": []
1017
+ }
1018
+ },
1019
+ {
1020
+ "name": "quo-list-calls-v1",
1021
+ "description": "List calls",
1022
+ "schema": {
1023
+ "type": "object",
1024
+ "properties": {
1025
+ "phoneNumberId": {
1026
+ "type": "string",
1027
+ "description": "The unique identifier of the OpenPhone number associated with the call.",
1028
+ "optional": false
1029
+ },
1030
+ "userId": {
1031
+ "type": "string",
1032
+ "description": "The unique identifier of the OpenPhone user who either placed or received the call. Defaults to the workspace owner.",
1033
+ "optional": false
1034
+ },
1035
+ "participants": {
1036
+ "type": "string",
1037
+ "description": "The phone numbers of participants involved in the call conversation, excluding your OpenPhone number. Each number should contain the country code and conform to the E.164 format. Currently limited to one-to-one (1:1) conversations only.",
1038
+ "optional": false
1039
+ },
1040
+ "since": {
1041
+ "type": "string",
1042
+ "description": "DEPRECATED, use \"createdAfter\" or \"createdBefore\" instead. \"since\" incorrectly behaves as \"createdBefore\" and will be removed in an upcoming release.",
1043
+ "optional": false
1044
+ },
1045
+ "createdAfter": {
1046
+ "type": "string",
1047
+ "description": "Filter results to only include calls created after the specified date and time, in ISO 8601 format.",
1048
+ "optional": false
1049
+ },
1050
+ "createdBefore": {
1051
+ "type": "string",
1052
+ "description": "Filter results to only include calls created before the specified date and time, in ISO 8601 format.",
1053
+ "optional": false
1054
+ },
1055
+ "maxResults": {
1056
+ "type": "number",
1057
+ "description": "Maximum number of results to return per page.",
1058
+ "optional": false
1059
+ },
1060
+ "pageToken": {
1061
+ "type": "string",
1062
+ "optional": false
1063
+ }
1064
+ },
1065
+ "required": [
1066
+ "phoneNumberId",
1067
+ "participants",
1068
+ "maxResults"
1069
+ ]
1070
+ },
1071
+ "search": {
1072
+ "capabilities": [
1073
+ "quo-list-calls-v1",
1074
+ "listcalls",
1075
+ "list",
1076
+ "calls"
1077
+ ],
1078
+ "intents": []
1079
+ }
1080
+ },
1081
+ {
1082
+ "name": "quo-get-call-by-id-v1",
1083
+ "description": "Get a call by ID",
1084
+ "schema": {
1085
+ "type": "object",
1086
+ "properties": {
1087
+ "callId": {
1088
+ "type": "string",
1089
+ "description": "Unique identifier of the call.",
1090
+ "optional": false
1091
+ }
1092
+ },
1093
+ "required": [
1094
+ "callId"
1095
+ ]
1096
+ },
1097
+ "search": {
1098
+ "capabilities": [
1099
+ "quo-get-call-by-id-v1",
1100
+ "getcallbyid",
1101
+ "get",
1102
+ "call",
1103
+ "calls",
1104
+ "callid"
1105
+ ],
1106
+ "intents": []
1107
+ }
1108
+ },
1109
+ {
1110
+ "name": "quo-get-call-summary-v1",
1111
+ "description": "Get a summary for a call",
1112
+ "schema": {
1113
+ "type": "object",
1114
+ "properties": {
1115
+ "callId": {
1116
+ "type": "string",
1117
+ "description": "The unique identifier of the call associated with the summary.",
1118
+ "optional": false
1119
+ }
1120
+ },
1121
+ "required": [
1122
+ "callId"
1123
+ ]
1124
+ },
1125
+ "search": {
1126
+ "capabilities": [
1127
+ "quo-get-call-summary-v1",
1128
+ "getcallsummary",
1129
+ "get",
1130
+ "summary",
1131
+ "for",
1132
+ "call",
1133
+ "call-summaries",
1134
+ "callid",
1135
+ "calls"
1136
+ ],
1137
+ "intents": []
1138
+ }
1139
+ },
1140
+ {
1141
+ "name": "quo-get-call-transcript-v1",
1142
+ "description": "Get a transcription for a call",
1143
+ "schema": {
1144
+ "type": "object",
1145
+ "properties": {
1146
+ "id": {
1147
+ "type": "string",
1148
+ "description": "Unique identifier of the call associated with this transcript.",
1149
+ "optional": false
1150
+ }
1151
+ },
1152
+ "required": [
1153
+ "id"
1154
+ ]
1155
+ },
1156
+ "search": {
1157
+ "capabilities": [
1158
+ "quo-get-call-transcript-v1",
1159
+ "getcalltranscript",
1160
+ "get",
1161
+ "transcription",
1162
+ "for",
1163
+ "call",
1164
+ "call-transcripts",
1165
+ "calls"
1166
+ ],
1167
+ "intents": []
1168
+ }
1169
+ },
1170
+ {
1171
+ "name": "quo-get-call-voicemails-v1",
1172
+ "description": "Get a voicemail for a call",
1173
+ "schema": {
1174
+ "type": "object",
1175
+ "properties": {
1176
+ "callId": {
1177
+ "type": "string",
1178
+ "description": "The unique identifier of the call for which a voicemail is being retrieved.",
1179
+ "optional": false
1180
+ }
1181
+ },
1182
+ "required": [
1183
+ "callId"
1184
+ ]
1185
+ },
1186
+ "search": {
1187
+ "capabilities": [
1188
+ "quo-get-call-voicemails-v1",
1189
+ "getcallvoicemails",
1190
+ "get",
1191
+ "voicemail",
1192
+ "for",
1193
+ "call",
1194
+ "call-voicemails",
1195
+ "callid",
1196
+ "calls"
1197
+ ],
1198
+ "intents": []
1199
+ }
1200
+ },
1201
+ {
1202
+ "name": "quo-get-contact-custom-fields-v1",
1203
+ "description": "Get contact custom fields",
1204
+ "schema": {
1205
+ "type": "object",
1206
+ "properties": {}
1207
+ },
1208
+ "search": {
1209
+ "capabilities": [
1210
+ "quo-get-contact-custom-fields-v1",
1211
+ "getcontactcustomfields",
1212
+ "get",
1213
+ "contact",
1214
+ "custom",
1215
+ "fields",
1216
+ "contact-custom-fields"
1217
+ ],
1218
+ "intents": []
1219
+ }
1220
+ },
1221
+ {
1222
+ "name": "quo-list-contacts-v1",
1223
+ "description": "List contacts",
1224
+ "schema": {
1225
+ "type": "object",
1226
+ "properties": {
1227
+ "externalIds": {
1228
+ "type": "string",
1229
+ "description": "Optional list of unique identifiers from an external system used to retrieve specific contacts. When provided, the result set is limited to contacts associated with the provided `externalIds`. These IDs must match those supplied during contact creation via the \"Create Contacts\" endpoint. When omitted, returns all contacts for the organization. Use this parameter to cross-reference and fetch contacts linked to external systems.",
1230
+ "optional": false
1231
+ },
1232
+ "sources": {
1233
+ "type": "string",
1234
+ "optional": false
1235
+ },
1236
+ "maxResults": {
1237
+ "type": "number",
1238
+ "description": "Maximum number of results to return per page.",
1239
+ "optional": false
1240
+ },
1241
+ "pageToken": {
1242
+ "type": "string",
1243
+ "optional": false
1244
+ }
1245
+ },
1246
+ "required": [
1247
+ "maxResults"
1248
+ ]
1249
+ },
1250
+ "search": {
1251
+ "capabilities": [
1252
+ "quo-list-contacts-v1",
1253
+ "listcontacts",
1254
+ "list",
1255
+ "contacts"
1256
+ ],
1257
+ "intents": []
1258
+ }
1259
+ },
1260
+ {
1261
+ "name": "quo-create-contact-v1",
1262
+ "description": "Create a contact",
1263
+ "schema": {
1264
+ "type": "object",
1265
+ "properties": {
1266
+ "defaultFields": {
1267
+ "type": "string",
1268
+ "description": "JSON array",
1269
+ "optional": true
1270
+ },
1271
+ "customFields": {
1272
+ "type": "string",
1273
+ "description": "JSON array",
1274
+ "optional": false
1275
+ },
1276
+ "createdByUserId": {
1277
+ "type": "string",
1278
+ "description": "The unique identifier of the user who created the contact.",
1279
+ "optional": false
1280
+ },
1281
+ "source": {
1282
+ "type": "string",
1283
+ "description": "The contact's source. Defaults to `null` for contacts created in the UI. Defaults to `public-api` for contacts created via the public API. Cannot be one of the following reserved words: `openphone`, `device`, `csv`, `zapier`, `google-people`, `other` or start with one of the following reserved prefixes: `openphone`, `csv`.",
1284
+ "optional": false
1285
+ },
1286
+ "sourceUrl": {
1287
+ "type": "string",
1288
+ "description": "A link to the contact in the source system.",
1289
+ "optional": false
1290
+ },
1291
+ "externalId": {
1292
+ "type": "string",
1293
+ "optional": false
1294
+ }
1295
+ },
1296
+ "required": [
1297
+ "defaultFields"
1298
+ ]
1299
+ },
1300
+ "search": {
1301
+ "capabilities": [
1302
+ "quo-create-contact-v1",
1303
+ "createcontact",
1304
+ "create",
1305
+ "contact",
1306
+ "contacts"
1307
+ ],
1308
+ "intents": []
1309
+ }
1310
+ },
1311
+ {
1312
+ "name": "quo-get-contact-by-id-v1",
1313
+ "description": "Get a contact by ID",
1314
+ "schema": {
1315
+ "type": "object",
1316
+ "properties": {
1317
+ "id": {
1318
+ "type": "string",
1319
+ "description": "The unique identifier of the contact.",
1320
+ "optional": false
1321
+ }
1322
+ },
1323
+ "required": [
1324
+ "id"
1325
+ ]
1326
+ },
1327
+ "search": {
1328
+ "capabilities": [
1329
+ "quo-get-contact-by-id-v1",
1330
+ "getcontactbyid",
1331
+ "get",
1332
+ "contact",
1333
+ "contacts"
1334
+ ],
1335
+ "intents": []
1336
+ }
1337
+ },
1338
+ {
1339
+ "name": "quo-update-contact-by-id-v1",
1340
+ "description": "Update a contact by ID",
1341
+ "schema": {
1342
+ "type": "object",
1343
+ "properties": {
1344
+ "id": {
1345
+ "type": "string",
1346
+ "description": "The unique identifier of the contact.",
1347
+ "optional": false
1348
+ },
1349
+ "externalId": {
1350
+ "type": "string",
1351
+ "optional": false
1352
+ },
1353
+ "source": {
1354
+ "type": "string",
1355
+ "optional": false
1356
+ },
1357
+ "sourceUrl": {
1358
+ "type": "string",
1359
+ "optional": false
1360
+ },
1361
+ "defaultFields": {
1362
+ "type": "string",
1363
+ "description": "JSON array",
1364
+ "optional": true
1365
+ },
1366
+ "customFields": {
1367
+ "type": "string",
1368
+ "description": "JSON array",
1369
+ "optional": false
1370
+ }
1371
+ },
1372
+ "required": [
1373
+ "id"
1374
+ ]
1375
+ },
1376
+ "search": {
1377
+ "capabilities": [
1378
+ "quo-update-contact-by-id-v1",
1379
+ "updatecontactbyid",
1380
+ "update",
1381
+ "contact",
1382
+ "contacts"
1383
+ ],
1384
+ "intents": []
1385
+ }
1386
+ },
1387
+ {
1388
+ "name": "quo-delete-contact-v1",
1389
+ "description": "Delete a contact",
1390
+ "schema": {
1391
+ "type": "object",
1392
+ "properties": {
1393
+ "id": {
1394
+ "type": "string",
1395
+ "description": "The unique identifier of the contact.",
1396
+ "optional": false
1397
+ }
1398
+ },
1399
+ "required": [
1400
+ "id"
1401
+ ]
1402
+ },
1403
+ "search": {
1404
+ "capabilities": [
1405
+ "quo-delete-contact-v1",
1406
+ "deletecontact",
1407
+ "delete",
1408
+ "contact",
1409
+ "contacts"
1410
+ ],
1411
+ "intents": []
1412
+ }
1413
+ },
1414
+ {
1415
+ "name": "quo-list-conversations-v1",
1416
+ "description": "List Conversations",
1417
+ "schema": {
1418
+ "type": "object",
1419
+ "properties": {
1420
+ "phoneNumber": {
1421
+ "type": "string",
1422
+ "description": "DEPRECATED, use `phoneNumbers` instead. If both `phoneNumber` and `phoneNumbers` are provided, `phoneNumbers` will be used. Filters results to only include conversations with the specified OpenPhone phone number. Can be either your OpenPhone phone number ID or the full phone number in E.164 format.",
1423
+ "optional": false
1424
+ },
1425
+ "phoneNumbers": {
1426
+ "type": "string",
1427
+ "description": "Filters results to only include conversations with the specified OpenPhone phone numbers. Each item can be either an OpenPhone phone number ID or a full phone number in E.164 format.",
1428
+ "optional": false
1429
+ },
1430
+ "userId": {
1431
+ "type": "string",
1432
+ "description": "The unique identifier of the user the making the request. Used to filter results to only include the user's conversations.",
1433
+ "optional": false
1434
+ },
1435
+ "createdAfter": {
1436
+ "type": "string",
1437
+ "description": "Filter results to only include conversations created after the specified date and time, in ISO_8601 format.",
1438
+ "optional": false
1439
+ },
1440
+ "createdBefore": {
1441
+ "type": "string",
1442
+ "description": "Filter results to only include conversations created before the specified date and time, in ISO_8601 format.",
1443
+ "optional": false
1444
+ },
1445
+ "excludeInactive": {
1446
+ "type": "boolean",
1447
+ "description": "Exclude inactive conversations from the results.",
1448
+ "optional": false
1449
+ },
1450
+ "updatedAfter": {
1451
+ "type": "string",
1452
+ "description": "Filter results to only include conversations updated after the specified date and time, in ISO_8601 format.",
1453
+ "optional": false
1454
+ },
1455
+ "updatedBefore": {
1456
+ "type": "string",
1457
+ "description": "Filter results to only include conversations updated before the specified date and time, in ISO_8601 format.",
1458
+ "optional": false
1459
+ },
1460
+ "maxResults": {
1461
+ "type": "number",
1462
+ "description": "Maximum number of results to return per page.",
1463
+ "optional": false
1464
+ },
1465
+ "pageToken": {
1466
+ "type": "string",
1467
+ "optional": false
1468
+ }
1469
+ },
1470
+ "required": [
1471
+ "maxResults"
1472
+ ]
1473
+ },
1474
+ "search": {
1475
+ "capabilities": [
1476
+ "quo-list-conversations-v1",
1477
+ "listconversations",
1478
+ "list",
1479
+ "conversations"
1480
+ ],
1481
+ "intents": []
1482
+ }
1483
+ },
1484
+ {
1485
+ "name": "quo-list-messages-v1",
1486
+ "description": "List messages",
1487
+ "schema": {
1488
+ "type": "object",
1489
+ "properties": {
1490
+ "phoneNumberId": {
1491
+ "type": "string",
1492
+ "description": "The unique identifier of the OpenPhone number used to send or receive the messages. PhoneNumberID can be retrieved via the Get Phone Numbers endpoint.",
1493
+ "optional": false
1494
+ },
1495
+ "userId": {
1496
+ "type": "string",
1497
+ "description": "The unique identifier of the user the message was sent from.",
1498
+ "optional": false
1499
+ },
1500
+ "participants": {
1501
+ "type": "string",
1502
+ "description": "Array of phone numbers involved in the conversation, excluding your OpenPhone number, in E.164 format.",
1503
+ "optional": false
1504
+ },
1505
+ "since": {
1506
+ "type": "string",
1507
+ "description": "DEPRECATED, use \"createdAfter\" or \"createdBefore\" instead. \"since\" currently behaves as \"createdBefore\" and will be removed in an upcoming release.",
1508
+ "optional": false
1509
+ },
1510
+ "createdAfter": {
1511
+ "type": "string",
1512
+ "description": "Filter results to only include messages created after the specified date and time, in ISO_8601 format.",
1513
+ "optional": false
1514
+ },
1515
+ "createdBefore": {
1516
+ "type": "string",
1517
+ "description": "Filter results to only include messages created before the specified date and time, in ISO_8601 format.",
1518
+ "optional": false
1519
+ },
1520
+ "maxResults": {
1521
+ "type": "number",
1522
+ "description": "Maximum number of results to return per page.",
1523
+ "optional": false
1524
+ },
1525
+ "pageToken": {
1526
+ "type": "string",
1527
+ "optional": false
1528
+ }
1529
+ },
1530
+ "required": [
1531
+ "phoneNumberId",
1532
+ "participants",
1533
+ "maxResults"
1534
+ ]
1535
+ },
1536
+ "search": {
1537
+ "capabilities": [
1538
+ "quo-list-messages-v1",
1539
+ "listmessages",
1540
+ "list",
1541
+ "messages"
1542
+ ],
1543
+ "intents": []
1544
+ }
1545
+ },
1546
+ {
1547
+ "name": "quo-send-message-v1",
1548
+ "description": "Send a text message",
1549
+ "schema": {
1550
+ "type": "object",
1551
+ "properties": {
1552
+ "content": {
1553
+ "type": "string",
1554
+ "description": "The text content of the message to be sent.",
1555
+ "optional": false
1556
+ },
1557
+ "phoneNumberId": {
1558
+ "type": "string",
1559
+ "description": "DEPRECATED, use \"from\" instead. OpenPhone phone number ID to send a message from",
1560
+ "optional": false
1561
+ },
1562
+ "from": {
1563
+ "type": "string",
1564
+ "optional": false
1565
+ },
1566
+ "to": {
1567
+ "type": "string",
1568
+ "description": "JSON array",
1569
+ "optional": false
1570
+ },
1571
+ "userId": {
1572
+ "type": "string",
1573
+ "description": "The unique identifier of the OpenPhone user sending the message. If not provided, defaults to the phone number owner.",
1574
+ "optional": false
1575
+ },
1576
+ "setInboxStatus": {
1577
+ "type": "string",
1578
+ "enum": [
1579
+ "done"
1580
+ ],
1581
+ "description": "Used to set the status of the related OpenPhone inbox conversation. The default behavior without setting this parameter will be for the message sent to show up as an open conversation in the user's inbox. Setting the parameter to `'done'` would move the conversation to the Done inbox view.",
1582
+ "optional": false
1583
+ }
1584
+ },
1585
+ "required": [
1586
+ "content",
1587
+ "from",
1588
+ "to"
1589
+ ]
1590
+ },
1591
+ "search": {
1592
+ "capabilities": [
1593
+ "quo-send-message-v1",
1594
+ "sendmessage",
1595
+ "send",
1596
+ "text",
1597
+ "message",
1598
+ "messages"
1599
+ ],
1600
+ "intents": []
1601
+ }
1602
+ },
1603
+ {
1604
+ "name": "quo-get-message-by-id-v1",
1605
+ "description": "Get a message by ID",
1606
+ "schema": {
1607
+ "type": "object",
1608
+ "properties": {
1609
+ "id": {
1610
+ "type": "string",
1611
+ "description": "The unique identifier of a message",
1612
+ "optional": false
1613
+ }
1614
+ },
1615
+ "required": [
1616
+ "id"
1617
+ ]
1618
+ },
1619
+ "search": {
1620
+ "capabilities": [
1621
+ "quo-get-message-by-id-v1",
1622
+ "getmessagebyid",
1623
+ "get",
1624
+ "message",
1625
+ "messages"
1626
+ ],
1627
+ "intents": []
1628
+ }
1629
+ },
1630
+ {
1631
+ "name": "quo-list-phone-numbers-v1",
1632
+ "description": "List phone numbers",
1633
+ "schema": {
1634
+ "type": "object",
1635
+ "properties": {
1636
+ "userId": {
1637
+ "type": "string",
1638
+ "description": "Filter results to return only phone numbers associated with the specified user\"s unique identifier.",
1639
+ "optional": false
1640
+ }
1641
+ }
1642
+ },
1643
+ "search": {
1644
+ "capabilities": [
1645
+ "quo-list-phone-numbers-v1",
1646
+ "listphonenumbers",
1647
+ "list",
1648
+ "phone",
1649
+ "numbers",
1650
+ "phone-numbers"
1651
+ ],
1652
+ "intents": []
1653
+ }
1654
+ },
1655
+ {
1656
+ "name": "quo-get-phone-number-by-id-v1",
1657
+ "description": "Get a phone number by ID",
1658
+ "schema": {
1659
+ "type": "object",
1660
+ "properties": {
1661
+ "phoneNumberId": {
1662
+ "type": "string",
1663
+ "description": "Unique identifier of the phone number.",
1664
+ "optional": false
1665
+ }
1666
+ },
1667
+ "required": [
1668
+ "phoneNumberId"
1669
+ ]
1670
+ },
1671
+ "search": {
1672
+ "capabilities": [
1673
+ "quo-get-phone-number-by-id-v1",
1674
+ "getphonenumberbyid",
1675
+ "get",
1676
+ "phone",
1677
+ "number",
1678
+ "phone-numbers",
1679
+ "phonenumberid",
1680
+ "numbers"
1681
+ ],
1682
+ "intents": []
1683
+ }
1684
+ },
1685
+ {
1686
+ "name": "quo-list-users-v1",
1687
+ "description": "List users",
1688
+ "schema": {
1689
+ "type": "object",
1690
+ "properties": {
1691
+ "maxResults": {
1692
+ "type": "number",
1693
+ "description": "Maximum number of results to return per page.",
1694
+ "optional": false
1695
+ },
1696
+ "pageToken": {
1697
+ "type": "string",
1698
+ "optional": false
1699
+ }
1700
+ },
1701
+ "required": [
1702
+ "maxResults"
1703
+ ]
1704
+ },
1705
+ "search": {
1706
+ "capabilities": [
1707
+ "quo-list-users-v1",
1708
+ "listusers",
1709
+ "list",
1710
+ "users"
1711
+ ],
1712
+ "intents": []
1713
+ }
1714
+ },
1715
+ {
1716
+ "name": "quo-get-user-by-id-v1",
1717
+ "description": "Get a user by ID",
1718
+ "schema": {
1719
+ "type": "object",
1720
+ "properties": {
1721
+ "userId": {
1722
+ "type": "string",
1723
+ "description": "The unique identifier of the user being retrieved.",
1724
+ "optional": false
1725
+ }
1726
+ },
1727
+ "required": [
1728
+ "userId"
1729
+ ]
1730
+ },
1731
+ "search": {
1732
+ "capabilities": [
1733
+ "quo-get-user-by-id-v1",
1734
+ "getuserbyid",
1735
+ "get",
1736
+ "user",
1737
+ "users",
1738
+ "userid"
1739
+ ],
1740
+ "intents": []
1741
+ }
1742
+ },
1743
+ {
1744
+ "name": "quo-list-webhooks-v1",
1745
+ "description": "Lists all webhooks",
1746
+ "schema": {
1747
+ "type": "object",
1748
+ "properties": {
1749
+ "userId": {
1750
+ "type": "string",
1751
+ "description": "The unique identifier the user. Defaults to the workspace owner.",
1752
+ "optional": false
1753
+ }
1754
+ }
1755
+ },
1756
+ "search": {
1757
+ "capabilities": [
1758
+ "quo-list-webhooks-v1",
1759
+ "listwebhooks",
1760
+ "lists",
1761
+ "all",
1762
+ "webhooks"
1763
+ ],
1764
+ "intents": []
1765
+ }
1766
+ },
1767
+ {
1768
+ "name": "quo-get-webhook-by-id-v1",
1769
+ "description": "Get a webhook by ID",
1770
+ "schema": {
1771
+ "type": "object",
1772
+ "properties": {
1773
+ "id": {
1774
+ "type": "string",
1775
+ "description": "The unique identifier of a webhook",
1776
+ "optional": false
1777
+ }
1778
+ },
1779
+ "required": [
1780
+ "id"
1781
+ ]
1782
+ },
1783
+ "search": {
1784
+ "capabilities": [
1785
+ "quo-get-webhook-by-id-v1",
1786
+ "getwebhookbyid",
1787
+ "get",
1788
+ "webhook",
1789
+ "webhooks"
1790
+ ],
1791
+ "intents": []
1792
+ }
1793
+ },
1794
+ {
1795
+ "name": "quo-delete-webhook-by-id-v1",
1796
+ "description": "Delete a webhook by ID",
1797
+ "schema": {
1798
+ "type": "object",
1799
+ "properties": {
1800
+ "id": {
1801
+ "type": "string",
1802
+ "description": "The unique identifier of a webhook",
1803
+ "optional": false
1804
+ }
1805
+ },
1806
+ "required": [
1807
+ "id"
1808
+ ]
1809
+ },
1810
+ "search": {
1811
+ "capabilities": [
1812
+ "quo-delete-webhook-by-id-v1",
1813
+ "deletewebhookbyid",
1814
+ "delete",
1815
+ "webhook",
1816
+ "webhooks"
1817
+ ],
1818
+ "intents": []
1819
+ }
1820
+ },
1821
+ {
1822
+ "name": "quo-create-message-webhook-v1",
1823
+ "description": "Create a new webhook for messages",
1824
+ "schema": {
1825
+ "type": "object",
1826
+ "properties": {
1827
+ "events": {
1828
+ "type": "string",
1829
+ "optional": false
1830
+ },
1831
+ "label": {
1832
+ "type": "string",
1833
+ "description": "Webhook's label",
1834
+ "optional": false
1835
+ },
1836
+ "resourceIds": {
1837
+ "type": "string",
1838
+ "optional": false
1839
+ },
1840
+ "status": {
1841
+ "type": "string",
1842
+ "enum": [
1843
+ "enabled",
1844
+ "disabled"
1845
+ ],
1846
+ "description": "The status of the webhook.",
1847
+ "optional": false
1848
+ },
1849
+ "url": {
1850
+ "type": "string",
1851
+ "description": "The endpoint that receives events from the webhook.",
1852
+ "optional": false
1853
+ },
1854
+ "userId": {
1855
+ "type": "string",
1856
+ "description": "The unique identifier of the user that creates the webhook. If not provided, default to workspace owner.",
1857
+ "optional": false
1858
+ }
1859
+ },
1860
+ "required": [
1861
+ "events",
1862
+ "url"
1863
+ ]
1864
+ },
1865
+ "search": {
1866
+ "capabilities": [
1867
+ "quo-create-message-webhook-v1",
1868
+ "createmessagewebhook",
1869
+ "create",
1870
+ "new",
1871
+ "webhook",
1872
+ "for",
1873
+ "messages",
1874
+ "webhooks"
1875
+ ],
1876
+ "intents": []
1877
+ }
1878
+ },
1879
+ {
1880
+ "name": "quo-create-call-webhook-v1",
1881
+ "description": "Create a new webhook for calls",
1882
+ "schema": {
1883
+ "type": "object",
1884
+ "properties": {
1885
+ "url": {
1886
+ "type": "string",
1887
+ "description": "The endpoint that receives events from the webhook.",
1888
+ "optional": false
1889
+ },
1890
+ "events": {
1891
+ "type": "string",
1892
+ "optional": false
1893
+ },
1894
+ "resourceIds": {
1895
+ "type": "string",
1896
+ "optional": false
1897
+ },
1898
+ "userId": {
1899
+ "type": "string",
1900
+ "description": "The unique identifier of the user that creates the webhook. If not provided, default to workspace owner.",
1901
+ "optional": false
1902
+ },
1903
+ "label": {
1904
+ "type": "string",
1905
+ "description": "Webhook's label",
1906
+ "optional": false
1907
+ },
1908
+ "status": {
1909
+ "type": "string",
1910
+ "enum": [
1911
+ "enabled",
1912
+ "disabled"
1913
+ ],
1914
+ "description": "The status of the webhook.",
1915
+ "optional": false
1916
+ }
1917
+ },
1918
+ "required": [
1919
+ "url",
1920
+ "events"
1921
+ ]
1922
+ },
1923
+ "search": {
1924
+ "capabilities": [
1925
+ "quo-create-call-webhook-v1",
1926
+ "createcallwebhook",
1927
+ "create",
1928
+ "new",
1929
+ "webhook",
1930
+ "for",
1931
+ "calls",
1932
+ "webhooks"
1933
+ ],
1934
+ "intents": []
1935
+ }
1936
+ },
1937
+ {
1938
+ "name": "quo-create-call-summary-webhook-v1",
1939
+ "description": "Create a new webhook for call summaries",
1940
+ "schema": {
1941
+ "type": "object",
1942
+ "properties": {
1943
+ "events": {
1944
+ "type": "string",
1945
+ "optional": false
1946
+ },
1947
+ "label": {
1948
+ "type": "string",
1949
+ "description": "Webhook's label",
1950
+ "optional": false
1951
+ },
1952
+ "resourceIds": {
1953
+ "type": "string",
1954
+ "optional": false
1955
+ },
1956
+ "status": {
1957
+ "type": "string",
1958
+ "enum": [
1959
+ "enabled",
1960
+ "disabled"
1961
+ ],
1962
+ "description": "The status of the webhook.",
1963
+ "optional": false
1964
+ },
1965
+ "url": {
1966
+ "type": "string",
1967
+ "description": "The endpoint that receives events from the webhook.",
1968
+ "optional": false
1969
+ },
1970
+ "userId": {
1971
+ "type": "string",
1972
+ "description": "The unique identifier of the user that creates the webhook. If not provided, default to workspace owner.",
1973
+ "optional": false
1974
+ }
1975
+ },
1976
+ "required": [
1977
+ "events",
1978
+ "url"
1979
+ ]
1980
+ },
1981
+ "search": {
1982
+ "capabilities": [
1983
+ "quo-create-call-summary-webhook-v1",
1984
+ "createcallsummarywebhook",
1985
+ "create",
1986
+ "new",
1987
+ "webhook",
1988
+ "for",
1989
+ "call",
1990
+ "summaries",
1991
+ "webhooks",
1992
+ "call-summaries"
1993
+ ],
1994
+ "intents": []
1995
+ }
1996
+ },
1997
+ {
1998
+ "name": "quo-create-call-transcript-webhook-v1",
1999
+ "description": "Create a new webhook for call transcripts",
2000
+ "schema": {
2001
+ "type": "object",
2002
+ "properties": {
2003
+ "events": {
2004
+ "type": "string",
2005
+ "optional": false
2006
+ },
2007
+ "label": {
2008
+ "type": "string",
2009
+ "description": "The webhook's label.",
2010
+ "optional": false
2011
+ },
2012
+ "resourceIds": {
2013
+ "type": "string",
2014
+ "optional": false
2015
+ },
2016
+ "status": {
2017
+ "type": "string",
2018
+ "enum": [
2019
+ "enabled",
2020
+ "disabled"
2021
+ ],
2022
+ "description": "The status of the webhook.",
2023
+ "optional": false
2024
+ },
2025
+ "url": {
2026
+ "type": "string",
2027
+ "description": "The endpoint that receives events from the webhook.",
2028
+ "optional": false
2029
+ },
2030
+ "userId": {
2031
+ "type": "string",
2032
+ "description": "The ID of the user that creates the webhook. If not provided, default to workspace owner.",
2033
+ "optional": false
2034
+ }
2035
+ },
2036
+ "required": [
2037
+ "events",
2038
+ "url"
2039
+ ]
2040
+ },
2041
+ "search": {
2042
+ "capabilities": [
2043
+ "quo-create-call-transcript-webhook-v1",
2044
+ "createcalltranscriptwebhook",
2045
+ "create",
2046
+ "new",
2047
+ "webhook",
2048
+ "for",
2049
+ "call",
2050
+ "transcripts",
2051
+ "webhooks",
2052
+ "call-transcripts"
2053
+ ],
2054
+ "intents": []
2055
+ }
2056
+ },
2057
+ {
2058
+ "name": "quo-test-connection",
2059
+ "description": "Test API connection and verify credentials are configured",
2060
+ "schema": {
2061
+ "type": "object",
2062
+ "properties": {}
2063
+ },
2064
+ "search": {
2065
+ "capabilities": [
2066
+ "quo",
2067
+ "test",
2068
+ "connection",
2069
+ "health"
2070
+ ],
2071
+ "intents": [
2072
+ "connection"
2073
+ ]
2074
+ }
2075
+ }
2076
+ ]
2077
+
2078
+
2079
+ export default openAPITools