@warriorteam/redai-zalo-sdk 1.11.1 → 1.12.1

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.
@@ -1,858 +1,858 @@
1
- # Webhook Events Documentation
2
-
3
- > Source of truth: The full, strongly-typed webhook definitions live in `src/types/webhook.ts`.
4
- >
5
- > • GitHub: https://github.com/warriorteam/redai-zalo-sdk/blob/main/src/types/webhook.ts
6
-
7
- ## Table of Contents
8
- - Overview
9
- - Event Categories
10
- - Types & Enums Summary
11
- - Message Events (examples)
12
- - User Action Events (examples)
13
- - Shop Events (examples)
14
- - OA Message Events (examples)
15
- - User Interaction Events (examples)
16
- - Consent Events (examples)
17
- - Anonymous User Events (examples)
18
- - Type Guards and Utilities
19
- - Webhook Handler Setup
20
- - Best Practices
21
- - Migration from Legacy Types
22
-
23
- ## Types & Enums Summary
24
-
25
- - Union types
26
- - `WebhookEvent` – Tập hợp tất cả event types
27
- - `MessageWebhookEvent`, `UserActionWebhookEvent`, `ShopWebhookEvent`, `SystemWebhookEvent`, `AnonymousWebhookEvent`, `CallWebhookEvent`, `ZNSWebhookEvent`, `GroupWebhookEvent`, `WidgetWebhookEvent`
28
- - Handler map
29
- - `WebhookHandlers` – Bản đồ event_name -> handler function có type an toàn
30
- - Enums
31
- - `WebhookEventName` – Tên event chuẩn (string enum)
32
- - `AttachmentType` – Loại attachment: image, file, audio, video, gif, link, location, sticker
33
- - Type guards chính (đều export từ package)
34
- - `isMessageEvent`, `isFollowEvent`, `isUserActionEvent`, `isShopEvent`, `isOAMessageEvent`, `isAnonymousEvent`, `isCallEvent`, `isTemplateEvent`, `isBusinessCardEvent`, `isFeedbackEvent`, `isZNSEvent`, `isGroupEvent`, `isJourneyEvent`, `isReactionEvent`, `isConsentEvent`, `isUpdateUserInfoEvent`, `hasAttachments`
35
-
36
- - Message shape
37
- - `message.msg_id: string` — ID của tin nhắn
38
- - `message.text?: string` — Nội dung text (nếu là text)
39
- - `message.attachments?: Attachment[]` — Có mặt khi là tin nhắn đa phương tiện (image, gif, video, file, link, location, sticker)
40
- - `message.quote_msg_id?: string` — ID của tin nhắn gốc nếu đây là tin nhắn được gửi bằng thao tác “Trả lời” (reply)
41
-
42
-
43
-
44
- This document describes the webhook event types and DTOs for Zalo Official Account webhooks.
45
-
46
- ## Overview
47
-
48
- The Zalo SDK provides comprehensive TypeScript types for all webhook events sent by Zalo to your application. These events are strongly typed and include proper payload structures for each event type.
49
-
50
- ## Event Categories
51
-
52
- ### 1. Message Events
53
-
54
- Events triggered when users interact with your Official Account through messages.
55
-
56
- ### 2. User Action Events
57
-
58
- Events triggered when users perform actions like following your Official Account.
59
-
60
- ### 3. Legacy Events
61
-
62
- Backward compatibility events for existing integrations.
63
-
64
- ## Message Events
65
-
66
- ### User Send Text Event
67
-
68
- ```typescript
69
- import { UserSendTextEvent } from "redai-zalo-sdk";
70
-
71
- const textEvent: UserSendTextEvent = {
72
- app_id: "3482178216594085616",
73
- user_id_by_app: "3216904426693862293",
74
- event_name: "user_send_text",
75
- timestamp: "1754405178258",
76
- sender: { id: "4411682737790366300" },
77
- recipient: { id: "579745863508352884" },
78
- message: {
79
- msg_id: "message_id_123",
80
- text: "Hello from user",
81
- },
82
- };
83
- // Optional: reply to an existing message
84
- quote_msg_id: "96d3cdf3af150460909",
85
-
86
- ```
87
-
88
- ### User Send Image Event
89
-
90
- ```typescript
91
- import { UserSendImageEvent } from "redai-zalo-sdk";
92
-
93
- const imageEvent: UserSendImageEvent = {
94
- app_id: "3482178216594085616",
95
- user_id_by_app: "3216904426693862293",
96
- event_name: "user_send_image",
97
- timestamp: "1754405178258",
98
- sender: { id: "4411682737790366300" },
99
- recipient: { id: "579745863508352884" },
100
- message: {
101
- msg_id: "message_id_123",
102
- text: "Check out this image",
103
- attachments: [
104
- {
105
- type: "image",
106
- payload: {
107
- thumbnail: "https://example.com/thumb.jpg",
108
- url: "https://example.com/image.jpg",
109
- },
110
- },
111
- ],
112
- },
113
- };
114
- ```
115
-
116
- ### User Send Location Event
117
-
118
- ```typescript
119
- import { UserSendLocationEvent } from "redai-zalo-sdk";
120
-
121
- const locationEvent: UserSendLocationEvent = {
122
- app_id: "3482178216594085616",
123
- user_id_by_app: "3216904426693862293",
124
- event_name: "user_send_location",
125
- timestamp: "1754405178257",
126
- sender: { id: "4411682737790366300" },
127
- recipient: { id: "579745863508352884" },
128
- message: {
129
- msg_id: "message_id_123",
130
- text: "My current location",
131
- attachments: [
132
- {
133
- type: "location",
134
- payload: {
135
- coordinates: {
136
- latitude: "10.7642473",
137
- longitude: "106.6564313999999",
138
- },
139
- },
140
- },
141
- ],
142
- },
143
- };
144
- ```
145
-
146
- ### User Send Link Event
147
-
148
- ```typescript
149
- import { UserSendLinkEvent } from "redai-zalo-sdk";
150
-
151
- const linkEvent: UserSendLinkEvent = {
152
- app_id: "3482178216594085616",
153
- user_id_by_app: "3216904426693862293",
154
- event_name: "user_send_link",
155
- timestamp: "1754405178258",
156
- sender: { id: "4411682737790366300" },
157
- recipient: { id: "579745863508352884" },
158
- message: {
159
- msg_id: "message_id_123",
160
- text: "Check this link",
161
- attachments: [
162
- {
163
- type: "link",
164
- payload: {
165
- thumbnail: "https://example.com/thumb.jpg",
166
- description: "Interesting article",
167
- url: "https://example.com/article",
168
- },
169
- },
170
- ],
171
- },
172
- };
173
- ```
174
-
175
- ### User Send Sticker Event
176
-
177
- ```typescript
178
- import { UserSendStickerEvent } from "redai-zalo-sdk";
179
-
180
- const stickerEvent: UserSendStickerEvent = {
181
- app_id: "3482178216594085616",
182
- user_id_by_app: "3216904426693862293",
183
- event_name: "user_send_sticker",
184
- timestamp: "1754405178259",
185
- sender: { id: "4411682737790366300" },
186
- recipient: { id: "579745863508352884" },
187
- message: {
188
- msg_id: "message_id_123",
189
- text: "😊",
190
- attachments: [
191
- {
192
- type: "sticker",
193
- payload: {
194
- id: "sticker_123",
195
- url: "https://example.com/sticker.png",
196
- },
197
- },
198
- ],
199
- },
200
- };
201
- ```
202
-
203
- ### User Send GIF Event
204
-
205
- ```typescript
206
- import { UserSendGifEvent } from "redai-zalo-sdk";
207
-
208
- const gifEvent: UserSendGifEvent = {
209
- app_id: "3482178216594085616",
210
- user_id_by_app: "3216904426693862293",
211
- event_name: "user_send_gif",
212
- timestamp: "1754405178259",
213
- sender: { id: "4411682737790366300" },
214
- recipient: { id: "579745863508352884" },
215
- message: {
216
- msg_id: "message_id_123",
217
- text: "Funny GIF",
218
- attachments: [
219
- {
220
- type: "gif",
221
- payload: {
222
- thumbnail: "https://example.com/gif_thumb.jpg",
223
- url: "https://example.com/funny.gif",
224
- },
225
- },
226
- ],
227
- },
228
- };
229
- ```
230
-
231
- ### User Send Audio Event
232
-
233
- ```typescript
234
- import { UserSendAudioEvent } from "redai-zalo-sdk";
235
-
236
- const audioEvent: UserSendAudioEvent = {
237
- app_id: "3482178216594085616",
238
- user_id_by_app: "3216904426693862293",
239
- event_name: "user_send_audio",
240
- timestamp: "1754405178259",
241
- sender: { id: "4411682737790366300" },
242
- recipient: { id: "579745863508352884" },
243
- message: {
244
- msg_id: "message_id_123",
245
- text: "Voice message",
246
- attachments: [
247
- {
248
- type: "audio",
249
- payload: {
250
- url: "https://example.com/voice.mp3",
251
- },
252
- },
253
- ],
254
- },
255
- };
256
- ```
257
-
258
- ### User Send Video Event
259
-
260
- ```typescript
261
- import { UserSendVideoEvent } from "redai-zalo-sdk";
262
-
263
- const videoEvent: UserSendVideoEvent = {
264
- app_id: "3482178216594085616",
265
- user_id_by_app: "3216904426693862293",
266
- event_name: "user_send_video",
267
- timestamp: "1754405178261",
268
- sender: { id: "4411682737790366300" },
269
- recipient: { id: "579745863508352884" },
270
- message: {
271
- msg_id: "message_id_123",
272
- text: "Check out this video",
273
- attachments: [
274
- {
275
- type: "video",
276
- payload: {
277
- thumbnail: "https://example.com/video_thumb.jpg",
278
- description: "Amazing video content",
279
- url: "https://example.com/video.mp4",
280
- },
281
- },
282
- ],
283
- },
284
- };
285
- ```
286
-
287
- ### User Send File Event
288
-
289
- ```typescript
290
- import { UserSendFileEvent } from "redai-zalo-sdk";
291
-
292
- const fileEvent: UserSendFileEvent = {
293
- app_id: "3482178216594085616",
294
- user_id_by_app: "3216904426693862293",
295
- event_name: "user_send_file",
296
- timestamp: "1754405178261",
297
- sender: { id: "4411682737790366300" },
298
- recipient: { id: "579745863508352884" },
299
- message: {
300
- msg_id: "message_id_123",
301
- attachments: [
302
- {
303
- type: "file",
304
- payload: {
305
- url: "https://example.com/document.pdf",
306
- size: "1024000",
307
- name: "important_document.pdf",
308
- checksum: "abc123def456",
309
- type: "application/pdf",
310
- },
311
- },
312
- ],
313
- },
314
- };
315
- ```
316
-
317
- ### User Received Message Event
318
-
319
- ```typescript
320
- import { UserReceivedMessageEvent } from "redai-zalo-sdk";
321
-
322
- const receivedEvent: UserReceivedMessageEvent = {
323
- app_id: "3482178216594085616",
324
- user_id_by_app: "3216904426693862293",
325
- event_name: "user_received_message",
326
- timestamp: "1754405178259",
327
- sender: { id: "579745863508352884" }, // OA sent
328
- recipient: { id: "4411682737790366300" }, // User received
329
- message: {
330
- msg_id: "message_id_123",
331
- },
332
- };
333
- ```
334
-
335
- ### User Seen Message Event
336
-
337
- ```typescript
338
- import { UserSeenMessageEvent } from "redai-zalo-sdk";
339
-
340
- const seenEvent: UserSeenMessageEvent = {
341
- app_id: "3482178216594085616",
342
- user_id_by_app: "3216904426693862293",
343
- event_name: "user_seen_message",
344
- timestamp: "1754405178259",
345
- sender: { id: "579745863508352884" }, // OA
346
- recipient: { id: "4411682737790366300" }, // User
347
- message: {
348
- msg_ids: ["message_id_123", "message_id_124"],
349
- },
350
- };
351
- ```
352
-
353
- ## User Action Events
354
-
355
- ### User Follow Event
356
-
357
- ```typescript
358
- import { UserFollowEvent } from "redai-zalo-sdk";
359
-
360
- const followEvent: UserFollowEvent = {
361
- app_id: "3482178216594085616",
362
- user_id_by_app: "3216904426693862293",
363
- event_name: "follow",
364
- timestamp: "1754405178260",
365
- oa_id: "579745863508352884",
366
- source: "testing_webhook",
367
- follower: {
368
- id: "4411682737790366300",
369
- },
370
- };
371
- ```
372
-
373
- ### User Unfollow Event
374
-
375
- ```typescript
376
- import { UserUnfollowEvent } from "redai-zalo-sdk";
377
-
378
- const unfollowEvent: UserUnfollowEvent = {
379
- app_id: "3482178216594085616",
380
- user_id_by_app: "3216904426693862293",
381
- event_name: "unfollow",
382
- timestamp: "1754405178260",
383
- oa_id: "579745863508352884",
384
- source: "testing_webhook",
385
- follower: {
386
- id: "4411682737790366300",
387
- },
388
- };
389
- ```
390
-
391
- ### User Submit Info Event
392
-
393
- ```typescript
394
- import { UserSubmitInfoEvent } from "redai-zalo-sdk";
395
-
396
- const submitInfoEvent: UserSubmitInfoEvent = {
397
- app_id: "3482178216594085616",
398
- user_id_by_app: "3216904426693862293",
399
- event_name: "user_submit_info",
400
- timestamp: "1754405178260",
401
- sender: { id: "4411682737790366300" },
402
- recipient: { id: "579745863508352884" },
403
- info: {
404
- address: "123 Main Street",
405
- phone: "0123456789",
406
- city: "Ho Chi Minh City",
407
- district: "District 1",
408
- name: "John Doe",
409
- ward: "Ward 1",
410
- },
411
- };
412
- ```
413
-
414
- ## Shop Events
415
-
416
- ### Shop Has Order Event
417
-
418
- ```typescript
419
- import { ShopHasOrderEvent } from "redai-zalo-sdk";
420
-
421
- const orderEvent: ShopHasOrderEvent = {
422
- app_id: "3482178216594085616",
423
- user_id_by_app: "3216904426693862293",
424
- event_name: "shop_has_order",
425
- timestamp: "1754405178260",
426
- oa_id: "579745863508352884",
427
- customer: {
428
- id: "4411682737790366300",
429
- },
430
- };
431
- ```
432
-
433
- ## OA Message Events
434
-
435
- ### OA Send Text Event
436
-
437
- ```typescript
438
- import { OASendTextEvent } from "redai-zalo-sdk";
439
-
440
- const oaTextEvent: OASendTextEvent = {
441
- app_id: "3482178216594085616",
442
- user_id_by_app: "3216904426693862293",
443
- event_name: "oa_send_text",
444
- timestamp: "1754405178260",
445
- sender: { id: "579745863508352884" },
446
- recipient: { id: "4411682737790366300" },
447
- message: {
448
- msg_id: "oa_message_123",
449
- text: "Hello from Official Account",
450
- // Optional: reply to an existing message
451
- quote_msg_id: "96d3cdf3af150460909",
452
- },
453
- };
454
- ```
455
-
456
- ### OA Send Image Event
457
-
458
- ```typescript
459
- import { OASendImageEvent } from "redai-zalo-sdk";
460
-
461
- const oaImageEvent: OASendImageEvent = {
462
- app_id: "3482178216594085616",
463
- user_id_by_app: "3216904426693862293",
464
- event_name: "oa_send_image",
465
- timestamp: "1754405178260",
466
- sender: { id: "579745863508352884" },
467
- recipient: { id: "4411682737790366300" },
468
- message: {
469
- msg_id: "oa_message_123",
470
- text: "Check out our product",
471
- attachments: [
472
- {
473
- type: "image",
474
- payload: {
475
- thumbnail: "https://example.com/thumb.jpg",
476
- url: "https://example.com/product.jpg",
477
- },
478
- },
479
- ],
480
- },
481
- };
482
- ```
483
-
484
- ### OA Send List Event (Interactive Message)
485
-
486
- ```typescript
487
- import { OASendListEvent } from "redai-zalo-sdk";
488
-
489
- const oaListEvent: OASendListEvent = {
490
- app_id: "3482178216594085616",
491
- user_id_by_app: "3216904426693862293",
492
- event_name: "oa_send_list",
493
- timestamp: "1754405178260",
494
- sender: { id: "579745863508352884" },
495
- recipient: { id: "4411682737790366300" },
496
- message: {
497
- msg_id: "oa_message_123",
498
- text: "Choose from our options",
499
- attachments: [
500
- {
501
- type: "link",
502
- payload: {
503
- thumbnail: "https://example.com/option1.jpg",
504
- description: "Option 1 description",
505
- url: "https://example.com/option1",
506
- title: "Option 1",
507
- },
508
- },
509
- {
510
- type: "link",
511
- payload: {
512
- thumbnail: "https://example.com/option2.jpg",
513
- description: "Option 2 description",
514
- url: "https://example.com/option2",
515
- title: "Option 2",
516
- },
517
- },
518
- ],
519
- },
520
- };
521
- ```
522
-
523
- ### OA Send File Event
524
-
525
- ```typescript
526
- import { OASendFileEvent } from "redai-zalo-sdk";
527
-
528
- const oaFileEvent: OASendFileEvent = {
529
- app_id: "3482178216594085616",
530
- user_id_by_app: "3216904426693862293",
531
- event_name: "oa_send_file",
532
- timestamp: "1754405178261",
533
- sender: { id: "579745863508352884" },
534
- recipient: { id: "4411682737790366300" },
535
- message: {
536
- msg_id: "oa_message_123",
537
- attachments: [
538
- {
539
- type: "file",
540
- payload: {
541
- url: "https://example.com/document.pdf",
542
- size: "1024000",
543
- name: "important_document.pdf",
544
- checksum: "abc123def456",
545
- type: "application/pdf",
546
- },
547
- },
548
- ],
549
- },
550
- };
551
- ```
552
-
553
- ### OA Send Sticker Event
554
-
555
- ```typescript
556
- import { OASendStickerEvent } from "redai-zalo-sdk";
557
-
558
- const oaStickerEvent: OASendStickerEvent = {
559
- app_id: "3482178216594085616",
560
- user_id_by_app: "3216904426693862293",
561
- event_name: "oa_send_sticker",
562
- timestamp: "1754405178261",
563
- sender: { id: "579745863508352884" },
564
- recipient: { id: "4411682737790366300" },
565
- message: {
566
- msg_id: "oa_message_123",
567
- text: "Have a great day!",
568
- attachments: [
569
- {
570
- type: "sticker",
571
- payload: {
572
- id: "sticker_123",
573
- url: "https://example.com/sticker.png",
574
- },
575
- },
576
- ],
577
- },
578
- };
579
- ```
580
-
581
- ## User Interaction Events
582
-
583
- ### User Click Chat Now Event
584
-
585
- ```typescript
586
- import { UserClickChatNowEvent } from "redai-zalo-sdk";
587
-
588
- const clickChatEvent: UserClickChatNowEvent = {
589
- app_id: "3482178216594085616",
590
- user_id_by_app: "3216904426693862293",
591
- event_name: "user_click_chatnow",
592
- timestamp: "1754405178261",
593
- oa_id: "579745863508352884",
594
- user_id: "4411682737790366300",
595
- };
596
- ```
597
-
598
- ### User Reacted Message Event
599
-
600
- ```typescript
601
- import { UserReactedMessageEvent } from "redai-zalo-sdk";
602
-
603
- const userReactionEvent: UserReactedMessageEvent = {
604
- app_id: "3482178216594085616",
605
- user_id_by_app: "3216904426693862293",
606
- event_name: "user_reacted_message",
607
- timestamp: "1754405178261",
608
- sender: { id: "4411682737790366300" },
609
- recipient: { id: "579745863508352884" },
610
- message: {
611
- msg_id: "message_123",
612
- react_icon: "👍",
613
- },
614
- };
615
- ```
616
-
617
- ### OA Reacted Message Event
618
-
619
- ```typescript
620
- import { OAReactedMessageEvent } from "redai-zalo-sdk";
621
-
622
- const oaReactionEvent: OAReactedMessageEvent = {
623
- app_id: "3482178216594085616",
624
- user_id_by_app: "3216904426693862293",
625
- event_name: "oa_reacted_message",
626
- timestamp: "1754405178261",
627
- sender: { id: "579745863508352884" },
628
- recipient: { id: "4411682737790366300" },
629
- message: {
630
- msg_id: "message_123",
631
- react_icon: "❤️",
632
- },
633
- };
634
- ```
635
-
636
- ## Consent Events
637
-
638
- ### OA Send Consent Event
639
-
640
- ```typescript
641
- import { OASendConsentEvent } from "redai-zalo-sdk";
642
-
643
- const consentEvent: OASendConsentEvent = {
644
- app_id: "3482178216594085616",
645
- user_id_by_app: "3216904426693862293",
646
- event_name: "oa_send_consent",
647
- timestamp: "1754405178261",
648
- oa_id: "579745863508352884",
649
- request_type: "SENT",
650
- create_time: "1754405178261",
651
- expired_time: "1754405178261",
652
- phone: "84773543888",
653
- };
654
- ```
655
-
656
- ### User Reply Consent Event
657
-
658
- ```typescript
659
- import { UserReplyConsentEvent } from "redai-zalo-sdk";
660
-
661
- const replyConsentEvent: UserReplyConsentEvent = {
662
- app_id: "3482178216594085616",
663
- user_id_by_app: "3216904426693862293",
664
- event_name: "user_reply_consent",
665
- timestamp: "1754405178261",
666
- oa_id: "579745863508352884",
667
- expired_time: "1754405178261",
668
- confirmed_time: "1754405178261",
669
- phone: "84773543888",
670
- };
671
- ```
672
-
673
- ## Anonymous User Events
674
-
675
- ### Anonymous Send Text Event
676
-
677
- ```typescript
678
- import { AnonymousSendTextEvent } from "redai-zalo-sdk";
679
-
680
- const anonymousTextEvent: AnonymousSendTextEvent = {
681
- app_id: "3482178216594085616",
682
- user_id_by_app: "3216904426693862293",
683
- event_name: "anonymous_send_text",
684
- timestamp: "1754405178261",
685
- sender: { id: "4411682737790366300" },
686
- recipient: { id: "579745863508352884" },
687
- message: {
688
- msg_id: "message_123",
689
- text: "Anonymous message",
690
- // Optional: reply to an existing message
691
- quote_msg_id: "96d3cdf3af150460909",
692
- conversation_id: "conversation_123",
693
- },
694
- };
695
- ```
696
-
697
- ### Anonymous Send Image Event
698
-
699
- ```typescript
700
- import { AnonymousSendImageEvent } from "redai-zalo-sdk";
701
-
702
- const anonymousImageEvent: AnonymousSendImageEvent = {
703
- app_id: "3482178216594085616",
704
- user_id_by_app: "3216904426693862293",
705
- event_name: "anonymous_send_image",
706
- timestamp: "1754405178262",
707
- sender: { id: "4411682737790366300" },
708
- recipient: { id: "579745863508352884" },
709
- message: {
710
- msg_id: "message_123",
711
- text: "Anonymous image",
712
- // Optional: reply to an existing message
713
- quote_msg_id: "96d3cdf3af150460909",
714
- conversation_id: "conversation_123",
715
- attachments: [
716
- {
717
- type: "image",
718
- payload: {
719
- thumbnail: "https://example.com/thumb.jpg",
720
- url: "https://example.com/image.jpg",
721
- },
722
- },
723
- ],
724
- },
725
- };
726
- ```
727
-
728
- ### Anonymous Send File Event
729
-
730
- ```typescript
731
- import { AnonymousSendFileEvent } from "redai-zalo-sdk";
732
-
733
- const anonymousFileEvent: AnonymousSendFileEvent = {
734
- app_id: "3482178216594085616",
735
- user_id_by_app: "3216904426693862293",
736
- event_name: "anonymous_send_file",
737
- timestamp: "1754405178262",
738
- sender: { id: "4411682737790366300" },
739
- recipient: { id: "579745863508352884" },
740
- message: {
741
- msg_id: "message_123",
742
- // Optional: reply to an existing message
743
- quote_msg_id: "96d3cdf3af150460909",
744
- conversation_id: "conversation_123",
745
- attachments: [
746
- {
747
- type: "file",
748
- payload: {
749
- url: "https://example.com/document.pdf",
750
- size: "1024000",
751
- name: "document.pdf",
752
- checksum: "abc123def456",
753
- type: "application/pdf",
754
- },
755
- },
756
- ],
757
- },
758
- };
759
- ```
760
-
761
- ## Type Guards and Utilities
762
-
763
- ### Check Event Type
764
-
765
- ```typescript
766
- import {
767
- isMessageEvent,
768
- isFollowEvent,
769
- hasAttachments,
770
- WebhookEvent,
771
- } from "@warriorteam/redai-zalo-sdk";
772
-
773
- function handleWebhook(event: WebhookEvent) {
774
- if (isMessageEvent(event)) {
775
- console.log("Message event:", event.event_name);
776
-
777
- if ("message" in event && hasAttachments(event.message)) {
778
- console.log("Has attachments:", event.message.attachments.length);
779
- }
780
- }
781
-
782
- if (isFollowEvent(event)) {
783
- console.log("Follower event:", event.event_name);
784
- }
785
- }
786
- ```
787
-
788
- ### Using Enums
789
-
790
- ```typescript
791
- import { WebhookEventName, AttachmentType } from "redai-zalo-sdk";
792
-
793
- function processEvent(event: WebhookEvent) {
794
- switch (event.event_name) {
795
- case WebhookEventName.USER_SEND_TEXT:
796
- console.log("Text message received");
797
- break;
798
-
799
- case WebhookEventName.USER_SEND_IMAGE:
800
- console.log("Image message received");
801
- break;
802
-
803
- case WebhookEventName.FOLLOW:
804
- console.log("User followed OA");
805
- break;
806
- }
807
- }
808
- ```
809
-
810
- ## Webhook Handler Setup
811
-
812
- ```typescript
813
- import { WebhookHandlers, UserSendTextEvent } from "redai-zalo-sdk";
814
-
815
- const handlers: WebhookHandlers = {
816
- user_send_text: async (event: UserSendTextEvent) => {
817
- console.log(`User ${event.sender.id} sent: ${event.message.text}`);
818
- // Handle text message
819
- },
820
-
821
- user_send_image: async (event) => {
822
- console.log(`User sent image: ${event.message.attachments[0].payload.url}`);
823
- // Handle image message
824
- },
825
-
826
- follow: async (event) => {
827
- console.log(`New follower: ${event.follower.id}`);
828
- // Handle follow event
829
- },
830
-
831
- "*": async (event) => {
832
- console.log(`Unhandled event: ${event.event_name}`);
833
- // Catch-all handler
834
- },
835
- };
836
- ```
837
-
838
- ## Best Practices
839
-
840
- 1. **Type Safety**: Always use the specific event types instead of generic ones
841
- 2. **Type Guards**: Use provided type guards to safely check event types
842
- 3. **Error Handling**: Implement proper error handling for webhook processing
843
- 4. **Validation**: Validate webhook signatures for security
844
- 5. **Async Processing**: Use async handlers for database operations or API calls
845
-
846
- ## Migration from Legacy Types
847
-
848
- If you're migrating from the old `UserSendMessageEvent` type:
849
-
850
- ```typescript
851
- // Old way (deprecated)
852
- user_send_text?: WebhookHandler<UserSendMessageEvent>;
853
-
854
- // New way (recommended)
855
- user_send_text?: WebhookHandler<UserSendTextEvent>;
856
- ```
857
-
858
- The new types provide better type safety and more specific payload structures for each event type.
1
+ # Webhook Events Documentation
2
+
3
+ > Source of truth: The full, strongly-typed webhook definitions live in `src/types/webhook.ts`.
4
+ >
5
+ > • GitHub: https://github.com/warriorteam/redai-zalo-sdk/blob/main/src/types/webhook.ts
6
+
7
+ ## Table of Contents
8
+ - Overview
9
+ - Event Categories
10
+ - Types & Enums Summary
11
+ - Message Events (examples)
12
+ - User Action Events (examples)
13
+ - Shop Events (examples)
14
+ - OA Message Events (examples)
15
+ - User Interaction Events (examples)
16
+ - Consent Events (examples)
17
+ - Anonymous User Events (examples)
18
+ - Type Guards and Utilities
19
+ - Webhook Handler Setup
20
+ - Best Practices
21
+ - Migration from Legacy Types
22
+
23
+ ## Types & Enums Summary
24
+
25
+ - Union types
26
+ - `WebhookEvent` – Tập hợp tất cả event types
27
+ - `MessageWebhookEvent`, `UserActionWebhookEvent`, `ShopWebhookEvent`, `SystemWebhookEvent`, `AnonymousWebhookEvent`, `CallWebhookEvent`, `ZNSWebhookEvent`, `GroupWebhookEvent`, `WidgetWebhookEvent`
28
+ - Handler map
29
+ - `WebhookHandlers` – Bản đồ event_name -> handler function có type an toàn
30
+ - Enums
31
+ - `WebhookEventName` – Tên event chuẩn (string enum)
32
+ - `AttachmentType` – Loại attachment: image, file, audio, video, gif, link, location, sticker
33
+ - Type guards chính (đều export từ package)
34
+ - `isMessageEvent`, `isFollowEvent`, `isUserActionEvent`, `isShopEvent`, `isOAMessageEvent`, `isAnonymousEvent`, `isCallEvent`, `isTemplateEvent`, `isBusinessCardEvent`, `isFeedbackEvent`, `isZNSEvent`, `isGroupEvent`, `isJourneyEvent`, `isReactionEvent`, `isConsentEvent`, `isUpdateUserInfoEvent`, `hasAttachments`
35
+
36
+ - Message shape
37
+ - `message.msg_id: string` — ID của tin nhắn
38
+ - `message.text?: string` — Nội dung text (nếu là text)
39
+ - `message.attachments?: Attachment[]` — Có mặt khi là tin nhắn đa phương tiện (image, gif, video, file, link, location, sticker)
40
+ - `message.quote_msg_id?: string` — ID của tin nhắn gốc nếu đây là tin nhắn được gửi bằng thao tác “Trả lời” (reply)
41
+
42
+
43
+
44
+ This document describes the webhook event types and DTOs for Zalo Official Account webhooks.
45
+
46
+ ## Overview
47
+
48
+ The Zalo SDK provides comprehensive TypeScript types for all webhook events sent by Zalo to your application. These events are strongly typed and include proper payload structures for each event type.
49
+
50
+ ## Event Categories
51
+
52
+ ### 1. Message Events
53
+
54
+ Events triggered when users interact with your Official Account through messages.
55
+
56
+ ### 2. User Action Events
57
+
58
+ Events triggered when users perform actions like following your Official Account.
59
+
60
+ ### 3. Legacy Events
61
+
62
+ Backward compatibility events for existing integrations.
63
+
64
+ ## Message Events
65
+
66
+ ### User Send Text Event
67
+
68
+ ```typescript
69
+ import { UserSendTextEvent } from "redai-zalo-sdk";
70
+
71
+ const textEvent: UserSendTextEvent = {
72
+ app_id: "3482178216594085616",
73
+ user_id_by_app: "3216904426693862293",
74
+ event_name: "user_send_text",
75
+ timestamp: "1754405178258",
76
+ sender: { id: "4411682737790366300" },
77
+ recipient: { id: "579745863508352884" },
78
+ message: {
79
+ msg_id: "message_id_123",
80
+ text: "Hello from user",
81
+ },
82
+ };
83
+ // Optional: reply to an existing message
84
+ quote_msg_id: "96d3cdf3af150460909",
85
+
86
+ ```
87
+
88
+ ### User Send Image Event
89
+
90
+ ```typescript
91
+ import { UserSendImageEvent } from "redai-zalo-sdk";
92
+
93
+ const imageEvent: UserSendImageEvent = {
94
+ app_id: "3482178216594085616",
95
+ user_id_by_app: "3216904426693862293",
96
+ event_name: "user_send_image",
97
+ timestamp: "1754405178258",
98
+ sender: { id: "4411682737790366300" },
99
+ recipient: { id: "579745863508352884" },
100
+ message: {
101
+ msg_id: "message_id_123",
102
+ text: "Check out this image",
103
+ attachments: [
104
+ {
105
+ type: "image",
106
+ payload: {
107
+ thumbnail: "https://example.com/thumb.jpg",
108
+ url: "https://example.com/image.jpg",
109
+ },
110
+ },
111
+ ],
112
+ },
113
+ };
114
+ ```
115
+
116
+ ### User Send Location Event
117
+
118
+ ```typescript
119
+ import { UserSendLocationEvent } from "redai-zalo-sdk";
120
+
121
+ const locationEvent: UserSendLocationEvent = {
122
+ app_id: "3482178216594085616",
123
+ user_id_by_app: "3216904426693862293",
124
+ event_name: "user_send_location",
125
+ timestamp: "1754405178257",
126
+ sender: { id: "4411682737790366300" },
127
+ recipient: { id: "579745863508352884" },
128
+ message: {
129
+ msg_id: "message_id_123",
130
+ text: "My current location",
131
+ attachments: [
132
+ {
133
+ type: "location",
134
+ payload: {
135
+ coordinates: {
136
+ latitude: "10.7642473",
137
+ longitude: "106.6564313999999",
138
+ },
139
+ },
140
+ },
141
+ ],
142
+ },
143
+ };
144
+ ```
145
+
146
+ ### User Send Link Event
147
+
148
+ ```typescript
149
+ import { UserSendLinkEvent } from "redai-zalo-sdk";
150
+
151
+ const linkEvent: UserSendLinkEvent = {
152
+ app_id: "3482178216594085616",
153
+ user_id_by_app: "3216904426693862293",
154
+ event_name: "user_send_link",
155
+ timestamp: "1754405178258",
156
+ sender: { id: "4411682737790366300" },
157
+ recipient: { id: "579745863508352884" },
158
+ message: {
159
+ msg_id: "message_id_123",
160
+ text: "Check this link",
161
+ attachments: [
162
+ {
163
+ type: "link",
164
+ payload: {
165
+ thumbnail: "https://example.com/thumb.jpg",
166
+ description: "Interesting article",
167
+ url: "https://example.com/article",
168
+ },
169
+ },
170
+ ],
171
+ },
172
+ };
173
+ ```
174
+
175
+ ### User Send Sticker Event
176
+
177
+ ```typescript
178
+ import { UserSendStickerEvent } from "redai-zalo-sdk";
179
+
180
+ const stickerEvent: UserSendStickerEvent = {
181
+ app_id: "3482178216594085616",
182
+ user_id_by_app: "3216904426693862293",
183
+ event_name: "user_send_sticker",
184
+ timestamp: "1754405178259",
185
+ sender: { id: "4411682737790366300" },
186
+ recipient: { id: "579745863508352884" },
187
+ message: {
188
+ msg_id: "message_id_123",
189
+ text: "😊",
190
+ attachments: [
191
+ {
192
+ type: "sticker",
193
+ payload: {
194
+ id: "sticker_123",
195
+ url: "https://example.com/sticker.png",
196
+ },
197
+ },
198
+ ],
199
+ },
200
+ };
201
+ ```
202
+
203
+ ### User Send GIF Event
204
+
205
+ ```typescript
206
+ import { UserSendGifEvent } from "redai-zalo-sdk";
207
+
208
+ const gifEvent: UserSendGifEvent = {
209
+ app_id: "3482178216594085616",
210
+ user_id_by_app: "3216904426693862293",
211
+ event_name: "user_send_gif",
212
+ timestamp: "1754405178259",
213
+ sender: { id: "4411682737790366300" },
214
+ recipient: { id: "579745863508352884" },
215
+ message: {
216
+ msg_id: "message_id_123",
217
+ text: "Funny GIF",
218
+ attachments: [
219
+ {
220
+ type: "gif",
221
+ payload: {
222
+ thumbnail: "https://example.com/gif_thumb.jpg",
223
+ url: "https://example.com/funny.gif",
224
+ },
225
+ },
226
+ ],
227
+ },
228
+ };
229
+ ```
230
+
231
+ ### User Send Audio Event
232
+
233
+ ```typescript
234
+ import { UserSendAudioEvent } from "redai-zalo-sdk";
235
+
236
+ const audioEvent: UserSendAudioEvent = {
237
+ app_id: "3482178216594085616",
238
+ user_id_by_app: "3216904426693862293",
239
+ event_name: "user_send_audio",
240
+ timestamp: "1754405178259",
241
+ sender: { id: "4411682737790366300" },
242
+ recipient: { id: "579745863508352884" },
243
+ message: {
244
+ msg_id: "message_id_123",
245
+ text: "Voice message",
246
+ attachments: [
247
+ {
248
+ type: "audio",
249
+ payload: {
250
+ url: "https://example.com/voice.mp3",
251
+ },
252
+ },
253
+ ],
254
+ },
255
+ };
256
+ ```
257
+
258
+ ### User Send Video Event
259
+
260
+ ```typescript
261
+ import { UserSendVideoEvent } from "redai-zalo-sdk";
262
+
263
+ const videoEvent: UserSendVideoEvent = {
264
+ app_id: "3482178216594085616",
265
+ user_id_by_app: "3216904426693862293",
266
+ event_name: "user_send_video",
267
+ timestamp: "1754405178261",
268
+ sender: { id: "4411682737790366300" },
269
+ recipient: { id: "579745863508352884" },
270
+ message: {
271
+ msg_id: "message_id_123",
272
+ text: "Check out this video",
273
+ attachments: [
274
+ {
275
+ type: "video",
276
+ payload: {
277
+ thumbnail: "https://example.com/video_thumb.jpg",
278
+ description: "Amazing video content",
279
+ url: "https://example.com/video.mp4",
280
+ },
281
+ },
282
+ ],
283
+ },
284
+ };
285
+ ```
286
+
287
+ ### User Send File Event
288
+
289
+ ```typescript
290
+ import { UserSendFileEvent } from "redai-zalo-sdk";
291
+
292
+ const fileEvent: UserSendFileEvent = {
293
+ app_id: "3482178216594085616",
294
+ user_id_by_app: "3216904426693862293",
295
+ event_name: "user_send_file",
296
+ timestamp: "1754405178261",
297
+ sender: { id: "4411682737790366300" },
298
+ recipient: { id: "579745863508352884" },
299
+ message: {
300
+ msg_id: "message_id_123",
301
+ attachments: [
302
+ {
303
+ type: "file",
304
+ payload: {
305
+ url: "https://example.com/document.pdf",
306
+ size: "1024000",
307
+ name: "important_document.pdf",
308
+ checksum: "abc123def456",
309
+ type: "application/pdf",
310
+ },
311
+ },
312
+ ],
313
+ },
314
+ };
315
+ ```
316
+
317
+ ### User Received Message Event
318
+
319
+ ```typescript
320
+ import { UserReceivedMessageEvent } from "redai-zalo-sdk";
321
+
322
+ const receivedEvent: UserReceivedMessageEvent = {
323
+ app_id: "3482178216594085616",
324
+ user_id_by_app: "3216904426693862293",
325
+ event_name: "user_received_message",
326
+ timestamp: "1754405178259",
327
+ sender: { id: "579745863508352884" }, // OA sent
328
+ recipient: { id: "4411682737790366300" }, // User received
329
+ message: {
330
+ msg_id: "message_id_123",
331
+ },
332
+ };
333
+ ```
334
+
335
+ ### User Seen Message Event
336
+
337
+ ```typescript
338
+ import { UserSeenMessageEvent } from "redai-zalo-sdk";
339
+
340
+ const seenEvent: UserSeenMessageEvent = {
341
+ app_id: "3482178216594085616",
342
+ user_id_by_app: "3216904426693862293",
343
+ event_name: "user_seen_message",
344
+ timestamp: "1754405178259",
345
+ sender: { id: "579745863508352884" }, // OA
346
+ recipient: { id: "4411682737790366300" }, // User
347
+ message: {
348
+ msg_ids: ["message_id_123", "message_id_124"],
349
+ },
350
+ };
351
+ ```
352
+
353
+ ## User Action Events
354
+
355
+ ### User Follow Event
356
+
357
+ ```typescript
358
+ import { UserFollowEvent } from "redai-zalo-sdk";
359
+
360
+ const followEvent: UserFollowEvent = {
361
+ app_id: "3482178216594085616",
362
+ user_id_by_app: "3216904426693862293",
363
+ event_name: "follow",
364
+ timestamp: "1754405178260",
365
+ oa_id: "579745863508352884",
366
+ source: "testing_webhook",
367
+ follower: {
368
+ id: "4411682737790366300",
369
+ },
370
+ };
371
+ ```
372
+
373
+ ### User Unfollow Event
374
+
375
+ ```typescript
376
+ import { UserUnfollowEvent } from "redai-zalo-sdk";
377
+
378
+ const unfollowEvent: UserUnfollowEvent = {
379
+ app_id: "3482178216594085616",
380
+ user_id_by_app: "3216904426693862293",
381
+ event_name: "unfollow",
382
+ timestamp: "1754405178260",
383
+ oa_id: "579745863508352884",
384
+ source: "testing_webhook",
385
+ follower: {
386
+ id: "4411682737790366300",
387
+ },
388
+ };
389
+ ```
390
+
391
+ ### User Submit Info Event
392
+
393
+ ```typescript
394
+ import { UserSubmitInfoEvent } from "redai-zalo-sdk";
395
+
396
+ const submitInfoEvent: UserSubmitInfoEvent = {
397
+ app_id: "3482178216594085616",
398
+ user_id_by_app: "3216904426693862293",
399
+ event_name: "user_submit_info",
400
+ timestamp: "1754405178260",
401
+ sender: { id: "4411682737790366300" },
402
+ recipient: { id: "579745863508352884" },
403
+ info: {
404
+ address: "123 Main Street",
405
+ phone: "0123456789",
406
+ city: "Ho Chi Minh City",
407
+ district: "District 1",
408
+ name: "John Doe",
409
+ ward: "Ward 1",
410
+ },
411
+ };
412
+ ```
413
+
414
+ ## Shop Events
415
+
416
+ ### Shop Has Order Event
417
+
418
+ ```typescript
419
+ import { ShopHasOrderEvent } from "redai-zalo-sdk";
420
+
421
+ const orderEvent: ShopHasOrderEvent = {
422
+ app_id: "3482178216594085616",
423
+ user_id_by_app: "3216904426693862293",
424
+ event_name: "shop_has_order",
425
+ timestamp: "1754405178260",
426
+ oa_id: "579745863508352884",
427
+ customer: {
428
+ id: "4411682737790366300",
429
+ },
430
+ };
431
+ ```
432
+
433
+ ## OA Message Events
434
+
435
+ ### OA Send Text Event
436
+
437
+ ```typescript
438
+ import { OASendTextEvent } from "redai-zalo-sdk";
439
+
440
+ const oaTextEvent: OASendTextEvent = {
441
+ app_id: "3482178216594085616",
442
+ user_id_by_app: "3216904426693862293",
443
+ event_name: "oa_send_text",
444
+ timestamp: "1754405178260",
445
+ sender: { id: "579745863508352884" },
446
+ recipient: { id: "4411682737790366300" },
447
+ message: {
448
+ msg_id: "oa_message_123",
449
+ text: "Hello from Official Account",
450
+ // Optional: reply to an existing message
451
+ quote_msg_id: "96d3cdf3af150460909",
452
+ },
453
+ };
454
+ ```
455
+
456
+ ### OA Send Image Event
457
+
458
+ ```typescript
459
+ import { OASendImageEvent } from "redai-zalo-sdk";
460
+
461
+ const oaImageEvent: OASendImageEvent = {
462
+ app_id: "3482178216594085616",
463
+ user_id_by_app: "3216904426693862293",
464
+ event_name: "oa_send_image",
465
+ timestamp: "1754405178260",
466
+ sender: { id: "579745863508352884" },
467
+ recipient: { id: "4411682737790366300" },
468
+ message: {
469
+ msg_id: "oa_message_123",
470
+ text: "Check out our product",
471
+ attachments: [
472
+ {
473
+ type: "image",
474
+ payload: {
475
+ thumbnail: "https://example.com/thumb.jpg",
476
+ url: "https://example.com/product.jpg",
477
+ },
478
+ },
479
+ ],
480
+ },
481
+ };
482
+ ```
483
+
484
+ ### OA Send List Event (Interactive Message)
485
+
486
+ ```typescript
487
+ import { OASendListEvent } from "redai-zalo-sdk";
488
+
489
+ const oaListEvent: OASendListEvent = {
490
+ app_id: "3482178216594085616",
491
+ user_id_by_app: "3216904426693862293",
492
+ event_name: "oa_send_list",
493
+ timestamp: "1754405178260",
494
+ sender: { id: "579745863508352884" },
495
+ recipient: { id: "4411682737790366300" },
496
+ message: {
497
+ msg_id: "oa_message_123",
498
+ text: "Choose from our options",
499
+ attachments: [
500
+ {
501
+ type: "link",
502
+ payload: {
503
+ thumbnail: "https://example.com/option1.jpg",
504
+ description: "Option 1 description",
505
+ url: "https://example.com/option1",
506
+ title: "Option 1",
507
+ },
508
+ },
509
+ {
510
+ type: "link",
511
+ payload: {
512
+ thumbnail: "https://example.com/option2.jpg",
513
+ description: "Option 2 description",
514
+ url: "https://example.com/option2",
515
+ title: "Option 2",
516
+ },
517
+ },
518
+ ],
519
+ },
520
+ };
521
+ ```
522
+
523
+ ### OA Send File Event
524
+
525
+ ```typescript
526
+ import { OASendFileEvent } from "redai-zalo-sdk";
527
+
528
+ const oaFileEvent: OASendFileEvent = {
529
+ app_id: "3482178216594085616",
530
+ user_id_by_app: "3216904426693862293",
531
+ event_name: "oa_send_file",
532
+ timestamp: "1754405178261",
533
+ sender: { id: "579745863508352884" },
534
+ recipient: { id: "4411682737790366300" },
535
+ message: {
536
+ msg_id: "oa_message_123",
537
+ attachments: [
538
+ {
539
+ type: "file",
540
+ payload: {
541
+ url: "https://example.com/document.pdf",
542
+ size: "1024000",
543
+ name: "important_document.pdf",
544
+ checksum: "abc123def456",
545
+ type: "application/pdf",
546
+ },
547
+ },
548
+ ],
549
+ },
550
+ };
551
+ ```
552
+
553
+ ### OA Send Sticker Event
554
+
555
+ ```typescript
556
+ import { OASendStickerEvent } from "redai-zalo-sdk";
557
+
558
+ const oaStickerEvent: OASendStickerEvent = {
559
+ app_id: "3482178216594085616",
560
+ user_id_by_app: "3216904426693862293",
561
+ event_name: "oa_send_sticker",
562
+ timestamp: "1754405178261",
563
+ sender: { id: "579745863508352884" },
564
+ recipient: { id: "4411682737790366300" },
565
+ message: {
566
+ msg_id: "oa_message_123",
567
+ text: "Have a great day!",
568
+ attachments: [
569
+ {
570
+ type: "sticker",
571
+ payload: {
572
+ id: "sticker_123",
573
+ url: "https://example.com/sticker.png",
574
+ },
575
+ },
576
+ ],
577
+ },
578
+ };
579
+ ```
580
+
581
+ ## User Interaction Events
582
+
583
+ ### User Click Chat Now Event
584
+
585
+ ```typescript
586
+ import { UserClickChatNowEvent } from "redai-zalo-sdk";
587
+
588
+ const clickChatEvent: UserClickChatNowEvent = {
589
+ app_id: "3482178216594085616",
590
+ user_id_by_app: "3216904426693862293",
591
+ event_name: "user_click_chatnow",
592
+ timestamp: "1754405178261",
593
+ oa_id: "579745863508352884",
594
+ user_id: "4411682737790366300",
595
+ };
596
+ ```
597
+
598
+ ### User Reacted Message Event
599
+
600
+ ```typescript
601
+ import { UserReactedMessageEvent } from "redai-zalo-sdk";
602
+
603
+ const userReactionEvent: UserReactedMessageEvent = {
604
+ app_id: "3482178216594085616",
605
+ user_id_by_app: "3216904426693862293",
606
+ event_name: "user_reacted_message",
607
+ timestamp: "1754405178261",
608
+ sender: { id: "4411682737790366300" },
609
+ recipient: { id: "579745863508352884" },
610
+ message: {
611
+ msg_id: "message_123",
612
+ react_icon: "👍",
613
+ },
614
+ };
615
+ ```
616
+
617
+ ### OA Reacted Message Event
618
+
619
+ ```typescript
620
+ import { OAReactedMessageEvent } from "redai-zalo-sdk";
621
+
622
+ const oaReactionEvent: OAReactedMessageEvent = {
623
+ app_id: "3482178216594085616",
624
+ user_id_by_app: "3216904426693862293",
625
+ event_name: "oa_reacted_message",
626
+ timestamp: "1754405178261",
627
+ sender: { id: "579745863508352884" },
628
+ recipient: { id: "4411682737790366300" },
629
+ message: {
630
+ msg_id: "message_123",
631
+ react_icon: "❤️",
632
+ },
633
+ };
634
+ ```
635
+
636
+ ## Consent Events
637
+
638
+ ### OA Send Consent Event
639
+
640
+ ```typescript
641
+ import { OASendConsentEvent } from "redai-zalo-sdk";
642
+
643
+ const consentEvent: OASendConsentEvent = {
644
+ app_id: "3482178216594085616",
645
+ user_id_by_app: "3216904426693862293",
646
+ event_name: "oa_send_consent",
647
+ timestamp: "1754405178261",
648
+ oa_id: "579745863508352884",
649
+ request_type: "SENT",
650
+ create_time: "1754405178261",
651
+ expired_time: "1754405178261",
652
+ phone: "84773543888",
653
+ };
654
+ ```
655
+
656
+ ### User Reply Consent Event
657
+
658
+ ```typescript
659
+ import { UserReplyConsentEvent } from "redai-zalo-sdk";
660
+
661
+ const replyConsentEvent: UserReplyConsentEvent = {
662
+ app_id: "3482178216594085616",
663
+ user_id_by_app: "3216904426693862293",
664
+ event_name: "user_reply_consent",
665
+ timestamp: "1754405178261",
666
+ oa_id: "579745863508352884",
667
+ expired_time: "1754405178261",
668
+ confirmed_time: "1754405178261",
669
+ phone: "84773543888",
670
+ };
671
+ ```
672
+
673
+ ## Anonymous User Events
674
+
675
+ ### Anonymous Send Text Event
676
+
677
+ ```typescript
678
+ import { AnonymousSendTextEvent } from "redai-zalo-sdk";
679
+
680
+ const anonymousTextEvent: AnonymousSendTextEvent = {
681
+ app_id: "3482178216594085616",
682
+ user_id_by_app: "3216904426693862293",
683
+ event_name: "anonymous_send_text",
684
+ timestamp: "1754405178261",
685
+ sender: { id: "4411682737790366300" },
686
+ recipient: { id: "579745863508352884" },
687
+ message: {
688
+ msg_id: "message_123",
689
+ text: "Anonymous message",
690
+ // Optional: reply to an existing message
691
+ quote_msg_id: "96d3cdf3af150460909",
692
+ conversation_id: "conversation_123",
693
+ },
694
+ };
695
+ ```
696
+
697
+ ### Anonymous Send Image Event
698
+
699
+ ```typescript
700
+ import { AnonymousSendImageEvent } from "redai-zalo-sdk";
701
+
702
+ const anonymousImageEvent: AnonymousSendImageEvent = {
703
+ app_id: "3482178216594085616",
704
+ user_id_by_app: "3216904426693862293",
705
+ event_name: "anonymous_send_image",
706
+ timestamp: "1754405178262",
707
+ sender: { id: "4411682737790366300" },
708
+ recipient: { id: "579745863508352884" },
709
+ message: {
710
+ msg_id: "message_123",
711
+ text: "Anonymous image",
712
+ // Optional: reply to an existing message
713
+ quote_msg_id: "96d3cdf3af150460909",
714
+ conversation_id: "conversation_123",
715
+ attachments: [
716
+ {
717
+ type: "image",
718
+ payload: {
719
+ thumbnail: "https://example.com/thumb.jpg",
720
+ url: "https://example.com/image.jpg",
721
+ },
722
+ },
723
+ ],
724
+ },
725
+ };
726
+ ```
727
+
728
+ ### Anonymous Send File Event
729
+
730
+ ```typescript
731
+ import { AnonymousSendFileEvent } from "redai-zalo-sdk";
732
+
733
+ const anonymousFileEvent: AnonymousSendFileEvent = {
734
+ app_id: "3482178216594085616",
735
+ user_id_by_app: "3216904426693862293",
736
+ event_name: "anonymous_send_file",
737
+ timestamp: "1754405178262",
738
+ sender: { id: "4411682737790366300" },
739
+ recipient: { id: "579745863508352884" },
740
+ message: {
741
+ msg_id: "message_123",
742
+ // Optional: reply to an existing message
743
+ quote_msg_id: "96d3cdf3af150460909",
744
+ conversation_id: "conversation_123",
745
+ attachments: [
746
+ {
747
+ type: "file",
748
+ payload: {
749
+ url: "https://example.com/document.pdf",
750
+ size: "1024000",
751
+ name: "document.pdf",
752
+ checksum: "abc123def456",
753
+ type: "application/pdf",
754
+ },
755
+ },
756
+ ],
757
+ },
758
+ };
759
+ ```
760
+
761
+ ## Type Guards and Utilities
762
+
763
+ ### Check Event Type
764
+
765
+ ```typescript
766
+ import {
767
+ isMessageEvent,
768
+ isFollowEvent,
769
+ hasAttachments,
770
+ WebhookEvent,
771
+ } from "@warriorteam/redai-zalo-sdk";
772
+
773
+ function handleWebhook(event: WebhookEvent) {
774
+ if (isMessageEvent(event)) {
775
+ console.log("Message event:", event.event_name);
776
+
777
+ if ("message" in event && hasAttachments(event.message)) {
778
+ console.log("Has attachments:", event.message.attachments.length);
779
+ }
780
+ }
781
+
782
+ if (isFollowEvent(event)) {
783
+ console.log("Follower event:", event.event_name);
784
+ }
785
+ }
786
+ ```
787
+
788
+ ### Using Enums
789
+
790
+ ```typescript
791
+ import { WebhookEventName, AttachmentType } from "redai-zalo-sdk";
792
+
793
+ function processEvent(event: WebhookEvent) {
794
+ switch (event.event_name) {
795
+ case WebhookEventName.USER_SEND_TEXT:
796
+ console.log("Text message received");
797
+ break;
798
+
799
+ case WebhookEventName.USER_SEND_IMAGE:
800
+ console.log("Image message received");
801
+ break;
802
+
803
+ case WebhookEventName.FOLLOW:
804
+ console.log("User followed OA");
805
+ break;
806
+ }
807
+ }
808
+ ```
809
+
810
+ ## Webhook Handler Setup
811
+
812
+ ```typescript
813
+ import { WebhookHandlers, UserSendTextEvent } from "redai-zalo-sdk";
814
+
815
+ const handlers: WebhookHandlers = {
816
+ user_send_text: async (event: UserSendTextEvent) => {
817
+ console.log(`User ${event.sender.id} sent: ${event.message.text}`);
818
+ // Handle text message
819
+ },
820
+
821
+ user_send_image: async (event) => {
822
+ console.log(`User sent image: ${event.message.attachments[0].payload.url}`);
823
+ // Handle image message
824
+ },
825
+
826
+ follow: async (event) => {
827
+ console.log(`New follower: ${event.follower.id}`);
828
+ // Handle follow event
829
+ },
830
+
831
+ "*": async (event) => {
832
+ console.log(`Unhandled event: ${event.event_name}`);
833
+ // Catch-all handler
834
+ },
835
+ };
836
+ ```
837
+
838
+ ## Best Practices
839
+
840
+ 1. **Type Safety**: Always use the specific event types instead of generic ones
841
+ 2. **Type Guards**: Use provided type guards to safely check event types
842
+ 3. **Error Handling**: Implement proper error handling for webhook processing
843
+ 4. **Validation**: Validate webhook signatures for security
844
+ 5. **Async Processing**: Use async handlers for database operations or API calls
845
+
846
+ ## Migration from Legacy Types
847
+
848
+ If you're migrating from the old `UserSendMessageEvent` type:
849
+
850
+ ```typescript
851
+ // Old way (deprecated)
852
+ user_send_text?: WebhookHandler<UserSendMessageEvent>;
853
+
854
+ // New way (recommended)
855
+ user_send_text?: WebhookHandler<UserSendTextEvent>;
856
+ ```
857
+
858
+ The new types provide better type safety and more specific payload structures for each event type.