Events & Messages

Convenience methods

client.on_qr        { |qr_string| ... }  # QR code data string
client.on_message   { |msg| ... }        # Live messages only (Whatsapp::Message)
client.on_connected { ... }              # Successfully connected

Message status callbacks

Track delivery status of sent messages:

# All status changes
client.on_message_status do |data|
  puts "#{data[:id]}#{data[:status]}"
  # data = { id:, to:, from_me:, status:, status_code: }
end

# Specific statuses
client.on_message_sent      { |data| puts "Sent: #{data[:id]}" }
client.on_message_delivered { |data| puts "Delivered: #{data[:id]}" }
client.on_message_read      { |data| puts "Read: #{data[:id]}" }

Status values: pending, sent, delivered, read, played, error.

Presence updates

# Subscribe to a contact's presence
client.subscribe_presence("+33612345678")

# React to presence changes
client.on_presence_update do |data|
  # data = { id: "33612345678@s.whatsapp.net", presences: { ... } }
  puts data
end

Read receipts

# Mark messages as read (send blue ticks)
client.read_messages([
  { remote_jid: "33612345678@s.whatsapp.net", id: "msg123" }
])

# React to read receipts from contacts
client.on_message_receipt do |data|
  puts data
end

Poll votes

Poll votes are encrypted by WhatsApp. The bridge automatically decrypts them using Baileys’ getAggregateVotesInPollMessage and emits a high-level poll.vote event.

client.on_poll_vote do |data|
  data[:poll_message_id]  # ID of the poll message
  data[:remote_jid]       # JID of the chat
  data[:votes]            # [{ name: "Option A", voters: ["jid1", ...] }, ...]
end

Low-level events

client.on('qr')              { |data| ... }  # QR code for authentication
client.on('connected')       { |data| ... }  # Connected
client.on('disconnected')    { |data| ... }  # Connection lost
client.on('message.new')     { |msg|  ... }  # Live incoming (same as on_message)
client.on('message')         { |msg|  ... }  # All messages (live + history sync)
client.on('message.status')  { |data| ... }  # Message delivery status update
client.on('health.ok')       { |data| ... }  # Heartbeat success
client.on('health.failure')  { |data| ... }  # Heartbeat failure
client.on('health.recovered'){ |data| ... }
client.on('presence.update')            { |data| ... }  # Presence change
client.on('message-receipt.update')     { |data| ... }  # Read receipt
client.on('poll.vote')                  { |data| ... }  # Poll vote results

History sync vs live messages

On first connection, Baileys syncs your message history. on_message filters these out and only delivers real-time messages. Use on_message_any if you need the full history.

client.on_message_any { |msg| ... }  # All messages including history sync

Message object

client.on_message do |msg|
  msg.id                # Message ID
  msg.from              # Sender JID ("33612345678@s.whatsapp.net")
  msg.text              # Text content
  msg.timestamp         # Time object
  msg.type              # :text, :image, :video, :audio, :document, :sticker, :location, :contact
  msg.from_me?          # Sent by you?
  msg.group?            # From a group chat?
  msg.media?            # Contains media? (image, video, audio, document, sticker)
  msg.location?         # Location message?
  msg.contact?          # Contact card?
  msg.reply?            # Reply to another message?
  msg.caption           # Media caption
  msg.location          # { latitude:, longitude:, name:, address: }
  msg.contact_info      # { display_name:, vcard: }
  msg.quoted_message_id # ID of the quoted message
  msg.raw               # Full raw data hash from Baileys
end

Error handling

begin
  client.send_message(to: "+33...", text: "hello")
rescue Whatsapp::RateLimited => e
  # Rate limit exceeded — wait and retry
rescue Whatsapp::NotConnected
  # WhatsApp not connected — scan QR or reconnect
rescue Whatsapp::BridgeNotRunning
  # Node bridge process is not running
rescue Whatsapp::BridgeTimeout
  # Bridge failed to start within timeout
rescue Whatsapp::BridgeError => e
  # Bridge HTTP error (e.status_code, e.body)
rescue Whatsapp::NodeNotFound
  # Node.js not found on the system
rescue Whatsapp::MessageFailed => e
  # Delivery failed (e.to, e.reason)
end