Skip to Content
Events & Handlers

Events & Handlers

The adapter wires Zaileys events into the standard Chat SDK handlers. Whatever has a native SDK concept arrives there; everything else stays reachable — fully typed — through adapter.client.on(…).

Wired to Chat SDK handlers

Zaileys eventChat SDK handlerNotes
message (all types)onNewMention / onSubscribedMessage / onDirectMessageFull MessageContext attached as message.raw.context. Stories and newsletters are skipped.
reactiononReactionadded reflects add vs. remove; emoji normalized to an EmojiValue.
button-clickonActionNative button taps — see Cards & Buttons.
list-selectonActionList row selections use the same action decoding.
poll-voteonPollVote (adapter) + message handlersDecrypted natively — see Polls.
group-joinonMemberJoinedChannelOne event per joined participant, with inviterId when known.
prefixed message (/cmd)onSlashCommandOpt-in via slashCommands: true.
bot.onReaction('🔥', async (event) => { await event.thread.post(`${event.user.userName} reacted with fire!`) }) bot.onMemberJoinedChannel(async (event) => { const thread = await bot.getThread(event.channelId) await thread.post(`Welcome <@${event.userId}>!`) })

Slash commands

With slashCommands: true, messages starting with a Zaileys command prefix are routed to onSlashCommand instead of message handlers — mirroring how Slack separates slash commands from messages:

const whatsapp = createZaileysAdapter({ session: { sessionId: 'main', commandPrefix: ['/', '!'] }, slashCommands: true, }) bot.onSlashCommand('/deploy', async (event) => { await event.channel.post(`Deploying ${event.text}…`) // "/deploy prod" → text = "prod" })

The command is normalized to /name regardless of which prefix triggered it.

Message-author semantics

  • author.isMetrue for messages sent by the paired account (fromMe) or tracked as sent by this adapter instance.
  • author.isBottrue for adapter-sent messages, otherwise Zaileys’ bot detection (ctx.isBot).
  • message.isMention — set when the bot is @-tagged (ctx.isTagMe), in addition to the SDK’s own username matching.

Everything else: typed passthrough

Zaileys emits 20+ event types. Those without a Chat SDK equivalent — calls, presence, group updates, edits, deletions, history sync — are one line away, fully typed:

whatsapp.client.on('call-incoming', (call) => console.log('incoming call from', call.from)) whatsapp.client.on('group-update', (u) => console.log('group changed:', u.update)) whatsapp.client.on('delete', (d) => console.log('message deleted:', d.key.id)) whatsapp.client.on('presence', (p) => console.log(p))

See Zaileys → Events for every event and payload shape.

Concurrency & locking

The adapter declares lockScope: 'channel' — WhatsApp conversations are flat, so all messages in a chat contend for the same lock. Combine with the SDK’s concurrency strategies (queue, debounce, burst) as usual; media attachments survive serialization thanks to rehydrateAttachment.