@automate.ax/integration-contracts 0.87.7 → 0.88.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,995 @@
1
+ import * as z from "zod"
2
+ import { CLOSE_OBJECT_SCHEMA, CLOSE_VALUE_SCHEMA } from "./api"
3
+
4
+ export const CLOSE_DATE_SCHEMA = z
5
+ .union([
6
+ z.date(),
7
+ z.string().refine((value) => !Number.isNaN(Date.parse(value)), {
8
+ message: "Expected a Close date or datetime.",
9
+ }),
10
+ ])
11
+ .transform((value) => (value instanceof Date ? value : new Date(value)))
12
+ const DATE_SCHEMA = CLOSE_DATE_SCHEMA
13
+ const NULLABLE_DATE_SCHEMA = DATE_SCHEMA.nullable()
14
+
15
+ export const CLOSE_ADDRESS_SCHEMA = z.object({
16
+ address1: z.string().nullable(),
17
+ address2: z.string().nullable(),
18
+ city: z.string().nullable(),
19
+ country: z.string().nullable(),
20
+ label: z.string().nullable(),
21
+ state: z.string().nullable(),
22
+ tzIds: z.string().array().optional(),
23
+ zipcode: z.string().nullable(),
24
+ })
25
+
26
+ export const CLOSE_CONTACT_EMAIL_SCHEMA = z.object({
27
+ email: z.email(),
28
+ isUnsubscribed: z.boolean().prefault(false),
29
+ type: z.string(),
30
+ })
31
+
32
+ export const CLOSE_CONTACT_PHONE_SCHEMA = z.object({
33
+ country: z.string().nullable().optional(),
34
+ outboundSmsBlocked: z.boolean().optional(),
35
+ phone: z.string(),
36
+ phoneFormatted: z.string().optional(),
37
+ tzIds: z.string().array().optional(),
38
+ type: z.string(),
39
+ })
40
+
41
+ export const CLOSE_CONTACT_URL_SCHEMA = z.object({
42
+ type: z.string(),
43
+ url: z.string(),
44
+ })
45
+
46
+ export const CLOSE_LEAD_SCHEMA = z.object({
47
+ addresses: CLOSE_ADDRESS_SCHEMA.array().prefault([]),
48
+ contactIds: z.string().array(),
49
+ createdAt: DATE_SCHEMA,
50
+ createdBy: z.string().nullable(),
51
+ customFields: z.record(z.string(), z.json()).prefault({}),
52
+ description: z.string().nullable(),
53
+ displayName: z.string().optional(),
54
+ htmlUrl: z.url(),
55
+ id: z.string(),
56
+ name: z.string().nullable(),
57
+ organizationId: z.string(),
58
+ source: z.string().nullable().optional(),
59
+ statusId: z.string(),
60
+ statusLabel: z.string().optional(),
61
+ updatedAt: DATE_SCHEMA,
62
+ updatedBy: z.string().nullable(),
63
+ url: z.string().nullable(),
64
+ })
65
+
66
+ export const CLOSE_CONTACT_SCHEMA = z.object({
67
+ createdAt: DATE_SCHEMA,
68
+ createdBy: z.string().nullable(),
69
+ customFields: z.record(z.string(), z.json()).prefault({}),
70
+ displayName: z.string(),
71
+ emails: CLOSE_CONTACT_EMAIL_SCHEMA.array().prefault([]),
72
+ id: z.string(),
73
+ leadId: z.string().nullable(),
74
+ name: z.string().nullable(),
75
+ organizationId: z.string(),
76
+ phones: CLOSE_CONTACT_PHONE_SCHEMA.array().prefault([]),
77
+ title: z.string().nullable(),
78
+ updatedAt: DATE_SCHEMA,
79
+ updatedBy: z.string().nullable(),
80
+ urls: CLOSE_CONTACT_URL_SCHEMA.array().prefault([]),
81
+ })
82
+
83
+ export const CLOSE_OPPORTUNITY_STATUS_TYPE_SCHEMA = z.enum([
84
+ "active",
85
+ "lost",
86
+ "won",
87
+ ])
88
+
89
+ export const CLOSE_ATTACHMENT_SCHEMA = z.object({
90
+ contentType: z.string().nullable(),
91
+ filename: z.string().nullable(),
92
+ size: z.number().int().nullable(),
93
+ thumbnailUrl: z.url().nullable().optional(),
94
+ url: z.url(),
95
+ })
96
+
97
+ const CLOSE_OPPORTUNITY_SUGGESTED_ACTION_SCHEMA = z.discriminatedUnion(
98
+ "action",
99
+ [
100
+ z.object({
101
+ action: z.literal("change_status"),
102
+ details: z.object({ statusId: z.string() }).nullable(),
103
+ justification: z.string(),
104
+ }),
105
+ z.object({
106
+ action: z.literal("adjust_close_date"),
107
+ details: z.object({ closeDate: DATE_SCHEMA }).nullable(),
108
+ justification: z.string(),
109
+ }),
110
+ z.object({
111
+ action: z.literal("follow_up_email"),
112
+ details: z
113
+ .object({
114
+ contactId: z.string(),
115
+ messageDraft: z.string(),
116
+ subjectDraft: z.string(),
117
+ })
118
+ .nullable(),
119
+ justification: z.string(),
120
+ }),
121
+ z.object({
122
+ action: z.literal("follow_up_sms"),
123
+ details: z
124
+ .object({ contactId: z.string(), messageDraft: z.string() })
125
+ .nullable(),
126
+ justification: z.string(),
127
+ }),
128
+ z.object({
129
+ action: z.literal("follow_up_call"),
130
+ details: z
131
+ .object({ callPlan: z.string(), contactId: z.string() })
132
+ .nullable(),
133
+ justification: z.string(),
134
+ }),
135
+ ],
136
+ )
137
+
138
+ export const CLOSE_OPPORTUNITY_SCHEMA = z.object({
139
+ annualizedExpectedValue: z.number().int().nullable(),
140
+ annualizedValue: z.number().int().nullable(),
141
+ attachments: CLOSE_ATTACHMENT_SCHEMA.array().optional(),
142
+ commentSummary: z
143
+ .object({ commentCount: z.number().int(), threadId: z.string() })
144
+ .nullable()
145
+ .optional(),
146
+ confidence: z.number().int().min(0).max(100),
147
+ contactId: z.string().nullable(),
148
+ contactName: z.string().nullable().optional(),
149
+ createdAt: DATE_SCHEMA,
150
+ createdBy: z.string().nullable(),
151
+ createdByName: z.string().nullable().optional(),
152
+ customFields: z.record(z.string(), z.json()).prefault({}),
153
+ dateLost: NULLABLE_DATE_SCHEMA,
154
+ dateWon: NULLABLE_DATE_SCHEMA,
155
+ expectedValue: z.number().int().nullable(),
156
+ id: z.string(),
157
+ integrationLinks: z
158
+ .object({ name: z.string(), url: z.url() })
159
+ .array()
160
+ .optional(),
161
+ isStalled: z.boolean().optional(),
162
+ leadId: z.string(),
163
+ leadName: z.string().nullable().optional(),
164
+ leadPrimaryEmail: CLOSE_CONTACT_EMAIL_SCHEMA.nullable().optional(),
165
+ leadPrimaryPhone: CLOSE_CONTACT_PHONE_SCHEMA.array().nullable().optional(),
166
+ note: z.string().nullable(),
167
+ noteHtml: z.string().nullable(),
168
+ organizationId: z.string(),
169
+ pipelineId: z.string().nullable().optional(),
170
+ pipelineName: z.string().nullable().optional(),
171
+ stallStatus: z
172
+ .object({
173
+ communicationIssue: z.enum([
174
+ "no_issue",
175
+ "cant_get_in_touch",
176
+ "no_communication_attempts",
177
+ ]),
178
+ nextAction: z.object({
179
+ action: z.enum([
180
+ "mark_as_lost",
181
+ "change_status",
182
+ "follow_up",
183
+ "adjust_close_date",
184
+ "ask_someone_else_to_reach_out",
185
+ "change_communication_method",
186
+ ]),
187
+ justification: z.string(),
188
+ }),
189
+ })
190
+ .nullable()
191
+ .optional(),
192
+ statusId: z.string(),
193
+ statusDisplayName: z.string().optional(),
194
+ statusLabel: z.string().optional(),
195
+ statusType: CLOSE_OPPORTUNITY_STATUS_TYPE_SCHEMA.optional(),
196
+ suggestedAction:
197
+ CLOSE_OPPORTUNITY_SUGGESTED_ACTION_SCHEMA.nullable().optional(),
198
+ updatedAt: DATE_SCHEMA,
199
+ updatedBy: z.string().nullable(),
200
+ updatedByName: z.string().nullable().optional(),
201
+ userId: z.string(),
202
+ userName: z.string().nullable().optional(),
203
+ value: z.number().int().nullable(),
204
+ valueCurrency: z.string().nullable().optional(),
205
+ valueFormatted: z.string().nullable().optional(),
206
+ valuePeriod: z.enum(["annual", "monthly", "one_time"]),
207
+ })
208
+
209
+ export const CLOSE_OPPORTUNITY_PAGE_SCHEMA = z.object({
210
+ countByValuePeriod: z.record(z.string(), z.number().int().nonnegative()),
211
+ data: CLOSE_OPPORTUNITY_SCHEMA.array(),
212
+ expectedValueAnnual: z.number().int(),
213
+ expectedValueAnnualFormatted: z.string(),
214
+ expectedValueAnnualized: z.number().int(),
215
+ expectedValueAnnualizedFormatted: z.string(),
216
+ expectedValueMonthly: z.number().int(),
217
+ expectedValueMonthlyFormatted: z.string(),
218
+ expectedValueOneTime: z.number().int(),
219
+ expectedValueOneTimeFormatted: z.string(),
220
+ hasMore: z.boolean(),
221
+ totalResults: z.number().int().nonnegative(),
222
+ totalValueAnnual: z.number().int(),
223
+ totalValueAnnualFormatted: z.string(),
224
+ totalValueAnnualized: z.number().int(),
225
+ totalValueAnnualizedFormatted: z.string(),
226
+ totalValueMonthly: z.number().int(),
227
+ totalValueMonthlyFormatted: z.string(),
228
+ totalValueOneTime: z.number().int(),
229
+ totalValueOneTimeFormatted: z.string(),
230
+ })
231
+
232
+ const CLOSE_TASK_FIELDS = {
233
+ assignedTo: z.string().nullable(),
234
+ assignedToName: z.string().nullable().optional(),
235
+ contactId: z.string().nullable(),
236
+ contactName: z.string().nullable().optional(),
237
+ createdAt: DATE_SCHEMA,
238
+ createdBy: z.string().nullable(),
239
+ createdByName: z.string().nullable().optional(),
240
+ date: NULLABLE_DATE_SCHEMA,
241
+ dueDate: NULLABLE_DATE_SCHEMA.optional(),
242
+ id: z.string(),
243
+ isComplete: z.boolean(),
244
+ isDateless: z.boolean().optional(),
245
+ leadId: z.string().nullable(),
246
+ leadName: z.string().nullable().optional(),
247
+ objectId: z.string().nullable().optional(),
248
+ objectType: z.string().nullable().optional(),
249
+ organizationId: z.string(),
250
+ priority: z.enum(["high", "medium"]).nullable().optional(),
251
+ text: z.string().nullable().optional(),
252
+ updatedAt: DATE_SCHEMA,
253
+ updatedBy: z.string().nullable(),
254
+ updatedByName: z.string().nullable().optional(),
255
+ view: z.enum(["archive", "future", "inbox"]).optional(),
256
+ }
257
+
258
+ const CLOSE_TASK_PHONE_FIELDS = {
259
+ localPhone: z.string().nullable().optional(),
260
+ phone: z.string().nullable().optional(),
261
+ phoneFormatted: z.string().nullable().optional(),
262
+ phoneNumberDescription: z.string().nullable().optional(),
263
+ }
264
+
265
+ export const CLOSE_TASK_SCHEMA = z.discriminatedUnion("type", [
266
+ z.object({ ...CLOSE_TASK_FIELDS, type: z.literal("lead") }),
267
+ z.object({
268
+ ...CLOSE_TASK_FIELDS,
269
+ ...CLOSE_TASK_PHONE_FIELDS,
270
+ type: z.literal("missed_call"),
271
+ }),
272
+ z.object({
273
+ ...CLOSE_TASK_FIELDS,
274
+ ...CLOSE_TASK_PHONE_FIELDS,
275
+ type: z.literal("voicemail"),
276
+ voicemailDuration: z.number().int().nonnegative().optional(),
277
+ voicemailUrl: z.url().optional(),
278
+ }),
279
+ z.object({
280
+ ...CLOSE_TASK_FIELDS,
281
+ bodyPreview: z.string().nullable().optional(),
282
+ emails: z.string().array().optional(),
283
+ subject: z.string().nullable().optional(),
284
+ type: z.literal("incoming_email"),
285
+ }),
286
+ z.object({
287
+ ...CLOSE_TASK_FIELDS,
288
+ bodyPreview: z.string().nullable().optional(),
289
+ emailId: z.string().optional(),
290
+ subject: z.string().nullable().optional(),
291
+ type: z.literal("email_followup"),
292
+ }),
293
+ z.object({
294
+ ...CLOSE_TASK_FIELDS,
295
+ ...CLOSE_TASK_PHONE_FIELDS,
296
+ recordingUrl: z.url().nullable().optional(),
297
+ type: z.literal("answered_detached_call"),
298
+ }),
299
+ z.object({
300
+ ...CLOSE_TASK_FIELDS,
301
+ opportunityNote: z.string().nullable().optional(),
302
+ opportunityValue: z.number().int().nullable().optional(),
303
+ opportunityValueCurrency: z.string().nullable().optional(),
304
+ opportunityValueFormatted: z.string().nullable().optional(),
305
+ opportunityValuePeriod: z
306
+ .enum(["annual", "monthly", "one_time"])
307
+ .nullable()
308
+ .optional(),
309
+ type: z.literal("opportunity_due"),
310
+ }),
311
+ z.object({
312
+ ...CLOSE_TASK_FIELDS,
313
+ attachments: z
314
+ .object({
315
+ contentType: z.string(),
316
+ filename: z.string(),
317
+ mediaId: z.string(),
318
+ size: z.number().int().nonnegative(),
319
+ thumbnailUrl: z.url().nullable().optional(),
320
+ url: z.url(),
321
+ })
322
+ .array()
323
+ .optional(),
324
+ localPhone: z.string().nullable().optional(),
325
+ remotePhone: z.string().nullable().optional(),
326
+ remotePhoneDescription: z.string().nullable().optional(),
327
+ remotePhoneFormatted: z.string().nullable().optional(),
328
+ type: z.literal("incoming_sms"),
329
+ }),
330
+ z.object({
331
+ ...CLOSE_TASK_FIELDS,
332
+ agentConfigId: z.string().nullable().optional(),
333
+ deduplicationKey: z.string().nullable().optional(),
334
+ isPrimaryLeadNotification: z.boolean().optional(),
335
+ resolution: z.string().nullable().optional(),
336
+ sequenceId: z.string().nullable().optional(),
337
+ sequenceSubscriptionId: z.string().nullable().optional(),
338
+ stepId: z.string().nullable().optional(),
339
+ type: z.literal("outgoing_call"),
340
+ }),
341
+ ])
342
+
343
+ const CLOSE_CREATION_SOURCE_SCHEMA = z.enum([
344
+ "ui",
345
+ "api",
346
+ "import",
347
+ "clipper",
348
+ "email",
349
+ "suggestion",
350
+ "segment-integration",
351
+ "customerio-integration",
352
+ "calendly-integration",
353
+ "ai",
354
+ "whatsapp",
355
+ "webform",
356
+ ])
357
+
358
+ export const CLOSE_NOTE_SCHEMA = z.object({
359
+ activityAt: NULLABLE_DATE_SCHEMA,
360
+ attachments: CLOSE_ATTACHMENT_SCHEMA.array(),
361
+ contactId: z.string().nullable(),
362
+ createdAt: DATE_SCHEMA,
363
+ createdBy: z.string().nullable(),
364
+ id: z.string(),
365
+ leadId: z.string().nullable(),
366
+ note: z.string(),
367
+ noteHtml: z.string(),
368
+ noteMentions: z.string().array(),
369
+ organizationId: z.string(),
370
+ pinned: z.boolean(),
371
+ pinnedAt: NULLABLE_DATE_SCHEMA,
372
+ source: CLOSE_CREATION_SOURCE_SCHEMA.nullable(),
373
+ title: z.string().nullable(),
374
+ type: z.literal("Note"),
375
+ updatedAt: DATE_SCHEMA,
376
+ updatedBy: z.string().nullable(),
377
+ userId: z.string().nullable(),
378
+ users: z.string().array(),
379
+ })
380
+
381
+ const CLOSE_ACTIVITY_FIELDS = {
382
+ activityAt: NULLABLE_DATE_SCHEMA.optional(),
383
+ contactId: z.string().nullable().optional(),
384
+ createdAt: DATE_SCHEMA,
385
+ createdBy: z.string().nullable(),
386
+ createdByName: z.string().nullable().optional(),
387
+ id: z.string(),
388
+ leadId: z.string().nullable(),
389
+ organizationId: z.string(),
390
+ source: z.string().nullable().optional(),
391
+ updatedAt: DATE_SCHEMA,
392
+ updatedBy: z.string().nullable(),
393
+ updatedByName: z.string().nullable().optional(),
394
+ userId: z.string().nullable().optional(),
395
+ userName: z.string().nullable().optional(),
396
+ users: z.string().array().prefault([]),
397
+ }
398
+ const CLOSE_EXACT_ACTIVITY_FIELDS = {
399
+ ...CLOSE_ACTIVITY_FIELDS,
400
+ activityAt: NULLABLE_DATE_SCHEMA,
401
+ contactId: z.string().nullable(),
402
+ userId: z.string().nullable(),
403
+ }
404
+ const CLOSE_TASK_COMPLETED_ACTIVITY_FIELDS = {
405
+ ...CLOSE_ACTIVITY_FIELDS,
406
+ activityAt: NULLABLE_DATE_SCHEMA,
407
+ userId: z.string().nullable(),
408
+ }
409
+
410
+ export const CLOSE_CALL_SCHEMA = z
411
+ .object({
412
+ ...CLOSE_ACTIVITY_FIELDS,
413
+ activityAt: NULLABLE_DATE_SCHEMA,
414
+ callMethod: z.string().nullable().optional(),
415
+ contactId: z.string().nullable(),
416
+ cost: z.string().nullable().optional(),
417
+ dialerId: z.string().nullable().optional(),
418
+ dialerSavedSearchId: z.string().nullable().optional(),
419
+ direction: z.enum(["inbound", "outbound"]),
420
+ disposition: z.string().nullable().optional(),
421
+ duration: z.number().int().nonnegative().nullable(),
422
+ localCountryIso: z.string().nullable().optional(),
423
+ localPhone: z.string().nullable().optional(),
424
+ localPhoneFormatted: z.string().nullable().optional(),
425
+ note: z.string().nullable(),
426
+ noteHtml: z.string().nullable(),
427
+ outcomeId: z.string().nullable(),
428
+ phone: z.string().nullable(),
429
+ recordingUrl: z.url().nullable(),
430
+ remoteCountryIso: z.string().nullable().optional(),
431
+ remotePhone: z.string().nullable().optional(),
432
+ remotePhoneFormatted: z.string().nullable().optional(),
433
+ source: z.enum(["Close.io", "External"]),
434
+ status: z.enum([
435
+ "busy",
436
+ "cancel",
437
+ "completed",
438
+ "created",
439
+ "failed",
440
+ "in-progress",
441
+ "no-answer",
442
+ "timeout",
443
+ ]),
444
+ type: z.literal("Call"),
445
+ userId: z.string().nullable(),
446
+ voicemailDuration: z.number().int().nonnegative().nullable().optional(),
447
+ voicemailUrl: z.url().nullable().optional(),
448
+ })
449
+ .catchall(CLOSE_VALUE_SCHEMA)
450
+
451
+ export const CLOSE_EMAIL_SCHEMA = z
452
+ .object({
453
+ ...CLOSE_ACTIVITY_FIELDS,
454
+ activityAt: NULLABLE_DATE_SCHEMA,
455
+ attachments: CLOSE_ATTACHMENT_SCHEMA.array().nullable().optional(),
456
+ bcc: z.string().array().prefault([]),
457
+ bodyHtml: z.string().nullable(),
458
+ bodyText: z.string().nullable(),
459
+ bulkEmailActionId: z.string().nullable(),
460
+ cc: z.string().array().prefault([]),
461
+ contactId: z.string().nullable(),
462
+ dateScheduled: NULLABLE_DATE_SCHEMA,
463
+ dateSent: NULLABLE_DATE_SCHEMA,
464
+ direction: z.enum(["incoming", "outgoing"]).nullable(),
465
+ emailAccountId: z.string().nullable().optional(),
466
+ followupSequenceAddCcBcc: z.boolean(),
467
+ followupSequenceDelay: z.number().int().nullable(),
468
+ hasReply: z.boolean(),
469
+ inReplyToId: z.string().nullable(),
470
+ messageIds: z.string().array().prefault([]),
471
+ needSmtpCredentials: z.boolean(),
472
+ opens: z
473
+ .object({
474
+ ipAddress: z.string().nullable(),
475
+ openedAt: DATE_SCHEMA,
476
+ openedBy: z.string().nullable(),
477
+ userAgent: z.string().nullable(),
478
+ })
479
+ .array()
480
+ .nullable()
481
+ .optional(),
482
+ opensSummary: z.string().nullable(),
483
+ references: z.string().array().prefault([]),
484
+ sendAsId: z.string().nullable(),
485
+ sendAttempts: z
486
+ .record(z.string(), z.string())
487
+ .array()
488
+ .nullable()
489
+ .optional(),
490
+ sender: z.string().nullable(),
491
+ sequenceId: z.string().nullable().optional(),
492
+ sequenceName: z.string().nullable().optional(),
493
+ sequenceSubscriptionId: z.string().nullable().optional(),
494
+ status: z.enum(["draft", "error", "inbox", "outbox", "scheduled", "sent"]),
495
+ subject: z.string().nullable(),
496
+ templateId: z.string().nullable(),
497
+ threadId: z.string().nullable(),
498
+ to: z.string().array().prefault([]),
499
+ type: z.literal("Email"),
500
+ userId: z.string().nullable(),
501
+ })
502
+ .catchall(CLOSE_VALUE_SCHEMA)
503
+
504
+ export const CLOSE_SMS_SCHEMA = z
505
+ .object({
506
+ ...CLOSE_ACTIVITY_FIELDS,
507
+ activityAt: NULLABLE_DATE_SCHEMA,
508
+ attachments: CLOSE_ATTACHMENT_SCHEMA.array().nullable().optional(),
509
+ contactId: z.string().nullable(),
510
+ cost: z.string().nullable(),
511
+ dateScheduled: NULLABLE_DATE_SCHEMA,
512
+ dateSent: NULLABLE_DATE_SCHEMA,
513
+ direction: z.enum(["inbound", "outbound"]),
514
+ errorMessage: z.string().nullable(),
515
+ localCountryIso: z.string().nullable(),
516
+ localPhone: z.string().nullable(),
517
+ localPhoneFormatted: z.string().nullable(),
518
+ remoteCountryIso: z.string().nullable(),
519
+ remotePhone: z.string().nullable(),
520
+ remotePhoneFormatted: z.string().nullable(),
521
+ source: z.enum(["Close.io", "External"]),
522
+ status: z.enum(["draft", "error", "inbox", "outbox", "scheduled", "sent"]),
523
+ templateId: z.string().nullable(),
524
+ text: z.string().nullable(),
525
+ type: z.literal("SMS"),
526
+ userId: z.string().nullable(),
527
+ })
528
+ .catchall(CLOSE_VALUE_SCHEMA)
529
+
530
+ export const CLOSE_MEETING_SCHEMA = z
531
+ .object({
532
+ ...CLOSE_ACTIVITY_FIELDS,
533
+ actualDuration: z.number().int().nonnegative().nullable(),
534
+ attachedCallIds: z.string().array().prefault([]),
535
+ attendees: CLOSE_OBJECT_SCHEMA.array().prefault([]),
536
+ calendarEventLink: z.url().nullable(),
537
+ calendarEventUids: z.string().array().prefault([]),
538
+ conferenceLinks: CLOSE_OBJECT_SCHEMA.array().prefault([]),
539
+ connectedAccountId: z.string().nullable(),
540
+ duration: z.number().int().nonnegative(),
541
+ endsAt: DATE_SCHEMA,
542
+ integrations: CLOSE_OBJECT_SCHEMA.array().prefault([]),
543
+ isRecurring: z.boolean(),
544
+ location: z.string().nullable(),
545
+ note: z.string().nullable(),
546
+ outcomeId: z.string().nullable(),
547
+ providerCalendarEventId: z.string().nullable(),
548
+ providerCalendarIds: z.string().array().prefault([]),
549
+ providerCalendarType: z.enum(["google", "microsoft"]).nullable(),
550
+ source: z.enum(["calendar", "manual"]),
551
+ startsAt: DATE_SCHEMA,
552
+ status: z
553
+ .enum([
554
+ "upcoming",
555
+ "in-progress",
556
+ "completed",
557
+ "canceled",
558
+ "declined-by-org",
559
+ "declined-by-lead",
560
+ ])
561
+ .nullable(),
562
+ summary: z.object({ html: z.string(), text: z.string() }).nullable(),
563
+ title: z.string().nullable(),
564
+ type: z.literal("Meeting"),
565
+ })
566
+ .catchall(CLOSE_VALUE_SCHEMA)
567
+
568
+ const CLOSE_COMMENT_SUMMARY_SCHEMA = z.object({
569
+ commentCount: z.number().int(),
570
+ threadId: z.string(),
571
+ })
572
+ const CLOSE_CREATED_ACTIVITY_SCHEMA = z.object({
573
+ ...CLOSE_EXACT_ACTIVITY_FIELDS,
574
+ importId: z.string().nullable(),
575
+ source: CLOSE_CREATION_SOURCE_SCHEMA.nullable(),
576
+ type: z.literal("Created"),
577
+ })
578
+ const CLOSE_CUSTOM_ACTIVITY_SCHEMA = z
579
+ .object({
580
+ ...CLOSE_EXACT_ACTIVITY_FIELDS,
581
+ commentSummary: CLOSE_COMMENT_SUMMARY_SCHEMA.nullable().optional(),
582
+ customActivityTypeId: z.string(),
583
+ customFields: z.record(z.string(), z.json()).prefault({}),
584
+ lastPublishedAt: NULLABLE_DATE_SCHEMA,
585
+ mentions: z.string().array(),
586
+ mentionsUpdatedAt: NULLABLE_DATE_SCHEMA,
587
+ pinned: z.boolean(),
588
+ pinnedAt: NULLABLE_DATE_SCHEMA,
589
+ source: CLOSE_CREATION_SOURCE_SCHEMA.nullable(),
590
+ status: z.enum(["draft", "published"]),
591
+ type: z.literal("CustomActivity"),
592
+ })
593
+ .catchall(CLOSE_VALUE_SCHEMA)
594
+ const CLOSE_EMAIL_IDENTITY_SCHEMA = z.object({
595
+ email: z.string(),
596
+ name: z.string(),
597
+ })
598
+ const CLOSE_EMAIL_ENVELOPE_SCHEMA = z.object({
599
+ bcc: CLOSE_EMAIL_IDENTITY_SCHEMA.array(),
600
+ cc: CLOSE_EMAIL_IDENTITY_SCHEMA.array(),
601
+ date: z.string().nullable(),
602
+ from: CLOSE_EMAIL_IDENTITY_SCHEMA.array(),
603
+ inReplyTo: z.string().nullable(),
604
+ isAutoreply: z.boolean(),
605
+ messageId: z.string().nullable(),
606
+ replyTo: CLOSE_EMAIL_IDENTITY_SCHEMA.array(),
607
+ sender: CLOSE_EMAIL_IDENTITY_SCHEMA.array(),
608
+ subject: z.string().nullable(),
609
+ to: CLOSE_EMAIL_IDENTITY_SCHEMA.array(),
610
+ })
611
+ const CLOSE_EMAIL_PREVIEW_SCHEMA = z.object({
612
+ bcc: z.string().array(),
613
+ bodyPreview: z.string().nullable(),
614
+ cc: z.string().array(),
615
+ createdAt: DATE_SCHEMA,
616
+ dateSent: NULLABLE_DATE_SCHEMA,
617
+ direction: z.enum(["incoming", "outgoing"]),
618
+ envelope: CLOSE_EMAIL_ENVELOPE_SCHEMA.nullable(),
619
+ hasAttachments: z.boolean().nullable(),
620
+ id: z.string().nullable(),
621
+ opensSummary: z.string().nullable(),
622
+ sendAsId: z.string().nullable(),
623
+ sender: z.string().nullable(),
624
+ status: z.enum(["draft", "error", "inbox", "outbox", "scheduled", "sent"]),
625
+ subject: z.string().nullable(),
626
+ to: z.string().array(),
627
+ updatedAt: DATE_SCHEMA,
628
+ userId: z.string().nullable(),
629
+ })
630
+ const CLOSE_EMAIL_IN_THREAD_SCHEMA = CLOSE_EMAIL_SCHEMA.extend({
631
+ bodyHtml: z.string().nullable().optional(),
632
+ bodyText: z.string().nullable().optional(),
633
+ })
634
+ const CLOSE_EMAIL_THREAD_SCHEMA = z.object({
635
+ ...CLOSE_EXACT_ACTIVITY_FIELDS,
636
+ emails: CLOSE_EMAIL_IN_THREAD_SCHEMA.array().optional(),
637
+ importance: z
638
+ .discriminatedUnion("type", [
639
+ z.object({
640
+ reason: z.enum([
641
+ "manual",
642
+ "contains-manual-message",
643
+ "most-recent-communication",
644
+ "has-response",
645
+ "whitelisted",
646
+ "by-default",
647
+ "unset-initial-default",
648
+ ]),
649
+ type: z.literal("important"),
650
+ }),
651
+ z.object({
652
+ reason: z.enum([
653
+ "manual",
654
+ "scheduling-emails",
655
+ "automated-outbound",
656
+ "marketing-or-transactional",
657
+ "by-default",
658
+ ]),
659
+ type: z.literal("not_important"),
660
+ }),
661
+ ])
662
+ .optional(),
663
+ latestEmails: CLOSE_EMAIL_PREVIEW_SCHEMA.array().optional(),
664
+ latestNormalizedSubject: z.string().nullable(),
665
+ nEmails: z.number().int().nullable(),
666
+ participants: CLOSE_EMAIL_IDENTITY_SCHEMA.array().optional(),
667
+ summary: z
668
+ .object({
669
+ expiredAt: NULLABLE_DATE_SCHEMA,
670
+ feedback: z
671
+ .object({
672
+ detail: z.string().nullable(),
673
+ givenAt: DATE_SCHEMA,
674
+ rating: z.enum(["positive", "negative"]),
675
+ })
676
+ .optional(),
677
+ generatedAt: NULLABLE_DATE_SCHEMA,
678
+ status: z.enum(["pending", "success", "failure", "expired"]),
679
+ summaryHtml: z.string().nullable(),
680
+ summaryText: z.string().nullable(),
681
+ updatedAt: DATE_SCHEMA,
682
+ })
683
+ .nullable()
684
+ .optional(),
685
+ type: z.literal("EmailThread"),
686
+ })
687
+ const CLOSE_FORM_SUBMISSION_SCHEMA = z.object({
688
+ ...CLOSE_EXACT_ACTIVITY_FIELDS,
689
+ formConfigurationId: z.string(),
690
+ formId: z.string(),
691
+ formName: z.string().nullable().optional(),
692
+ ipAddress: z.string().nullable(),
693
+ origin: z.string().nullable(),
694
+ sourceUrl: z.string().nullable(),
695
+ sourceUrlNormalized: z.string().nullable(),
696
+ type: z.literal("FormSubmission"),
697
+ values: z.record(z.string(), z.union([z.string(), z.boolean(), z.null()])),
698
+ valuesByName: z.record(
699
+ z.string(),
700
+ z.union([z.string(), z.boolean(), z.null()]),
701
+ ),
702
+ })
703
+ const CLOSE_IMPORT_UPDATE_SCHEMA = z.object({
704
+ ...CLOSE_EXACT_ACTIVITY_FIELDS,
705
+ importId: z.string().nullable(),
706
+ reverted: z.boolean(),
707
+ type: z.literal("ImportUpdate"),
708
+ })
709
+ const CLOSE_LEAD_MERGE_SCHEMA = z.object({
710
+ ...CLOSE_EXACT_ACTIVITY_FIELDS,
711
+ destinationDisplayName: z.string().nullable(),
712
+ destinationLeadId: z.string(),
713
+ errorMessage: z.string().nullable(),
714
+ mergeStatus: z.enum(["pending", "in_progress", "completed", "errored"]),
715
+ sourceDisplayName: z.string().nullable(),
716
+ sourceLeadId: z.string(),
717
+ type: z.literal("LeadMerge"),
718
+ })
719
+ const CLOSE_LEAD_STATUS_CHANGE_SCHEMA = z.object({
720
+ ...CLOSE_EXACT_ACTIVITY_FIELDS,
721
+ newStatusId: z.string(),
722
+ newStatusLabel: z.string().optional(),
723
+ oldStatusId: z.string(),
724
+ oldStatusLabel: z.string().optional(),
725
+ pausedSubscriptions: z
726
+ .object({
727
+ contactId: z.string().nullable(),
728
+ contactName: z.string().nullable(),
729
+ id: z.string(),
730
+ sequenceId: z.string(),
731
+ sequenceName: z.string(),
732
+ sequenceStatus: z.string(),
733
+ })
734
+ .array()
735
+ .optional(),
736
+ type: z.literal("LeadStatusChange"),
737
+ })
738
+ const CLOSE_OPPORTUNITY_STATUS_CHANGE_SCHEMA = z.object({
739
+ ...CLOSE_EXACT_ACTIVITY_FIELDS,
740
+ newPipelineId: z.string().optional(),
741
+ newPipelineName: z.string().optional(),
742
+ newStatusId: z.string(),
743
+ newStatusLabel: z.string().optional(),
744
+ newStatusType: CLOSE_OPPORTUNITY_STATUS_TYPE_SCHEMA.optional(),
745
+ oldPipelineId: z.string().optional(),
746
+ oldPipelineName: z.string().optional(),
747
+ oldStatusId: z.string(),
748
+ oldStatusLabel: z.string().optional(),
749
+ oldStatusType: CLOSE_OPPORTUNITY_STATUS_TYPE_SCHEMA.optional(),
750
+ opportunityConfidence: z.number().int().nullable().optional(),
751
+ opportunityDateWon: NULLABLE_DATE_SCHEMA.optional(),
752
+ opportunityId: z.string().nullable(),
753
+ opportunityValue: z.number().int().nullable().optional(),
754
+ opportunityValueCurrency: z.string().nullable().optional(),
755
+ opportunityValueFormatted: z.string().nullable().optional(),
756
+ opportunityValuePeriod: z
757
+ .enum(["annual", "monthly", "one_time"])
758
+ .nullable()
759
+ .optional(),
760
+ type: z.literal("OpportunityStatusChange"),
761
+ })
762
+ const CLOSE_TASK_COMPLETED_ACTIVITY_SCHEMA = z.object({
763
+ ...CLOSE_TASK_COMPLETED_ACTIVITY_FIELDS,
764
+ commentSummary: CLOSE_COMMENT_SUMMARY_SCHEMA.nullable().optional(),
765
+ sequenceId: z.string().nullable().optional(),
766
+ sequenceName: z.string().nullable().optional(),
767
+ sequenceSubscriptionId: z.string().nullable().optional(),
768
+ taskAssignedTo: z.string().nullable().optional(),
769
+ taskAssignedToName: z.string().nullable().optional(),
770
+ taskId: z.string().nullable(),
771
+ taskText: z.string().nullable(),
772
+ type: z.literal("TaskCompleted"),
773
+ })
774
+ const CLOSE_WHATSAPP_MESSAGE_SCHEMA = z.object({
775
+ ...CLOSE_EXACT_ACTIVITY_FIELDS,
776
+ attachments: CLOSE_ATTACHMENT_SCHEMA.array().optional(),
777
+ direction: z.enum(["incoming", "outgoing"]),
778
+ externalWhatsappMessageId: z.string(),
779
+ integrationLink: z.string().nullable(),
780
+ integrationName: z.string().nullable(),
781
+ localPhone: z.string(),
782
+ localPhoneFormatted: z.string(),
783
+ messageHtml: z.string(),
784
+ messageMarkdown: z.string(),
785
+ remotePhone: z.string(),
786
+ remotePhoneFormatted: z.string(),
787
+ responseToId: z.string().nullable(),
788
+ sequenceId: z.string().nullable().optional(),
789
+ sequenceName: z.string().nullable().optional(),
790
+ sequenceSubscriptionId: z.string().nullable().optional(),
791
+ source: CLOSE_CREATION_SOURCE_SCHEMA,
792
+ text: z.string(),
793
+ type: z.literal("WhatsAppMessage"),
794
+ })
795
+ const CLOSE_ACTIVITY_LIST_CREATED_SCHEMA = CLOSE_CREATED_ACTIVITY_SCHEMA.extend(
796
+ {
797
+ importId: z.string().nullable().optional(),
798
+ },
799
+ )
800
+ const CLOSE_ACTIVITY_LIST_EMAIL_SCHEMA = CLOSE_EMAIL_SCHEMA.extend({
801
+ bulkEmailActionId: z.string().nullable().optional(),
802
+ dateSent: NULLABLE_DATE_SCHEMA.optional(),
803
+ hasReply: z.boolean().optional(),
804
+ inReplyToId: z.string().nullable().optional(),
805
+ needSmtpCredentials: z.boolean().optional(),
806
+ opensSummary: z.string().nullable().optional(),
807
+ sendAsId: z.string().nullable().optional(),
808
+ threadId: z.string().nullable().optional(),
809
+ })
810
+ const CLOSE_ACTIVITY_LIST_NOTE_SCHEMA = CLOSE_NOTE_SCHEMA.extend({
811
+ attachments: CLOSE_ATTACHMENT_SCHEMA.array().optional(),
812
+ noteHtml: z.string().optional(),
813
+ pinned: z.boolean().optional(),
814
+ pinnedAt: NULLABLE_DATE_SCHEMA.optional(),
815
+ source: z.string().nullable().optional(),
816
+ title: z.string().nullable().optional(),
817
+ })
818
+
819
+ export const CLOSE_ACTIVITY_SCHEMA = z.discriminatedUnion("type", [
820
+ CLOSE_CALL_SCHEMA,
821
+ CLOSE_ACTIVITY_LIST_EMAIL_SCHEMA,
822
+ CLOSE_MEETING_SCHEMA,
823
+ CLOSE_ACTIVITY_LIST_NOTE_SCHEMA,
824
+ CLOSE_SMS_SCHEMA,
825
+ CLOSE_ACTIVITY_LIST_CREATED_SCHEMA,
826
+ CLOSE_CUSTOM_ACTIVITY_SCHEMA,
827
+ CLOSE_EMAIL_THREAD_SCHEMA,
828
+ CLOSE_FORM_SUBMISSION_SCHEMA,
829
+ CLOSE_IMPORT_UPDATE_SCHEMA,
830
+ CLOSE_LEAD_MERGE_SCHEMA,
831
+ CLOSE_LEAD_STATUS_CHANGE_SCHEMA,
832
+ CLOSE_OPPORTUNITY_STATUS_CHANGE_SCHEMA,
833
+ CLOSE_TASK_COMPLETED_ACTIVITY_SCHEMA,
834
+ CLOSE_WHATSAPP_MESSAGE_SCHEMA,
835
+ ])
836
+
837
+ export const CLOSE_COMMENT_SCHEMA = z.object({
838
+ body: z.string(),
839
+ createdAt: DATE_SCHEMA,
840
+ createdBy: z.string(),
841
+ id: z.string(),
842
+ leadId: z.string(),
843
+ mentions: z.string().array().prefault([]),
844
+ organizationId: z.string(),
845
+ removedAt: NULLABLE_DATE_SCHEMA,
846
+ removedBy: z.string().nullable(),
847
+ threadId: z.string(),
848
+ updatedAt: DATE_SCHEMA,
849
+ updatedBy: z.string(),
850
+ })
851
+
852
+ const CLOSE_SEQUENCE_SCHEDULE_SCHEMA = z.object({
853
+ ranges: z
854
+ .object({
855
+ end: z.string(),
856
+ start: z.string(),
857
+ weekday: z.number().int(),
858
+ })
859
+ .array(),
860
+ })
861
+ const CLOSE_SEQUENCE_STEP_SCHEMA = z.object({
862
+ createdAt: DATE_SCHEMA,
863
+ createdById: z.string(),
864
+ delay: z.number().int().nonnegative(),
865
+ emailTemplateId: z.string().nullable().optional(),
866
+ id: z.string(),
867
+ required: z.boolean(),
868
+ stepAllowedDelay: z.number().int().nonnegative().nullable().optional(),
869
+ stepType: z.enum(["call", "email"]).optional(),
870
+ threading: z.literal("old_thread").nullable().optional(),
871
+ updatedAt: DATE_SCHEMA,
872
+ updatedById: z.string(),
873
+ })
874
+
875
+ export const CLOSE_SEQUENCE_SCHEMA = z.object({
876
+ createdAt: DATE_SCHEMA,
877
+ createdById: z.string(),
878
+ id: z.string(),
879
+ name: z.string(),
880
+ organizationId: z.string(),
881
+ schedule: CLOSE_SEQUENCE_SCHEDULE_SCHEMA.nullable(),
882
+ status: z.string(),
883
+ steps: CLOSE_SEQUENCE_STEP_SCHEMA.array(),
884
+ subscriptionCountsByStatus: z
885
+ .object({
886
+ active: z.number().int().nonnegative(),
887
+ error: z.number().int().nonnegative(),
888
+ finished: z.number().int().nonnegative(),
889
+ goal: z.number().int().nonnegative(),
890
+ paused: z.number().int().nonnegative(),
891
+ })
892
+ .optional(),
893
+ timezone: z.string(),
894
+ updatedAt: DATE_SCHEMA,
895
+ updatedById: z.string(),
896
+ })
897
+
898
+ export const CLOSE_SEQUENCE_SUBSCRIPTION_SCHEMA = z.object({
899
+ callsAssignedTo: z.string().array().prefault([]),
900
+ contactEmail: z.email().nullable(),
901
+ contactId: z.string().nullable(),
902
+ createdAt: DATE_SCHEMA,
903
+ createdById: z.string(),
904
+ id: z.string(),
905
+ leadId: z.string(),
906
+ organizationId: z.string(),
907
+ senderAccountId: z.string().nullable(),
908
+ senderEmail: z.email().nullable(),
909
+ senderName: z.string().nullable(),
910
+ sequenceId: z.string(),
911
+ startDate: NULLABLE_DATE_SCHEMA,
912
+ status: z.enum(["active", "error", "finished", "goal", "paused"]),
913
+ statusReason: z.string().nullable(),
914
+ updatedAt: DATE_SCHEMA,
915
+ updatedById: z.string(),
916
+ })
917
+
918
+ export const CLOSE_USER_SCHEMA = z
919
+ .object({
920
+ createdAt: DATE_SCHEMA,
921
+ email: z.email(),
922
+ firstName: z.string(),
923
+ id: z.string(),
924
+ image: z.url().nullable().optional(),
925
+ lastName: z.string(),
926
+ organizationIds: z.string().array().optional(),
927
+ organizations: z
928
+ .union([z.string(), z.object({ id: z.string() })])
929
+ .array()
930
+ .prefault([]),
931
+ updatedAt: DATE_SCHEMA,
932
+ })
933
+ .transform(({ organizationIds, organizations, ...user }) => ({
934
+ ...user,
935
+ organizationIds:
936
+ organizationIds ??
937
+ organizations.map((organization) =>
938
+ typeof organization === "string" ? organization : organization.id,
939
+ ),
940
+ }))
941
+
942
+ export const CLOSE_LEAD_STATUS_SCHEMA = z.object({
943
+ color: z
944
+ .enum([
945
+ "blue",
946
+ "gray",
947
+ "green",
948
+ "magenta",
949
+ "orange",
950
+ "purple",
951
+ "teal",
952
+ "yellow",
953
+ ])
954
+ .nullable(),
955
+ id: z.string(),
956
+ label: z.string(),
957
+ organizationId: z.string(),
958
+ })
959
+
960
+ export const CLOSE_OPPORTUNITY_STATUS_SCHEMA = z.object({
961
+ id: z.string(),
962
+ label: z.string(),
963
+ organizationId: z.string(),
964
+ pipelineId: z.string().optional(),
965
+ type: CLOSE_OPPORTUNITY_STATUS_TYPE_SCHEMA,
966
+ })
967
+
968
+ export const CLOSE_PIPELINE_SCHEMA = z.object({
969
+ createdAt: DATE_SCHEMA,
970
+ createdBy: z.string().nullable(),
971
+ id: z.string(),
972
+ name: z.string(),
973
+ organizationId: z.string(),
974
+ statuses: z
975
+ .object({
976
+ id: z.string(),
977
+ label: z.string(),
978
+ type: CLOSE_OPPORTUNITY_STATUS_TYPE_SCHEMA,
979
+ })
980
+ .array(),
981
+ updatedAt: DATE_SCHEMA,
982
+ updatedBy: z.string().nullable(),
983
+ })
984
+
985
+ /**
986
+ * Creates a schema for a paginated Close collection response.
987
+ *
988
+ * @param schema - Schema for one collection item.
989
+ */
990
+ export function closePageSchema<TSchema extends z.ZodType>(schema: TSchema) {
991
+ return z.object({
992
+ data: schema.array(),
993
+ hasMore: z.boolean().prefault(false),
994
+ })
995
+ }