@warriorteam/redai-zalo-sdk
Version:
Comprehensive TypeScript/JavaScript SDK for Zalo APIs - Official Account v3.0, ZNS with Full Type Safety, Consultation Service, Broadcast Service, Group Messaging with List APIs, Social APIs, Enhanced Article Management, Promotion Service v3.0 with Multip
859 lines (725 loc) • 22.3 kB
Markdown
# Webhook Events Documentation
> Source of truth: The full, strongly-typed webhook definitions live in `src/types/webhook.ts`.
>
> • GitHub: https://github.com/warriorteam/redai-zalo-sdk/blob/main/src/types/webhook.ts
## Table of Contents
- Overview
- Event Categories
- Types & Enums Summary
- Message Events (examples)
- User Action Events (examples)
- Shop Events (examples)
- OA Message Events (examples)
- User Interaction Events (examples)
- Consent Events (examples)
- Anonymous User Events (examples)
- Type Guards and Utilities
- Webhook Handler Setup
- Best Practices
- Migration from Legacy Types
## Types & Enums Summary
- Union types
- `WebhookEvent` – Tập hợp tất cả event types
- `MessageWebhookEvent`, `UserActionWebhookEvent`, `ShopWebhookEvent`, `SystemWebhookEvent`, `AnonymousWebhookEvent`, `CallWebhookEvent`, `ZNSWebhookEvent`, `GroupWebhookEvent`, `WidgetWebhookEvent`
- Handler map
- `WebhookHandlers` – Bản đồ event_name -> handler function có type an toàn
- Enums
- `WebhookEventName` – Tên event chuẩn (string enum)
- `AttachmentType` – Loại attachment: image, file, audio, video, gif, link, location, sticker
- Type guards chính (đều export từ package)
- `isMessageEvent`, `isFollowEvent`, `isUserActionEvent`, `isShopEvent`, `isOAMessageEvent`, `isAnonymousEvent`, `isCallEvent`, `isTemplateEvent`, `isBusinessCardEvent`, `isFeedbackEvent`, `isZNSEvent`, `isGroupEvent`, `isJourneyEvent`, `isReactionEvent`, `isConsentEvent`, `isUpdateUserInfoEvent`, `hasAttachments`
- Message shape
- `message.msg_id: string` — ID của tin nhắn
- `message.text?: string` — Nội dung text (nếu là text)
- `message.attachments?: Attachment[]` — Có mặt khi là tin nhắn đa phương tiện (image, gif, video, file, link, location, sticker)
- `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)
This document describes the webhook event types and DTOs for Zalo Official Account webhooks.
## Overview
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.
## Event Categories
### 1. Message Events
Events triggered when users interact with your Official Account through messages.
### 2. User Action Events
Events triggered when users perform actions like following your Official Account.
### 3. Legacy Events
Backward compatibility events for existing integrations.
## Message Events
### User Send Text Event
```typescript
import { UserSendTextEvent } from "redai-zalo-sdk";
const textEvent: UserSendTextEvent = {
app_id: "3482178216594085616",
user_id_by_app: "3216904426693862293",
event_name: "user_send_text",
timestamp: "1754405178258",
sender: { id: "4411682737790366300" },
recipient: { id: "579745863508352884" },
message: {
msg_id: "message_id_123",
text: "Hello from user",
},
};
// Optional: reply to an existing message
quote_msg_id: "96d3cdf3af150460909",
```
### User Send Image Event
```typescript
import { UserSendImageEvent } from "redai-zalo-sdk";
const imageEvent: UserSendImageEvent = {
app_id: "3482178216594085616",
user_id_by_app: "3216904426693862293",
event_name: "user_send_image",
timestamp: "1754405178258",
sender: { id: "4411682737790366300" },
recipient: { id: "579745863508352884" },
message: {
msg_id: "message_id_123",
text: "Check out this image",
attachments: [
{
type: "image",
payload: {
thumbnail: "https://example.com/thumb.jpg",
url: "https://example.com/image.jpg",
},
},
],
},
};
```
### User Send Location Event
```typescript
import { UserSendLocationEvent } from "redai-zalo-sdk";
const locationEvent: UserSendLocationEvent = {
app_id: "3482178216594085616",
user_id_by_app: "3216904426693862293",
event_name: "user_send_location",
timestamp: "1754405178257",
sender: { id: "4411682737790366300" },
recipient: { id: "579745863508352884" },
message: {
msg_id: "message_id_123",
text: "My current location",
attachments: [
{
type: "location",
payload: {
coordinates: {
latitude: "10.7642473",
longitude: "106.6564313999999",
},
},
},
],
},
};
```
### User Send Link Event
```typescript
import { UserSendLinkEvent } from "redai-zalo-sdk";
const linkEvent: UserSendLinkEvent = {
app_id: "3482178216594085616",
user_id_by_app: "3216904426693862293",
event_name: "user_send_link",
timestamp: "1754405178258",
sender: { id: "4411682737790366300" },
recipient: { id: "579745863508352884" },
message: {
msg_id: "message_id_123",
text: "Check this link",
attachments: [
{
type: "link",
payload: {
thumbnail: "https://example.com/thumb.jpg",
description: "Interesting article",
url: "https://example.com/article",
},
},
],
},
};
```
### User Send Sticker Event
```typescript
import { UserSendStickerEvent } from "redai-zalo-sdk";
const stickerEvent: UserSendStickerEvent = {
app_id: "3482178216594085616",
user_id_by_app: "3216904426693862293",
event_name: "user_send_sticker",
timestamp: "1754405178259",
sender: { id: "4411682737790366300" },
recipient: { id: "579745863508352884" },
message: {
msg_id: "message_id_123",
text: "😊",
attachments: [
{
type: "sticker",
payload: {
id: "sticker_123",
url: "https://example.com/sticker.png",
},
},
],
},
};
```
### User Send GIF Event
```typescript
import { UserSendGifEvent } from "redai-zalo-sdk";
const gifEvent: UserSendGifEvent = {
app_id: "3482178216594085616",
user_id_by_app: "3216904426693862293",
event_name: "user_send_gif",
timestamp: "1754405178259",
sender: { id: "4411682737790366300" },
recipient: { id: "579745863508352884" },
message: {
msg_id: "message_id_123",
text: "Funny GIF",
attachments: [
{
type: "gif",
payload: {
thumbnail: "https://example.com/gif_thumb.jpg",
url: "https://example.com/funny.gif",
},
},
],
},
};
```
### User Send Audio Event
```typescript
import { UserSendAudioEvent } from "redai-zalo-sdk";
const audioEvent: UserSendAudioEvent = {
app_id: "3482178216594085616",
user_id_by_app: "3216904426693862293",
event_name: "user_send_audio",
timestamp: "1754405178259",
sender: { id: "4411682737790366300" },
recipient: { id: "579745863508352884" },
message: {
msg_id: "message_id_123",
text: "Voice message",
attachments: [
{
type: "audio",
payload: {
url: "https://example.com/voice.mp3",
},
},
],
},
};
```
### User Send Video Event
```typescript
import { UserSendVideoEvent } from "redai-zalo-sdk";
const videoEvent: UserSendVideoEvent = {
app_id: "3482178216594085616",
user_id_by_app: "3216904426693862293",
event_name: "user_send_video",
timestamp: "1754405178261",
sender: { id: "4411682737790366300" },
recipient: { id: "579745863508352884" },
message: {
msg_id: "message_id_123",
text: "Check out this video",
attachments: [
{
type: "video",
payload: {
thumbnail: "https://example.com/video_thumb.jpg",
description: "Amazing video content",
url: "https://example.com/video.mp4",
},
},
],
},
};
```
### User Send File Event
```typescript
import { UserSendFileEvent } from "redai-zalo-sdk";
const fileEvent: UserSendFileEvent = {
app_id: "3482178216594085616",
user_id_by_app: "3216904426693862293",
event_name: "user_send_file",
timestamp: "1754405178261",
sender: { id: "4411682737790366300" },
recipient: { id: "579745863508352884" },
message: {
msg_id: "message_id_123",
attachments: [
{
type: "file",
payload: {
url: "https://example.com/document.pdf",
size: "1024000",
name: "important_document.pdf",
checksum: "abc123def456",
type: "application/pdf",
},
},
],
},
};
```
### User Received Message Event
```typescript
import { UserReceivedMessageEvent } from "redai-zalo-sdk";
const receivedEvent: UserReceivedMessageEvent = {
app_id: "3482178216594085616",
user_id_by_app: "3216904426693862293",
event_name: "user_received_message",
timestamp: "1754405178259",
sender: { id: "579745863508352884" }, // OA sent
recipient: { id: "4411682737790366300" }, // User received
message: {
msg_id: "message_id_123",
},
};
```
### User Seen Message Event
```typescript
import { UserSeenMessageEvent } from "redai-zalo-sdk";
const seenEvent: UserSeenMessageEvent = {
app_id: "3482178216594085616",
user_id_by_app: "3216904426693862293",
event_name: "user_seen_message",
timestamp: "1754405178259",
sender: { id: "579745863508352884" }, // OA
recipient: { id: "4411682737790366300" }, // User
message: {
msg_ids: ["message_id_123", "message_id_124"],
},
};
```
## User Action Events
### User Follow Event
```typescript
import { UserFollowEvent } from "redai-zalo-sdk";
const followEvent: UserFollowEvent = {
app_id: "3482178216594085616",
user_id_by_app: "3216904426693862293",
event_name: "follow",
timestamp: "1754405178260",
oa_id: "579745863508352884",
source: "testing_webhook",
follower: {
id: "4411682737790366300",
},
};
```
### User Unfollow Event
```typescript
import { UserUnfollowEvent } from "redai-zalo-sdk";
const unfollowEvent: UserUnfollowEvent = {
app_id: "3482178216594085616",
user_id_by_app: "3216904426693862293",
event_name: "unfollow",
timestamp: "1754405178260",
oa_id: "579745863508352884",
source: "testing_webhook",
follower: {
id: "4411682737790366300",
},
};
```
### User Submit Info Event
```typescript
import { UserSubmitInfoEvent } from "redai-zalo-sdk";
const submitInfoEvent: UserSubmitInfoEvent = {
app_id: "3482178216594085616",
user_id_by_app: "3216904426693862293",
event_name: "user_submit_info",
timestamp: "1754405178260",
sender: { id: "4411682737790366300" },
recipient: { id: "579745863508352884" },
info: {
address: "123 Main Street",
phone: "0123456789",
city: "Ho Chi Minh City",
district: "District 1",
name: "John Doe",
ward: "Ward 1",
},
};
```
## Shop Events
### Shop Has Order Event
```typescript
import { ShopHasOrderEvent } from "redai-zalo-sdk";
const orderEvent: ShopHasOrderEvent = {
app_id: "3482178216594085616",
user_id_by_app: "3216904426693862293",
event_name: "shop_has_order",
timestamp: "1754405178260",
oa_id: "579745863508352884",
customer: {
id: "4411682737790366300",
},
};
```
## OA Message Events
### OA Send Text Event
```typescript
import { OASendTextEvent } from "redai-zalo-sdk";
const oaTextEvent: OASendTextEvent = {
app_id: "3482178216594085616",
user_id_by_app: "3216904426693862293",
event_name: "oa_send_text",
timestamp: "1754405178260",
sender: { id: "579745863508352884" },
recipient: { id: "4411682737790366300" },
message: {
msg_id: "oa_message_123",
text: "Hello from Official Account",
// Optional: reply to an existing message
quote_msg_id: "96d3cdf3af150460909",
},
};
```
### OA Send Image Event
```typescript
import { OASendImageEvent } from "redai-zalo-sdk";
const oaImageEvent: OASendImageEvent = {
app_id: "3482178216594085616",
user_id_by_app: "3216904426693862293",
event_name: "oa_send_image",
timestamp: "1754405178260",
sender: { id: "579745863508352884" },
recipient: { id: "4411682737790366300" },
message: {
msg_id: "oa_message_123",
text: "Check out our product",
attachments: [
{
type: "image",
payload: {
thumbnail: "https://example.com/thumb.jpg",
url: "https://example.com/product.jpg",
},
},
],
},
};
```
### OA Send List Event (Interactive Message)
```typescript
import { OASendListEvent } from "redai-zalo-sdk";
const oaListEvent: OASendListEvent = {
app_id: "3482178216594085616",
user_id_by_app: "3216904426693862293",
event_name: "oa_send_list",
timestamp: "1754405178260",
sender: { id: "579745863508352884" },
recipient: { id: "4411682737790366300" },
message: {
msg_id: "oa_message_123",
text: "Choose from our options",
attachments: [
{
type: "link",
payload: {
thumbnail: "https://example.com/option1.jpg",
description: "Option 1 description",
url: "https://example.com/option1",
title: "Option 1",
},
},
{
type: "link",
payload: {
thumbnail: "https://example.com/option2.jpg",
description: "Option 2 description",
url: "https://example.com/option2",
title: "Option 2",
},
},
],
},
};
```
### OA Send File Event
```typescript
import { OASendFileEvent } from "redai-zalo-sdk";
const oaFileEvent: OASendFileEvent = {
app_id: "3482178216594085616",
user_id_by_app: "3216904426693862293",
event_name: "oa_send_file",
timestamp: "1754405178261",
sender: { id: "579745863508352884" },
recipient: { id: "4411682737790366300" },
message: {
msg_id: "oa_message_123",
attachments: [
{
type: "file",
payload: {
url: "https://example.com/document.pdf",
size: "1024000",
name: "important_document.pdf",
checksum: "abc123def456",
type: "application/pdf",
},
},
],
},
};
```
### OA Send Sticker Event
```typescript
import { OASendStickerEvent } from "redai-zalo-sdk";
const oaStickerEvent: OASendStickerEvent = {
app_id: "3482178216594085616",
user_id_by_app: "3216904426693862293",
event_name: "oa_send_sticker",
timestamp: "1754405178261",
sender: { id: "579745863508352884" },
recipient: { id: "4411682737790366300" },
message: {
msg_id: "oa_message_123",
text: "Have a great day!",
attachments: [
{
type: "sticker",
payload: {
id: "sticker_123",
url: "https://example.com/sticker.png",
},
},
],
},
};
```
## User Interaction Events
### User Click Chat Now Event
```typescript
import { UserClickChatNowEvent } from "redai-zalo-sdk";
const clickChatEvent: UserClickChatNowEvent = {
app_id: "3482178216594085616",
user_id_by_app: "3216904426693862293",
event_name: "user_click_chatnow",
timestamp: "1754405178261",
oa_id: "579745863508352884",
user_id: "4411682737790366300",
};
```
### User Reacted Message Event
```typescript
import { UserReactedMessageEvent } from "redai-zalo-sdk";
const userReactionEvent: UserReactedMessageEvent = {
app_id: "3482178216594085616",
user_id_by_app: "3216904426693862293",
event_name: "user_reacted_message",
timestamp: "1754405178261",
sender: { id: "4411682737790366300" },
recipient: { id: "579745863508352884" },
message: {
msg_id: "message_123",
react_icon: "👍",
},
};
```
### OA Reacted Message Event
```typescript
import { OAReactedMessageEvent } from "redai-zalo-sdk";
const oaReactionEvent: OAReactedMessageEvent = {
app_id: "3482178216594085616",
user_id_by_app: "3216904426693862293",
event_name: "oa_reacted_message",
timestamp: "1754405178261",
sender: { id: "579745863508352884" },
recipient: { id: "4411682737790366300" },
message: {
msg_id: "message_123",
react_icon: "❤️",
},
};
```
## Consent Events
### OA Send Consent Event
```typescript
import { OASendConsentEvent } from "redai-zalo-sdk";
const consentEvent: OASendConsentEvent = {
app_id: "3482178216594085616",
user_id_by_app: "3216904426693862293",
event_name: "oa_send_consent",
timestamp: "1754405178261",
oa_id: "579745863508352884",
request_type: "SENT",
create_time: "1754405178261",
expired_time: "1754405178261",
phone: "84773543888",
};
```
### User Reply Consent Event
```typescript
import { UserReplyConsentEvent } from "redai-zalo-sdk";
const replyConsentEvent: UserReplyConsentEvent = {
app_id: "3482178216594085616",
user_id_by_app: "3216904426693862293",
event_name: "user_reply_consent",
timestamp: "1754405178261",
oa_id: "579745863508352884",
expired_time: "1754405178261",
confirmed_time: "1754405178261",
phone: "84773543888",
};
```
## Anonymous User Events
### Anonymous Send Text Event
```typescript
import { AnonymousSendTextEvent } from "redai-zalo-sdk";
const anonymousTextEvent: AnonymousSendTextEvent = {
app_id: "3482178216594085616",
user_id_by_app: "3216904426693862293",
event_name: "anonymous_send_text",
timestamp: "1754405178261",
sender: { id: "4411682737790366300" },
recipient: { id: "579745863508352884" },
message: {
msg_id: "message_123",
text: "Anonymous message",
// Optional: reply to an existing message
quote_msg_id: "96d3cdf3af150460909",
conversation_id: "conversation_123",
},
};
```
### Anonymous Send Image Event
```typescript
import { AnonymousSendImageEvent } from "redai-zalo-sdk";
const anonymousImageEvent: AnonymousSendImageEvent = {
app_id: "3482178216594085616",
user_id_by_app: "3216904426693862293",
event_name: "anonymous_send_image",
timestamp: "1754405178262",
sender: { id: "4411682737790366300" },
recipient: { id: "579745863508352884" },
message: {
msg_id: "message_123",
text: "Anonymous image",
// Optional: reply to an existing message
quote_msg_id: "96d3cdf3af150460909",
conversation_id: "conversation_123",
attachments: [
{
type: "image",
payload: {
thumbnail: "https://example.com/thumb.jpg",
url: "https://example.com/image.jpg",
},
},
],
},
};
```
### Anonymous Send File Event
```typescript
import { AnonymousSendFileEvent } from "redai-zalo-sdk";
const anonymousFileEvent: AnonymousSendFileEvent = {
app_id: "3482178216594085616",
user_id_by_app: "3216904426693862293",
event_name: "anonymous_send_file",
timestamp: "1754405178262",
sender: { id: "4411682737790366300" },
recipient: { id: "579745863508352884" },
message: {
msg_id: "message_123",
// Optional: reply to an existing message
quote_msg_id: "96d3cdf3af150460909",
conversation_id: "conversation_123",
attachments: [
{
type: "file",
payload: {
url: "https://example.com/document.pdf",
size: "1024000",
name: "document.pdf",
checksum: "abc123def456",
type: "application/pdf",
},
},
],
},
};
```
## Type Guards and Utilities
### Check Event Type
```typescript
import {
isMessageEvent,
isFollowEvent,
hasAttachments,
WebhookEvent,
} from "@warriorteam/redai-zalo-sdk";
function handleWebhook(event: WebhookEvent) {
if (isMessageEvent(event)) {
console.log("Message event:", event.event_name);
if ("message" in event && hasAttachments(event.message)) {
console.log("Has attachments:", event.message.attachments.length);
}
}
if (isFollowEvent(event)) {
console.log("Follower event:", event.event_name);
}
}
```
### Using Enums
```typescript
import { WebhookEventName, AttachmentType } from "redai-zalo-sdk";
function processEvent(event: WebhookEvent) {
switch (event.event_name) {
case WebhookEventName.USER_SEND_TEXT:
console.log("Text message received");
break;
case WebhookEventName.USER_SEND_IMAGE:
console.log("Image message received");
break;
case WebhookEventName.FOLLOW:
console.log("User followed OA");
break;
}
}
```
## Webhook Handler Setup
```typescript
import { WebhookHandlers, UserSendTextEvent } from "redai-zalo-sdk";
const handlers: WebhookHandlers = {
user_send_text: async (event: UserSendTextEvent) => {
console.log(`User ${event.sender.id} sent: ${event.message.text}`);
// Handle text message
},
user_send_image: async (event) => {
console.log(`User sent image: ${event.message.attachments[0].payload.url}`);
// Handle image message
},
follow: async (event) => {
console.log(`New follower: ${event.follower.id}`);
// Handle follow event
},
"*": async (event) => {
console.log(`Unhandled event: ${event.event_name}`);
// Catch-all handler
},
};
```
## Best Practices
1. **Type Safety**: Always use the specific event types instead of generic ones
2. **Type Guards**: Use provided type guards to safely check event types
3. **Error Handling**: Implement proper error handling for webhook processing
4. **Validation**: Validate webhook signatures for security
5. **Async Processing**: Use async handlers for database operations or API calls
## Migration from Legacy Types
If you're migrating from the old `UserSendMessageEvent` type:
```typescript
// Old way (deprecated)
user_send_text?: WebhookHandler<UserSendMessageEvent>;
// New way (recommended)
user_send_text?: WebhookHandler<UserSendTextEvent>;
```
The new types provide better type safety and more specific payload structures for each event type.