Event Emitter
The WASocket instance includes an event emitter accessible via sock.ev. Use it to listen for WhatsApp events.
interface BaileysEventEmitter {
on<T extends BaileysEvent>(event: T, listener: (arg: BaileysEventMap[T]) => void): void
off<T extends BaileysEvent>(event: T, listener: (arg: BaileysEventMap[T]) => void): void
removeAllListeners<T extends BaileysEvent>(event: T): void
emit<T extends BaileysEvent>(event: T, arg: BaileysEventMap[T]): boolean
}
Example Usage
import makeWASocket from '@whiskeysockets/baileys'
const sock = makeWASocket({ auth: state })
// Listen to connection updates
sock.ev.on('connection.update', (update) => {
const { connection, lastDisconnect, qr } = update
if(qr) {
console.log('QR Code:', qr)
}
if(connection === 'close') {
console.log('Connection closed')
}
})
// Listen to new messages
sock.ev.on('messages.upsert', ({ messages, type }) => {
console.log('Received', messages.length, 'messages')
for(const msg of messages) {
console.log('Message from:', msg.key.remoteJid)
}
})
BaileysEventMap
All available events and their payload types.
Connection Events
Emitted when connection state changes (WebSocket opened, closed, connecting, etc.).sock.ev.on('connection.update', (update) => {
const { connection, lastDisconnect, qr, isNewLogin, isOnline } = update
if(connection === 'close') {
// Handle disconnect
const shouldReconnect = lastDisconnect?.error?.output?.statusCode !== DisconnectReason.loggedOut
if(shouldReconnect) {
// Reconnect
}
} else if(connection === 'open') {
console.log('Connected successfully')
}
})
connection
'open' | 'close' | 'connecting'
Current connection state
lastDisconnect
{ error?: Error; date?: Date }
Information about the last disconnection
QR code string for authentication (only during initial pairing)
Whether this is a new login session
Whether the phone is online
Authentication Events
creds.update
Partial<AuthenticationCreds>
Emitted when authentication credentials are updated. Always save these updates to maintain the session.const { state, saveCreds } = await useMultiFileAuthState('auth_info')
const sock = makeWASocket({ auth: state })
sock.ev.on('creds.update', saveCreds)
Message Events
Emitted when new messages are received or updated.sock.ev.on('messages.upsert', ({ messages, type }) => {
for(const msg of messages) {
if(!msg.key.fromMe && type === 'notify') {
console.log('New message from', msg.key.remoteJid)
console.log('Message:', msg.message)
}
}
})
type
MessageUpsertType
required
Type of upsert:
'notify' - Message received while connection was online
'append' - Message from history sync
Present if message was received from the phone due to it being unavailable
Emitted when message metadata is updated (status, reactions, edits, etc.).sock.ev.on('messages.update', (updates) => {
for(const update of updates) {
console.log('Message', update.key.id, 'updated')
if(update.update.status) {
console.log('New status:', update.update.status)
}
}
})
Each update contains:update
Partial<WAMessage>
required
Updated fields (status, reactions, pollUpdates, etc.)
Emitted when messages are deleted.sock.ev.on('messages.delete', (deletion) => {
if('keys' in deletion) {
// Specific messages deleted
console.log('Deleted messages:', deletion.keys)
} else {
// All messages in chat deleted
console.log('All messages deleted in:', deletion.jid)
}
})
Two possible formats:
{ keys: WAMessageKey[] } - Specific messages deleted
{ jid: string; all: true } - All messages in chat cleared
messages.reaction
Array<{ key: WAMessageKey; reaction: proto.IReaction }>
Emitted when messages receive reactions.sock.ev.on('messages.reaction', (reactions) => {
for(const { key, reaction } of reactions) {
console.log('Message', key.id, 'reacted with:', reaction.text)
if(!reaction.text) {
console.log('Reaction removed')
}
}
})
If reaction.text is falsy, the reaction was removed.
messages.media-update
Array<{ key: WAMessageKey; media?: object; error?: Boom }>
Emitted when media message metadata is updated.media
{ ciphertext: Uint8Array; iv: Uint8Array }
Updated media encryption data
Error if media update failed
message-receipt.update
MessageUserReceiptUpdate[]
Emitted when message receipts are updated (read, delivered, played).sock.ev.on('message-receipt.update', (receipts) => {
for(const receipt of receipts) {
console.log('Message', receipt.key.id, 'receipt updated')
}
})
Chat Events
Emitted when new chats are created.sock.ev.on('chats.upsert', (chats) => {
console.log('New chats:', chats.length)
for(const chat of chats) {
console.log('Chat ID:', chat.id)
}
})
Emitted when chat metadata is updated.sock.ev.on('chats.update', (updates) => {
for(const update of updates) {
console.log('Chat', update.id, 'updated')
if(update.unreadCount !== undefined) {
console.log('Unread count:', update.unreadCount)
}
}
})
Emitted when chats are deleted.sock.ev.on('chats.delete', (deletedChatIds) => {
console.log('Deleted chats:', deletedChatIds)
})
chats.lock
{ id: string; locked: boolean }
Emitted when a chat is locked or unlocked.
Emitted when new contacts are added.sock.ev.on('contacts.upsert', (contacts) => {
for(const contact of contacts) {
console.log('Contact:', contact.id, contact.name)
}
})
Emitted when contact information is updated.
Group Events
Emitted when new groups are created or joined.sock.ev.on('groups.upsert', (groups) => {
for(const group of groups) {
console.log('Group:', group.subject)
console.log('Participants:', group.participants.length)
}
})
Emitted when group metadata is updated (name, description, settings, etc.).sock.ev.on('groups.update', (updates) => {
for(const update of updates) {
console.log('Group', update.id, 'updated')
if(update.subject) {
console.log('New name:', update.subject)
}
}
})
group-participants.update
Emitted when group participants are added, removed, promoted, or demoted.sock.ev.on('group-participants.update', ({ id, participants, action }) => {
console.log('Group', id)
console.log('Action:', action) // 'add', 'remove', 'promote', 'demote'
console.log('Participants:', participants.map(p => p.id))
})
JID of the user who performed the action
participants
GroupParticipant[]
required
Affected participants
action
ParticipantAction
required
Action performed: 'add' | 'remove' | 'promote' | 'demote'
Emitted when someone requests to join a group.sock.ev.on('group.join-request', ({ id, participant, action }) => {
console.log('Join request in group', id)
console.log('Participant:', participant)
console.log('Action:', action) // 'created', 'revoked'
})
JID of the requesting user
action
RequestJoinAction
required
Action type
method
RequestJoinMethod
required
How the request was made
Emitted when labels are assigned to group members.
Presence Events
presence.update
{ id: string; presences: { [participant: string]: PresenceData } }
Emitted when presence status of contacts changes (typing, recording, online, etc.).sock.ev.on('presence.update', ({ id, presences }) => {
console.log('Presence update in', id)
for(const [participant, presence] of Object.entries(presences)) {
console.log(participant, 'is', presence.lastKnownPresence)
// 'unavailable', 'available', 'composing', 'recording'
}
})
History Sync Events
Emitted when history sync is received (chats, contacts, messages from paired device).sock.ev.on('messaging-history.set', ({ chats, contacts, messages, isLatest }) => {
console.log('Received', chats.length, 'chats')
console.log('Received', contacts.length, 'contacts')
console.log('Received', messages.length, 'messages')
console.log('Is latest:', isLatest)
})
Whether this is the most recent sync
syncType
proto.HistorySync.HistorySyncType | null
Type of history sync
Blocklist Events
Emitted when the complete blocklist is set.sock.ev.on('blocklist.set', ({ blocklist }) => {
console.log('Blocked users:', blocklist)
})
blocklist.update
{ blocklist: string[]; type: 'add' | 'remove' }
Emitted when users are added to or removed from the blocklist.sock.ev.on('blocklist.update', ({ blocklist, type }) => {
if(type === 'add') {
console.log('Blocked:', blocklist)
} else {
console.log('Unblocked:', blocklist)
}
})
Call Events
Emitted when calls are received, accepted, or rejected.sock.ev.on('call', (calls) => {
for(const call of calls) {
console.log('Call from:', call.from)
console.log('Call status:', call.status) // 'offer', 'accept', 'reject', etc.
console.log('Is video:', call.isVideo)
console.log('Is group:', call.isGroup)
}
})
Label Events
Emitted when a label is created, edited, or deleted.sock.ev.on('labels.edit', (label) => {
console.log('Label:', label.id, label.name)
})
labels.association
{ association: LabelAssociation; type: 'add' | 'remove' }
Emitted when a label is associated with or removed from a chat/message.sock.ev.on('labels.association', ({ association, type }) => {
console.log('Label', association.labelId, type, 'to', association.chatId)
})
Newsletter Events
Emitted when a newsletter message receives a reaction.reaction
{ code?: string; count?: number; removed?: boolean }
required
Reaction data
newsletter.view
{ id: string; server_id: string; count: number }
Emitted when newsletter message view count is updated.
newsletter-participants.update
Emitted when newsletter participants are updated.
newsletter-settings.update
{ id: string; update: any }
Emitted when newsletter settings are updated.
Settings Events
Emitted when WhatsApp settings are updated. Multiple types of settings:sock.ev.on('settings.update', (setting) => {
switch(setting.setting) {
case 'unarchiveChats':
console.log('Unarchive chats:', setting.value)
break
case 'locale':
console.log('Locale:', setting.value)
break
// ... other settings
}
})
Possible settings:
{ setting: 'unarchiveChats'; value: boolean }
{ setting: 'locale'; value: string }
{ setting: 'disableLinkPreviews'; value: proto.SyncActionValue.IPrivacySettingDisableLinkPreviewsAction }
{ setting: 'timeFormat'; value: proto.SyncActionValue.ITimeFormatAction }
- And more…
LID Mapping Events
Emitted when phone number to LID (Linkable Identifier) mappings are updated.This is used internally for WhatsApp’s multi-device protocol.