Skip to content

FAQ ​

Do I need to scan the QR every time? ​

No. The session is saved in ./sessions/. You only scan the QR the first time. If the session is invalidated (you deleted the folder or WhatsApp unlinked the device), you'll need to scan again.

Can I use the bot without scanning QR? ​

Yes, with a pairing code (Baileys transport):

ts
const bot = new Bot({
  provider: new BaileysProvider({
    session: 'my-bot',
    pairingPhoneNumber: '+57300XXXXXXX', // full international format
  }),
})

// v2 emits the auth artifact (QR string / pairing code) through the 'qr' event:
bot.on('qr', (artifact) => console.log('Auth artifact:', artifact))

There is no dedicated pairing_code event in v2 — the pairing code arrives as the qr event payload (a string auth artifact the core forwards verbatim from the provider).

Does the bot work in groups? ​

Yes. when() handlers work in groups by default. To respond only in private:

ts
bot.when('hola', async (ctx) => {
  if (ctx.isGroup) return
  await ctx.reply('👋')
})

In a group, each participant gets an independent conversation by default when they trigger a flow — two people talking to the bot in the same group don't share state. Set conversationScope: 'chat' if you want one shared conversation per group instead.

Why doesn't bot.when('hi') match "hi there"? ​

The default match strategy is normalized equals, not "contains" — the message must equal the trigger exactly after lowercasing, stripping accents and collapsing spaces. For substring matching, use a TriggerObject:

ts
bot.when({ pattern: 'hi', match: 'contains' }, handler)

match also accepts 'startsWith' and 'endsWith'.

Can I send buttons? ​

It depends on the transport. With the official Cloud API (@botmesh/meta) and Telegram, ctx.buttons(text, buttons) sends native buttons (see Messages & media). On Baileys, no — native interactive buttons/lists are dead in the current WhatsApp Web protocol. Use a numbered menu (.choose() in a flow, c.choose() in a conversation) or a real poll:

ts
await ctx.poll('Confirm your order?', ['Yes', 'No'])

Do flows/conversations survive a restart? ​

Only if you opt in. flow(...).persistent() checkpoints the conversation after each step, but the default MemoryStore lives in memory — a restart loses those checkpoints unless the store is file-backed:

ts
const bot = new Bot({
  provider: new BaileysProvider({ session: 'my-bot' }),
  store: new MemoryStore({ file: './store.json' }), // or use @botmesh/sqlite-store
})

Can I send messages without someone writing first? ​

Yes, with bot.send:

ts
bot.schedule('0 9 * * *', async () => {
  await bot.send('57300XXXXXXX@s.whatsapp.net', '🌅 Good morning!')
})

To send one message to many chats use bot.broadcast() (batches, retries on rate limits, cancellable); to start a whole flow for someone use bot.trigger(). On the WhatsApp Cloud API, free-form messages only go out inside the 24-hour window: see Session window.

How do I stop the bot properly? ​

ts
process.on('SIGINT', async () => {
  console.log('🛑 Shutting down...')
  await bot.stop({ drain: true }) // wait for in-flight and paced replies (up to `timeout`, 10 s by default)
  process.exit(0)
})

Can I have multiple bots in the same process? ​

Yes, with different providers/sessions:

ts
const bot1 = new Bot({ provider: new BaileysProvider({ session: 'bot-1' }) })
const bot2 = new Bot({ provider: new BaileysProvider({ session: 'bot-2' }) })
await bot1.start()
await bot2.start()

You can even mix transports — one Bot per provider (e.g. a Baileys bot and a CloudAPIProvider bot in the same process).

Does it work with WhatsApp Business? ​

Yes. The bot works with both personal and WhatsApp Business accounts.

Can I build a ChatGPT-style AI assistant on WhatsApp? ​

Not on the WhatsApp Business Platform. Since 2026-01-15 Meta's terms prohibit general-purpose AI assistants (open-ended chatbots whose main purpose is the AI itself). AI that serves your business — customer support, sales, bookings — is allowed. With @botmesh/ai, write a persona scoped to your business; see the AI plugin guide.

Can my account get banned? ​

WhatsApp can detect excessive automation. To minimize risk:

  • Don't send spam or mass messages
  • Use markOnlineOnConnect: false (a BaileysProvider option)
  • Respect rate limits (the provider's built-in limiter)
  • Don't reply instantly to everything (turn on the typing indicator with BotConfig.typing)
  • Consider the official Cloud API (@botmesh/meta) for business-critical bots — no ban risk

Do I need TypeScript? ​

No. All examples work in plain JavaScript — just note the package is ESM-only, so your project needs "type": "module" in package.json (or a .mjs file) regardless of whether you use TypeScript. TypeScript gives you autocomplete and type-checking, but it's optional.

Why do I get ERR_REQUIRE_ESM or "require is not defined"? ​

You're trying to require('@botmesh/core') (or a transport package) from a CommonJS file. There is no CJS build — switch to import (add "type": "module" to your package.json, or use a .mjs extension). Node >= 22.12 can also require() an ESM package via its experimental require(esm) support.

Where is the full API reference? ​

At the API Reference — generated with TypeDoc from the source code. It covers @botmesh/core (every public export, including the internals-free /internal split); the channel, store and plugin packages are documented in their guide pages and in each package's README.md (packages/<pkg>/README.md).

Still having problems? ​

Released under the MIT License.