← projects

WhatsApp Internal API — multi-session Baileys

WhatsApp OTP & notifications without Chromium, via an npm SDK

BaileysExpressBullMQSocket.IODrizzle ORMRedisSDK npm

The need

An internal WhatsApp channel — light and reusable — to send OTPs and notifications without paying for the official APIs or going through their review. One building block that every product (Mon Bara, TransitSoft) consumes through an SDK.

Baileys, without Chromium

No WhatsApp Web inside a headless Chromium (heavy, fragile, RAM-hungry). Baileys speaks the WhatsApp protocol directly over a WebSocket. The result: it runs on a small VPS.

  • Server — Express + Socket.IO + Baileys + BullMQ
  • Dashboard — Next.js: create a session, scan the QR code, generate the keys
  • packages/shared — types + Zod schemas + socket events (the source of truth)
  • packages/sdk — the @wa/sdk npm client

Multiple sessions & keys

Each session is one WhatsApp number, created by QR code from the dashboard, with an API key shown exactly once. The consuming project never sees Baileys: just a baseUrl and a key.

Rate limiting is survival

WhatsApp is quick to ban a number that spams. Everything sent goes through a rate-limited BullMQ queue (15 messages/min, configurable), with retry backoff and controlled concurrency. Live statuses over Socket.IO:

queued → sending → sent → delivered → read | failed

Stack

Baileys · Express · BullMQ · Socket.IO · Drizzle ORM · Redis · npm SDK


Full write-up: An internal WhatsApp API with Baileys (no Chromium).