Skip to main content
Baileys uses the EventEmitter pattern to notify you about incoming messages, connection changes, and credential updates. You listen to these events to build your bot’s functionality.

Key Events

You can find all available events in the BaileysEventMap type definition.

messages.upsert

Fired when new messages arrive or are sent from another device.
sock.ev.on('messages.upsert', ({ messages, type }) => {
  console.log('got messages', messages)
  
  for (const msg of messages) {
    if (!msg.message) continue
    
    const text = msg.message.conversation || msg.message.extendedTextMessage?.text
    console.log('Message text:', text)
    
    // Reply to the message
    if (!msg.key.fromMe) {
      await sock.sendMessage(msg.key.remoteJid!, { text: 'Hello!' })
    }
  }
})
The type field indicates whether this is a 'notify' (new message) or 'append' (history sync) event.

connection.update

Handles connection state changes, QR code generation, and disconnections.
sock.ev.on('connection.update', (update) => {
  const { connection, lastDisconnect, qr } = update
  
  if (connection === 'close') {
    const shouldReconnect = (lastDisconnect.error as Boom)?.output?.statusCode !== DisconnectReason.loggedOut
    console.log('connection closed due to', lastDisconnect.error, ', reconnecting', shouldReconnect)
    
    if (shouldReconnect) {
      connectToWhatsApp()
    }
  } else if (connection === 'open') {
    console.log('opened connection')
  }
  
  if (qr) {
    console.log('QR Code:', qr)
  }
})
Always check the disconnect reason before reconnecting. If the status code is DisconnectReason.loggedOut, do not reconnect automatically.

creds.update

Fired when authentication credentials are updated. You must save these credentials to maintain your session.
import makeWASocket, { useMultiFileAuthState } from '@whiskeysockets/baileys'

const { state, saveCreds } = await useMultiFileAuthState('auth_info_baileys')

const sock = makeWASocket({ auth: state })

sock.ev.on('creds.update', saveCreds)
Credentials update whenever signal sessions change (on send/receive). Not saving them will cause message delivery failures.

Processing Events Efficiently

You can use sock.ev.process() to batch-process multiple events at once:
sock.ev.process(async (events) => {
  if (events['connection.update']) {
    const update = events['connection.update']
    console.log('connection update', update)
  }
  
  if (events['creds.update']) {
    await saveCreds()
  }
  
  if (events['messages.upsert']) {
    const { messages } = events['messages.upsert']
    for (const msg of messages) {
      console.log('new message', msg)
    }
  }
})

Other Common Events

messages.update

Fired when messages are edited, deleted, or status changes (delivered, read).
sock.ev.on('messages.update', (updates) => {
  for (const { key, update } of updates) {
    console.log('message updated:', key.id, update)
  }
})

chats.update

Fired when chat metadata changes (unread count, last message timestamp).
sock.ev.on('chats.update', (updates) => {
  console.log('chats updated', updates)
})

contacts.update

Fired when contact information changes (profile picture, name).
sock.ev.on('contacts.update', async (updates) => {
  for (const contact of updates) {
    if (typeof contact.imgUrl !== 'undefined') {
      const newUrl = contact.imgUrl === null
        ? null
        : await sock.profilePictureUrl(contact.id!).catch(() => null)
      console.log('contact has a new profile pic:', newUrl)
    }
  }
})

presence.update

Fired when a contact’s presence changes (online, typing, recording).
sock.ev.on('presence.update', (update) => {
  console.log('presence update:', update)
})

// Subscribe to presence updates for a specific chat
await sock.presenceSubscribe(jid)

Complete Example

1

Set up authentication

import makeWASocket, { DisconnectReason, useMultiFileAuthState } from '@whiskeysockets/baileys'
import { Boom } from '@hapi/boom'

const { state, saveCreds } = await useMultiFileAuthState('auth_info_baileys')
2

Create the socket

const sock = makeWASocket({
  auth: state
})
3

Handle events

sock.ev.on('connection.update', (update) => {
  const { connection, lastDisconnect } = update
  if (connection === 'close') {
    const shouldReconnect = (lastDisconnect.error as Boom)?.output?.statusCode !== DisconnectReason.loggedOut
    if (shouldReconnect) {
      connectToWhatsApp()
    }
  } else if (connection === 'open') {
    console.log('opened connection')
  }
})

sock.ev.on('messages.upsert', async ({ messages }) => {
  for (const msg of messages) {
    console.log('received message:', msg)
    
    if (!msg.key.fromMe && msg.message) {
      await sock.sendMessage(msg.key.remoteJid!, { text: 'Hello!' })
    }
  }
})

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

Build docs developers (and LLMs) love