Skip to main content
Baileys uses an event-driven architecture. All socket events are typed through the BaileysEventMap interface.

BaileysEventEmitter

The event emitter interface used by Baileys sockets.
on
function
required
Register an event listener
on<T extends keyof BaileysEventMap>(
  event: T, 
  listener: (arg: BaileysEventMap[T]) => void
): void
off
function
required
Remove an event listener
off<T extends keyof BaileysEventMap>(
  event: T, 
  listener: (arg: BaileysEventMap[T]) => void
): void
removeAllListeners
function
required
Remove all listeners for an event
removeAllListeners<T extends keyof BaileysEventMap>(event: T): void
emit
function
required
Emit an event
emit<T extends keyof BaileysEventMap>(
  event: T, 
  arg: BaileysEventMap[T]
): boolean

BaileysEventMap

Complete mapping of all events to their payload types.

Connection Events

connection.update
Partial<ConnectionState>
Fired when connection state changes (WS opened, closed, connecting, etc.)
sock.ev.on('connection.update', (update) => {
  const { connection, lastDisconnect, qr } = update
  if (connection === 'close') {
    // Handle disconnection
  }
})

Authentication Events

creds.update
Partial<AuthenticationCreds>
Fired when credentials are updated (keys, identity, etc.)
sock.ev.on('creds.update', saveCreds)

Message Events

messages.upsert
object
New messages received or synced from history
sock.ev.on('messages.upsert', ({ messages, type }) => {
  for (const msg of messages) {
    if (type === 'notify') {
      console.log('New message:', msg)
    }
  }
})
messages.update
WAMessageUpdate[]
Updates to existing messages (delivery receipts, edits, etc.)
sock.ev.on('messages.update', (updates) => {
  for (const { key, update } of updates) {
    // update.status: delivered, read, etc.
  }
})
messages.delete
object
Messages deleted by user
// Specific messages
{ keys: WAMessageKey[] }

// All messages in a chat
{ jid: string; all: true }
messages.reaction
array
Reactions added/removed from messages
Array<{
  key: WAMessageKey
  reaction: proto.IReaction
}>
Example:
sock.ev.on('messages.reaction', (reactions) => {
  for (const { key, reaction } of reactions) {
    console.log(`${reaction.text} on message ${key.id}`)
  }
})
messages.media-update
array
Media encryption info updates
Array<{
  key: WAMessageKey
  media?: { ciphertext: Uint8Array; iv: Uint8Array }
  error?: Boom
}>
message-receipt.update
MessageUserReceiptUpdate[]
Individual user receipts (read, played, etc.)
sock.ev.on('message-receipt.update', (receipts) => {
  for (const { key, receipt } of receipts) {
    console.log(`${receipt.userJid} read at ${receipt.readTimestamp}`)
  }
})

Chat Events

chats.upsert
Chat[]
New chats created
sock.ev.on('chats.upsert', (chats) => {
  console.log(`${chats.length} new chats`)
})
chats.update
ChatUpdate[]
Updates to existing chats (name, unread count, etc.)
sock.ev.on('chats.update', (updates) => {
  for (const update of updates) {
    if (update.unreadCount) {
      console.log(`${update.id}: ${update.unreadCount} unread`)
    }
  }
})
chats.delete
string[]
Array of chat JIDs that were deleted
sock.ev.on('chats.delete', (deletedChats) => {
  console.log('Deleted:', deletedChats)
})
chats.lock
object
Chat lock status changed
{ id: string; locked: boolean }

History Sync Events

messaging-history.set
object
Bulk history sync from phone (reverse chronological order)
sock.ev.on('messaging-history.set', (history) => {
  console.log(`Synced ${history.chats.length} chats`)
  console.log(`Synced ${history.messages.length} messages`)
  console.log(`Progress: ${history.progress * 100}%`)
})

Contact Events

contacts.upsert
Contact[]
New contacts added
contacts.update
Partial<Contact>[]
Updates to existing contacts

Group Events

groups.upsert
GroupMetadata[]
New groups joined
groups.update
Partial<GroupMetadata>[]
Updates to group metadata (name, subject, etc.)
group-participants.update
object
Participant changes in a group
sock.ev.on('group-participants.update', (update) => {
  console.log(`${update.action} in ${update.id}`)
  console.log('Participants:', update.participants)
})
group.join-request
object
Someone requested to join a group
group.member-tag.update
object
Labels assigned to group member changed
{
  groupId: string
  participant: string
  participantAlt?: string
  label: string
  messageTimestamp?: number
}

Presence Events

presence.update
object
Contact presence changed (typing, online, etc.)
{
  id: string // chat JID
  presences: { 
    [participant: string]: PresenceData 
  }
}
Example:
sock.ev.on('presence.update', ({ id, presences }) => {
  for (const [jid, presence] of Object.entries(presences)) {
    console.log(`${jid} is ${presence.lastKnownPresence}`)
    // 'unavailable', 'available', 'composing', 'recording', 'paused'
  }
})

Blocklist Events

blocklist.set
object
Entire blocklist replaced
{ blocklist: string[] }
blocklist.update
object
Blocklist updated incrementally
{
  blocklist: string[]
  type: 'add' | 'remove'
}

Call Events

call
WACallEvent[]
Incoming/outgoing call events
sock.ev.on('call', (calls) => {
  for (const call of calls) {
    console.log(`Call from ${call.from}: ${call.status}`)
  }
})

Label Events

labels.edit
Label
Label created or edited
labels.association
object
Label associated/disassociated with item
{
  association: LabelAssociation
  type: 'add' | 'remove'
}

Newsletter Events

newsletter.reaction
object
Reaction on newsletter message
{
  id: string
  server_id: string
  reaction: { 
    code?: string
    count?: number
    removed?: boolean 
  }
}
newsletter.view
object
Newsletter message viewed
{
  id: string
  server_id: string
  count: number
}
newsletter-participants.update
object
Newsletter participant role changed
{
  id: string
  author: string
  user: string
  new_role: string
  action: string
}
newsletter-settings.update
object
Newsletter settings changed
{
  id: string
  update: any
}

Settings Events

settings.update
union
Account settings changed. Union of:
| { setting: 'unarchiveChats'; value: boolean }
| { setting: 'locale'; value: string }
| { setting: 'disableLinkPreviews'; value: proto.SyncActionValue.IPrivacySettingDisableLinkPreviewsAction }
| { setting: 'timeFormat'; value: proto.SyncActionValue.ITimeFormatAction }
| { setting: 'privacySettingRelayAllCalls'; value: proto.SyncActionValue.IPrivacySettingRelayAllCalls }
| { setting: 'statusPrivacy'; value: proto.SyncActionValue.IStatusPrivacyAction }
| { setting: 'notificationActivitySetting'; value: proto.SyncActionValue.NotificationActivitySettingAction.NotificationActivitySetting }
| { setting: 'channelsPersonalisedRecommendation'; value: proto.SyncActionValue.IPrivacySettingChannelsPersonalisedRecommendationAction }
lid-mapping.update
LIDMapping
LID to phone number mapping updated
{
  pn: string // phone number
  lid: string // LID
}

BufferedEventData

Internal type used for buffering events before emission:
type BufferedEventData = {
  historySets: { ... }
  chatUpserts: { [jid: string]: Chat }
  chatUpdates: { [jid: string]: ChatUpdate }
  chatDeletes: Set<string>
  contactUpserts: { [jid: string]: Contact }
  contactUpdates: { [jid: string]: Partial<Contact> }
  messageUpserts: { [key: string]: { type: MessageUpsertType; message: WAMessage } }
  messageUpdates: { [key: string]: WAMessageUpdate }
  messageDeletes: { [key: string]: WAMessageKey }
  messageReactions: { [key: string]: { key: WAMessageKey; reactions: proto.IReaction[] } }
  messageReceipts: { [key: string]: { key: WAMessageKey; userReceipt: proto.IUserReceipt[] } }
  groupUpdates: { [jid: string]: Partial<GroupMetadata> }
}

Example: Complete Event Handler

import makeWASocket from '@whiskeysockets/baileys'

const sock = makeWASocket({ /* config */ })

// Connection
sock.ev.on('connection.update', (update) => {
  console.log('Connection:', update.connection)
})

// Credentials
sock.ev.on('creds.update', saveCreds)

// Messages
sock.ev.on('messages.upsert', async ({ messages, type }) => {
  for (const msg of messages) {
    if (type === 'notify' && !msg.key.fromMe) {
      await handleIncomingMessage(msg)
    }
  }
})

// Message updates
sock.ev.on('messages.update', (updates) => {
  for (const { key, update } of updates) {
    if (update.status) {
      console.log(`Message ${key.id} status: ${update.status}`)
    }
  }
})

// Presence
sock.ev.on('presence.update', ({ id, presences }) => {
  for (const [jid, presence] of Object.entries(presences)) {
    if (presence.lastKnownPresence === 'composing') {
      console.log(`${jid} is typing in ${id}`)
    }
  }
})

// Groups
sock.ev.on('group-participants.update', (update) => {
  console.log(`${update.action} in ${update.id}:`, update.participants)
})

Build docs developers (and LLMs) love