Skip to main content

What is a Provider?

A provider is an adapter that connects BuilderBot to a specific messaging platform (WhatsApp, Telegram, Instagram, Meta, etc.). The provider handles platform-specific communication, message sending, media handling, and event management.

Provider Class Overview

All providers extend the abstract ProviderClass, which defines a standard interface:
abstract class ProviderClass<V = any> 
  extends EventEmitterClass<ProviderEventTypes> 
  implements ProviderHttpServer {
  
  public abstract globalVendorArgs: GlobalVendorArgs
  public vendor: Vendor<V>
  public server: Polka
  public idBotName: string = 'bot'
  public idCtxBot: string = 'id-ctx-bot'
}
Key Components:
  • vendor - The underlying messaging platform SDK/API instance
  • server - HTTP server (Polka) for webhooks and API endpoints
  • Event emitter capabilities for message handling
  • Abstract methods that each provider must implement

Creating a Provider

Use the createProvider function to instantiate a provider:
import { createProvider } from '@builderbot/bot'
import { BaileysProvider } from '@builderbot/provider-baileys'

const adapterProvider = createProvider(BaileysProvider)

With Configuration

const adapterProvider = createProvider(MetaProvider, {
  jwtToken: 'your-jwt-token',
  numberId: 'phone-number-id',
  verifyToken: 'verify-token',
  version: 'v21.0'
})

Available Providers

BuilderBot supports multiple messaging platforms:
import { BaileysProvider } from '@builderbot/provider-baileys'

const provider = createProvider(BaileysProvider, {
  name: 'bot-name',
  port: 3008
})
Direct WhatsApp connection using Baileys library.

Provider Lifecycle

Providers follow a specific initialization sequence:
1

Construction

Provider instance is created and HTTP server is built:
constructor() {
  super()
  this.server = this.buildHTTPServer()
}
2

Vendor Initialization

The platform-specific SDK is initialized:
protected abstract initVendor(): Promise<any>
3

Event Registration

Platform events are registered and listeners attached:
protected abstract busEvents(): Array<{
  event: string | number | symbol
  func: Function
}>
4

HTTP Server Start

Webhook endpoints and HTTP server start listening:
beforeHttpServerInit()
start(methods, callback)
afterHttpServerInit()

Abstract Methods

Each provider must implement these core methods:

sendMessage

public abstract sendMessage<K = any>(
  userId: string,
  message: any,
  args?: any
): Promise<K>
Send a message to a user on the platform. Example:
await provider.sendMessage('1234567890', 'Hello!', {
  media: 'https://example.com/image.jpg'
})

saveFile

public abstract saveFile(
  ctx: any,
  options?: { path: string }
): Promise<string>
Download and save media files from messages. Example:
const filePath = await provider.saveFile(ctx, {
  path: './downloads'
})

initVendor

protected abstract initVendor(): Promise<any>
Initialize the platform SDK/API client.

busEvents

protected abstract busEvents(): Array<{
  event: string | number | symbol
  func: Function
}>
Define platform event listeners.

HTTP Server

Every provider includes a built-in HTTP server (Polka) for webhooks and custom endpoints:
public buildHTTPServer(): Polka {
  return polka()
    .use(cors())
    .use(urlencoded({ extended: true }))
    .use(json())
}

Adding Custom Endpoints

const { handleCtx } = await createBot({
  flow: adapterFlow,
  provider: adapterProvider,
  database: adapterDB,
})

// Custom endpoint for sending messages via API
adapterProvider.server.post(
  '/v1/messages',
  handleCtx(async (bot, req, res) => {
    const { number, message, urlMedia } = req.body
    await bot.sendMessage(number, message, { media: urlMedia ?? null })
    return res.end('sent')
  })
)

// Custom endpoint for triggering flows
adapterProvider.server.post(
  '/v1/register',
  handleCtx(async (bot, req, res) => {
    const { number, name } = req.body
    await bot.dispatch('REGISTER_FLOW', { from: number, name })
    return res.end('triggered')
  })
)

Route Discovery

Get all registered routes:
const routes = provider.getListRoutes(provider.server)
console.log(routes)
// Output:
// [
//   '[POST]: http://localhost:3008/v1/messages',
//   '[POST]: http://localhost:3008/v1/register',
//   '[GET]: http://localhost:3008/webhook'
// ]

Event System

Providers emit events that BuilderBot listens to:
type ProviderEventTypes = {
  message: [arg1: BotContext]
  require_action: [arg1: {
    title: string
    instructions: string[]
    payload?: { qr?: string; code?: string; [key: string]: any }
  }]
  notice: [arg1: { title: string; instructions: string[] }]
  ready: any
  auth_failure: any
  host: any
  [key: string]: any
}

Listening to Provider Events

adapterProvider.on('ready', () => {
  console.log('Provider is ready!')
})

adapterProvider.on('message', (ctx) => {
  console.log('Message received:', ctx.body)
})

adapterProvider.on('notice', ({ title, instructions }) => {
  console.log(title)
  instructions.forEach(i => console.log(i))
})

Dispatching Custom Events

Trigger flows programmatically using the dispatch method:
public dispatchInside(payload: {
  body: string
  name: string
  from: string
}) {
  this.emit('message', { ...payload })
}
Example:
adapterProvider.dispatchInside({
  from: '1234567890',
  name: 'John Doe',
  body: setEvent('WELCOME')
})

Context Middleware

The inHandleCtx method provides a safe wrapper for HTTP endpoint handlers:
public inHandleCtx<T extends Pick<ProviderClass<V>, 'sendMessage'> & {
  provider: V
}>(
  ctxPolka: (bot: T, req: Request, res: PolkaRes) => Promise<void>
): (...args: any[]) => any
Features:
  • Automatic error handling
  • Bot context injection
  • Authentication state validation

Starting and Stopping

Start the Server

public start(
  vendor: BotCtxMiddleware,
  cb: (arg?: any) => void = () => null
): void
Called internally by createBot, but can be invoked manually if needed.

Stop the Server

public stop(): Promise<void>
Gracefully shutdown the HTTP server:
await adapterProvider.stop()
console.log('Provider stopped')

Practical Example

Complete bot setup with provider configuration:
import { createBot, createProvider, createFlow, addKeyword } from '@builderbot/bot'
import { BaileysProvider } from '@builderbot/provider-baileys'
import { MemoryDB } from '@builderbot/bot'

const welcomeFlow = addKeyword(['hi', 'hello'])
  .addAnswer('Welcome to our bot!')

const main = async () => {
  const adapterFlow = createFlow([welcomeFlow])
  const adapterProvider = createProvider(BaileysProvider)
  const adapterDB = new MemoryDB()

  const { handleCtx, httpServer } = await createBot({
    flow: adapterFlow,
    provider: adapterProvider,
    database: adapterDB,
  })

  // Custom API endpoint
  adapterProvider.server.post(
    '/v1/send',
    handleCtx(async (bot, req, res) => {
      const { to, message } = req.body
      await bot.sendMessage(to, message)
      res.end('Message sent')
    })
  )

  // Listen on custom events
  adapterProvider.on('ready', () => {
    console.log('Bot is ready!')
  })

  httpServer(3008)
}

main()

Best Practices

Environment Variables: Store sensitive credentials in environment variables, never hardcode them.
Error Handling: Always implement error handling in custom endpoints to prevent crashes.
Port Configuration: Ensure the port number doesn’t conflict with other services. The default is 3008.
Multiple Providers: You can run multiple bots with different providers simultaneously by using different ports.

Build docs developers (and LLMs) love