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