Getting Started
From an empty folder to a Chat SDK bot answering on WhatsApp.
Install
npm i chat-adapter-zaileys zaileys chat @chat-adapter/state-memoryFor durable message history, add the store backend you want (optional — memory is the zero-config default):
npm i better-sqlite3Create the bot
import { Chat } from 'chat'
import { createMemoryState } from '@chat-adapter/state-memory'
import { createZaileysAdapter } from 'chat-adapter-zaileys'
const whatsapp = createZaileysAdapter({
session: { sessionId: 'main' },
})
const bot = new Chat({
userName: 'mybot',
adapters: { whatsapp },
state: createMemoryState(),
})
bot.onNewMention(async (thread, message) => {
await thread.subscribe()
await thread.post(`Hello, ${message.author.fullName}!`)
})
bot.onSubscribedMessage(async (thread, message) => {
await thread.post(`You said: ${message.text}`)
})
await bot.initialize()
await whatsapp.connect()Register all handlers before calling whatsapp.connect() — messages that arrive before initialization are lost.
Authenticate
QR code
On first run a QR code prints to the terminal. Scan it via WhatsApp → Linked Devices → Link a device. The session persists under ./.zaileys/auth/<sessionId> and is reused on restart.
Reconnection with backoff, session reuse, and logout handling are all managed by Zaileys — there is nothing to wire.
Bring your own Zaileys client
The session shorthand covers most cases, but you can construct the Zaileys Client yourself for full control — storage adapters, plugins, citation, ignore-self, anything from Zaileys configuration :
import { Client, SqliteAuthStore, SqliteMessageStore } from 'zaileys'
import { createZaileysAdapter } from 'chat-adapter-zaileys'
const client = new Client({
sessionId: 'main',
auth: new SqliteAuthStore({ database: './auth.db' }),
store: new SqliteMessageStore({ database: './wa.db' }), // durable history for fetchMessages
})
const whatsapp = createZaileysAdapter({ client })Pass either client or session — never both. The factory throws a ValidationError if you do.
Lifecycle
| Method | What it does |
|---|---|
adapter.connect() | Opens the WhatsApp WebSocket (delegates to client.connect()) |
adapter.disconnect() | Cleanly closes the connection; also called by chat.shutdown() |
adapter.handleWebhook() | Always returns HTTP 501 — WhatsApp uses a persistent socket, not webhooks |
Next steps
- Configuration — every adapter option
- Events & Handlers — what fires where
- Cards & Buttons — interactive messages