@automate.ax/integration-contracts 0.145.2 → 0.146.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,355 @@
1
+ /* oxlint-disable typescript/no-unsafe-type-assertion -- Object.keys and Object.fromEntries erase the exact generated webhook key correlation. */
2
+ import { encodableSchema } from "@automate.ax/codec"
3
+ import * as z from "zod"
4
+
5
+ export const HIGH_LEVEL_TRIGGER_CONFIG_SCHEMA = z.object({})
6
+
7
+ const BASE_EVENT_FIELDS = {
8
+ locationId: z.string().min(1),
9
+ timestamp: z.iso.datetime({ offset: true }),
10
+ webhookId: z.string().min(1),
11
+ } as const
12
+ const CONTACT_FIELDS = {
13
+ ...BASE_EVENT_FIELDS,
14
+ address1: z.string().optional(),
15
+ assignedTo: z.string().optional(),
16
+ attachments: encodableSchema.array().optional(),
17
+ city: z.string().optional(),
18
+ companyName: z.string().optional(),
19
+ country: z.string().optional(),
20
+ customFields: encodableSchema.array().optional(),
21
+ dateAdded: z.string().optional(),
22
+ dateOfBirth: z.string().optional(),
23
+ dnd: z.boolean().optional(),
24
+ dndSettings: encodableSchema.optional(),
25
+ email: z.string().optional(),
26
+ firstName: z.string().optional(),
27
+ id: z.string().min(1),
28
+ lastName: z.string().optional(),
29
+ name: z.string().optional(),
30
+ phone: z.string().optional(),
31
+ postalCode: z.string().optional(),
32
+ source: z.string().optional(),
33
+ state: z.string().optional(),
34
+ tags: z.string().array().optional(),
35
+ website: z.string().optional(),
36
+ } as const
37
+ const OPPORTUNITY_FIELDS = {
38
+ ...BASE_EVENT_FIELDS,
39
+ assignedTo: z.string().optional(),
40
+ contactId: z.string().optional(),
41
+ dateAdded: z.string().optional(),
42
+ id: z.string().min(1),
43
+ monetaryValue: z.number().optional(),
44
+ name: z.string().optional(),
45
+ pipelineId: z.string().optional(),
46
+ pipelineStageId: z.string().optional(),
47
+ source: z.string().optional(),
48
+ status: z.string().optional(),
49
+ } as const
50
+ const TASK_FIELDS = {
51
+ ...BASE_EVENT_FIELDS,
52
+ assignedTo: z.string().optional(),
53
+ body: z.string().optional(),
54
+ contactId: z.string().optional(),
55
+ dateAdded: z.string().optional(),
56
+ dueDate: z.string().optional(),
57
+ id: z.string().min(1),
58
+ title: z.string().optional(),
59
+ } as const
60
+ const NOTE_FIELDS = {
61
+ ...BASE_EVENT_FIELDS,
62
+ body: z.string().optional(),
63
+ contactId: z.string().optional(),
64
+ dateAdded: z.string().optional(),
65
+ id: z.string().min(1),
66
+ } as const
67
+ const MESSAGE_FIELDS = {
68
+ ...BASE_EVENT_FIELDS,
69
+ attachments: encodableSchema.array().optional(),
70
+ bcc: z.union([z.string(), z.string().array()]).optional(),
71
+ bccList: z.string().array().optional(),
72
+ body: z.string().optional(),
73
+ callDuration: z.number().optional(),
74
+ callStatus: z.string().optional(),
75
+ cc: z.union([z.string(), z.string().array()]).optional(),
76
+ ccList: z.string().array().optional(),
77
+ chatWidgetId: z.string().optional(),
78
+ contactId: z.string().optional(),
79
+ contentType: z.string().optional(),
80
+ conversationId: z.string().optional(),
81
+ conversationProviderId: z.string().optional(),
82
+ dateAdded: z.string().optional(),
83
+ direction: z.string().optional(),
84
+ emailMessageId: z.string().optional(),
85
+ from: z.string().optional(),
86
+ messageId: z.string().optional(),
87
+ messageType: z.string().optional(),
88
+ messageTypeId: z.string().optional(),
89
+ messageTypeString: z.string().optional(),
90
+ provider: z.string().optional(),
91
+ source: z.string().optional(),
92
+ status: z.string().optional(),
93
+ subject: z.string().optional(),
94
+ threadId: z.string().optional(),
95
+ to: z.union([z.string(), z.string().array()]).optional(),
96
+ userId: z.string().optional(),
97
+ } as const
98
+ const USER_FIELDS = {
99
+ ...BASE_EVENT_FIELDS,
100
+ companyId: z.string().optional(),
101
+ email: z.string().optional(),
102
+ extension: z.string().optional(),
103
+ firstName: z.string().optional(),
104
+ id: z.string().min(1),
105
+ lastName: z.string().optional(),
106
+ locations: z.string().array().optional(),
107
+ permissions: encodableSchema.optional(),
108
+ phone: z.string().optional(),
109
+ role: z.string().optional(),
110
+ scopes: z.string().array().optional(),
111
+ } as const
112
+ const APPOINTMENT_FIELDS = {
113
+ ...BASE_EVENT_FIELDS,
114
+ appointment: z
115
+ .object({
116
+ address: z.string().optional(),
117
+ appointmentStatus: z.string().optional(),
118
+ assignedUserId: z.string().optional(),
119
+ calendarId: z.string().optional(),
120
+ contactId: z.string().optional(),
121
+ dateAdded: z.string().optional(),
122
+ dateUpdated: z.string().optional(),
123
+ endTime: z.string().optional(),
124
+ groupId: z.string().optional(),
125
+ id: z.string().min(1),
126
+ notes: z.string().optional(),
127
+ source: z.string().optional(),
128
+ startTime: z.string().optional(),
129
+ title: z.string().optional(),
130
+ users: z.string().array().optional(),
131
+ })
132
+ .catchall(encodableSchema),
133
+ } as const
134
+
135
+ export const HIGH_LEVEL_EVENT_SCHEMAS = {
136
+ AppointmentCreate: eventSchema("AppointmentCreate", APPOINTMENT_FIELDS),
137
+ AppointmentDelete: eventSchema("AppointmentDelete", APPOINTMENT_FIELDS),
138
+ AppointmentUpdate: eventSchema("AppointmentUpdate", APPOINTMENT_FIELDS),
139
+ CampaignStatusUpdate: eventSchema("CampaignStatusUpdate", {
140
+ ...BASE_EVENT_FIELDS,
141
+ contactId: z.string().optional(),
142
+ dateAdded: z.string().optional(),
143
+ id: z.string().min(1),
144
+ replied: z.string().optional(),
145
+ status: z.string().optional(),
146
+ templateId: z.string().optional(),
147
+ }),
148
+ ContactCreate: eventSchema("ContactCreate", CONTACT_FIELDS),
149
+ ContactDelete: eventSchema("ContactDelete", CONTACT_FIELDS),
150
+ ContactDndUpdate: eventSchema("ContactDndUpdate", CONTACT_FIELDS),
151
+ ContactTagUpdate: eventSchema("ContactTagUpdate", CONTACT_FIELDS),
152
+ ContactUpdate: eventSchema("ContactUpdate", CONTACT_FIELDS),
153
+ ConversationUnreadUpdate: eventSchema("ConversationUnreadUpdate", {
154
+ ...BASE_EVENT_FIELDS,
155
+ contactId: z.string().optional(),
156
+ deleted: z.boolean().optional(),
157
+ id: z.string().min(1),
158
+ inbox: z.boolean().optional(),
159
+ starred: z.boolean().optional(),
160
+ unreadCount: z.number().int().nonnegative().optional(),
161
+ }),
162
+ ConversationUpdate: eventSchema("ConversationUpdate", {
163
+ ...BASE_EVENT_FIELDS,
164
+ companyId: z.string().optional(),
165
+ contactId: z.string().optional(),
166
+ newConversationId: z.string().min(1),
167
+ oldConversationId: z.string().min(1),
168
+ }),
169
+ InboundMessage: eventSchema("InboundMessage", MESSAGE_FIELDS),
170
+ LocationUpdate: eventSchema("LocationUpdate", {
171
+ companyId: z.string().optional(),
172
+ email: z.string().optional(),
173
+ id: z.string().min(1),
174
+ locationId: z.string().min(1).optional(),
175
+ name: z.string().optional(),
176
+ stripeProductId: z.string().optional(),
177
+ timestamp: BASE_EVENT_FIELDS.timestamp,
178
+ webhookId: BASE_EVENT_FIELDS.webhookId,
179
+ }),
180
+ NoteCreate: eventSchema("NoteCreate", NOTE_FIELDS),
181
+ NoteDelete: eventSchema("NoteDelete", NOTE_FIELDS),
182
+ NoteUpdate: eventSchema("NoteUpdate", NOTE_FIELDS),
183
+ OpportunityAssignedToUpdate: eventSchema(
184
+ "OpportunityAssignedToUpdate",
185
+ OPPORTUNITY_FIELDS,
186
+ ),
187
+ OpportunityCreate: eventSchema("OpportunityCreate", OPPORTUNITY_FIELDS),
188
+ OpportunityDelete: eventSchema("OpportunityDelete", OPPORTUNITY_FIELDS),
189
+ OpportunityMonetaryValueUpdate: eventSchema(
190
+ "OpportunityMonetaryValueUpdate",
191
+ OPPORTUNITY_FIELDS,
192
+ ),
193
+ OpportunityStageUpdate: eventSchema(
194
+ "OpportunityStageUpdate",
195
+ OPPORTUNITY_FIELDS,
196
+ ),
197
+ OpportunityStatusUpdate: eventSchema(
198
+ "OpportunityStatusUpdate",
199
+ OPPORTUNITY_FIELDS,
200
+ ),
201
+ OpportunityUpdate: eventSchema("OpportunityUpdate", OPPORTUNITY_FIELDS),
202
+ OutboundMessage: eventSchema("OutboundMessage", MESSAGE_FIELDS),
203
+ TaskComplete: eventSchema("TaskComplete", TASK_FIELDS),
204
+ TaskCreate: eventSchema("TaskCreate", TASK_FIELDS),
205
+ TaskDelete: eventSchema("TaskDelete", TASK_FIELDS),
206
+ UserCreate: eventSchema("UserCreate", USER_FIELDS),
207
+ UserDelete: eventSchema("UserDelete", USER_FIELDS),
208
+ UserUpdate: eventSchema("UserUpdate", USER_FIELDS),
209
+ } as const
210
+
211
+ export const HIGH_LEVEL_WEBHOOK_EVENT_TYPES = Object.keys(
212
+ HIGH_LEVEL_EVENT_SCHEMAS,
213
+ ) as HighLevelWebhookEventType[]
214
+
215
+ export type HighLevelWebhookEventType = keyof typeof HIGH_LEVEL_EVENT_SCHEMAS
216
+ export type HighLevelWebhookEvent = z.output<
217
+ (typeof HIGH_LEVEL_EVENT_SCHEMAS)[HighLevelWebhookEventType]
218
+ >
219
+
220
+ export const HIGH_LEVEL_EVENT_SCHEMA = z.discriminatedUnion("type", [
221
+ HIGH_LEVEL_EVENT_SCHEMAS.AppointmentCreate,
222
+ HIGH_LEVEL_EVENT_SCHEMAS.AppointmentDelete,
223
+ HIGH_LEVEL_EVENT_SCHEMAS.AppointmentUpdate,
224
+ HIGH_LEVEL_EVENT_SCHEMAS.CampaignStatusUpdate,
225
+ HIGH_LEVEL_EVENT_SCHEMAS.ContactCreate,
226
+ HIGH_LEVEL_EVENT_SCHEMAS.ContactDelete,
227
+ HIGH_LEVEL_EVENT_SCHEMAS.ContactDndUpdate,
228
+ HIGH_LEVEL_EVENT_SCHEMAS.ContactTagUpdate,
229
+ HIGH_LEVEL_EVENT_SCHEMAS.ContactUpdate,
230
+ HIGH_LEVEL_EVENT_SCHEMAS.ConversationUnreadUpdate,
231
+ HIGH_LEVEL_EVENT_SCHEMAS.ConversationUpdate,
232
+ HIGH_LEVEL_EVENT_SCHEMAS.InboundMessage,
233
+ HIGH_LEVEL_EVENT_SCHEMAS.LocationUpdate,
234
+ HIGH_LEVEL_EVENT_SCHEMAS.NoteCreate,
235
+ HIGH_LEVEL_EVENT_SCHEMAS.NoteDelete,
236
+ HIGH_LEVEL_EVENT_SCHEMAS.NoteUpdate,
237
+ HIGH_LEVEL_EVENT_SCHEMAS.OpportunityAssignedToUpdate,
238
+ HIGH_LEVEL_EVENT_SCHEMAS.OpportunityCreate,
239
+ HIGH_LEVEL_EVENT_SCHEMAS.OpportunityDelete,
240
+ HIGH_LEVEL_EVENT_SCHEMAS.OpportunityMonetaryValueUpdate,
241
+ HIGH_LEVEL_EVENT_SCHEMAS.OpportunityStageUpdate,
242
+ HIGH_LEVEL_EVENT_SCHEMAS.OpportunityStatusUpdate,
243
+ HIGH_LEVEL_EVENT_SCHEMAS.OpportunityUpdate,
244
+ HIGH_LEVEL_EVENT_SCHEMAS.OutboundMessage,
245
+ HIGH_LEVEL_EVENT_SCHEMAS.TaskComplete,
246
+ HIGH_LEVEL_EVENT_SCHEMAS.TaskCreate,
247
+ HIGH_LEVEL_EVENT_SCHEMAS.TaskDelete,
248
+ HIGH_LEVEL_EVENT_SCHEMAS.UserCreate,
249
+ HIGH_LEVEL_EVENT_SCHEMAS.UserDelete,
250
+ HIGH_LEVEL_EVENT_SCHEMAS.UserUpdate,
251
+ ])
252
+
253
+ export const HIGH_LEVEL_APP_LIFECYCLE_EVENT_SCHEMA = z
254
+ .discriminatedUnion("type", [
255
+ eventSchema("INSTALL", {
256
+ appId: z.string().min(1),
257
+ companyId: z.string().min(1).optional(),
258
+ companyName: z.string().optional(),
259
+ isWhitelabelCompany: z.boolean().optional(),
260
+ locationId: z.string().min(1).optional(),
261
+ planId: z.string().optional(),
262
+ trial: encodableSchema.optional(),
263
+ userId: z.string().optional(),
264
+ whitelabelDetails: encodableSchema.optional(),
265
+ }),
266
+ eventSchema("UNINSTALL", {
267
+ appId: z.string().min(1),
268
+ companyId: z.string().min(1).optional(),
269
+ locationId: z.string().min(1).optional(),
270
+ }),
271
+ ])
272
+ .refine((event) => event.locationId || event.companyId, {
273
+ message: "HighLevel app lifecycle events require a location or company ID.",
274
+ })
275
+
276
+ export type HighLevelAppLifecycleEvent = z.output<
277
+ typeof HIGH_LEVEL_APP_LIFECYCLE_EVENT_SCHEMA
278
+ >
279
+
280
+ export const highLevelEventTypeMap = {
281
+ AppointmentCreate: "highlevel.appointment.created",
282
+ AppointmentDelete: "highlevel.appointment.deleted",
283
+ AppointmentUpdate: "highlevel.appointment.updated",
284
+ CampaignStatusUpdate: "highlevel.campaign.statusUpdated",
285
+ ContactCreate: "highlevel.contact.created",
286
+ ContactDelete: "highlevel.contact.deleted",
287
+ ContactDndUpdate: "highlevel.contact.dndUpdated",
288
+ ContactTagUpdate: "highlevel.contact.tagsUpdated",
289
+ ContactUpdate: "highlevel.contact.updated",
290
+ ConversationUnreadUpdate: "highlevel.conversation.unreadUpdated",
291
+ ConversationUpdate: "highlevel.conversation.updated",
292
+ InboundMessage: "highlevel.message.received",
293
+ LocationUpdate: "highlevel.location.updated",
294
+ NoteCreate: "highlevel.note.created",
295
+ NoteDelete: "highlevel.note.deleted",
296
+ NoteUpdate: "highlevel.note.updated",
297
+ OpportunityAssignedToUpdate: "highlevel.opportunity.assigneeUpdated",
298
+ OpportunityCreate: "highlevel.opportunity.created",
299
+ OpportunityDelete: "highlevel.opportunity.deleted",
300
+ OpportunityMonetaryValueUpdate: "highlevel.opportunity.valueUpdated",
301
+ OpportunityStageUpdate: "highlevel.opportunity.stageUpdated",
302
+ OpportunityStatusUpdate: "highlevel.opportunity.statusUpdated",
303
+ OpportunityUpdate: "highlevel.opportunity.updated",
304
+ OutboundMessage: "highlevel.message.sent",
305
+ TaskComplete: "highlevel.task.completed",
306
+ TaskCreate: "highlevel.task.created",
307
+ TaskDelete: "highlevel.task.deleted",
308
+ UserCreate: "highlevel.user.created",
309
+ UserDelete: "highlevel.user.deleted",
310
+ UserUpdate: "highlevel.user.updated",
311
+ } as const satisfies Record<HighLevelWebhookEventType, `highlevel.${string}`>
312
+
313
+ type HighLevelTriggerContract<TEvent> = {
314
+ readonly configSchema: typeof HIGH_LEVEL_TRIGGER_CONFIG_SCHEMA
315
+ readonly eventSchema: z.ZodType<TEvent>
316
+ }
317
+
318
+ /** Typed semantic contracts derived from provider webhook discriminators. */
319
+ type HighLevelSemanticTriggerContracts = {
320
+ readonly [TType in HighLevelWebhookEventType as (typeof highLevelEventTypeMap)[TType]]: HighLevelTriggerContract<
321
+ z.output<(typeof HIGH_LEVEL_EVENT_SCHEMAS)[TType]>
322
+ >
323
+ }
324
+
325
+ export const highLevelTriggerContracts = {
326
+ "highlevel.event": {
327
+ configSchema: HIGH_LEVEL_TRIGGER_CONFIG_SCHEMA,
328
+ eventSchema: HIGH_LEVEL_EVENT_SCHEMA,
329
+ },
330
+ ...Object.fromEntries(
331
+ Object.entries(highLevelEventTypeMap).map(([providerType, eventType]) => [
332
+ eventType,
333
+ {
334
+ configSchema: HIGH_LEVEL_TRIGGER_CONFIG_SCHEMA,
335
+ eventSchema:
336
+ HIGH_LEVEL_EVENT_SCHEMAS[providerType as HighLevelWebhookEventType],
337
+ },
338
+ ]),
339
+ ),
340
+ } as unknown as HighLevelSemanticTriggerContracts & {
341
+ readonly "highlevel.event": HighLevelTriggerContract<HighLevelWebhookEvent>
342
+ }
343
+
344
+ /**
345
+ * Creates an extensible schema for one HighLevel webhook discriminator.
346
+ *
347
+ * @param type - Provider event discriminator.
348
+ * @param shape - Known fields for the event.
349
+ */
350
+ function eventSchema<
351
+ const TType extends string,
352
+ TShape extends Record<string, z.ZodType>,
353
+ >(type: TType, shape: TShape) {
354
+ return z.object({ ...shape, type: z.literal(type) }).catchall(encodableSchema)
355
+ }
@@ -0,0 +1,6 @@
1
+ export * from "./api"
2
+ export * from "./events"
3
+ export * from "./operation-manifest"
4
+ export * from "./schemas"
5
+ export type { HighLevelOperationMap } from "./openapi-types.generated"
6
+ export type * from "./types"