How to implement a REST API?

In many occasions we need to send a message via HTTP request is very useful to send reminders or order confirmations. In this case each provider implements a handleCtx function which allows you to inject the bot instantiation and access its functions from a controller.


Send Single Message

Request

POST
/v1/messages
curl https://api.example.chat/v1/messages \
  -d number="34000000" \
  -d message="Hello!"

In the exercise below you can get an example of how it works. It is interesting to understand that internally the library already implements a very light version of HTTP similar to express but called polka.

app.ts

import 'dotenv/config'
import { createBot, MemoryDB, createProvider } from '@builderbot/bot'
import { BaileysProvider } from '@builderbot/provider-baileys'
import flow from './flows';

const PORT = process.env.PORT ?? 3001

const main = async () => {
    const provider = createProvider(BaileysProvider)

    const { handleCtx, httpServer } = await createBot({
        database: new MemoryDB(),
        provider,
        flow,
    })

    httpServer(+PORT)

    provider.server.post('/v1/messages', handleCtx(async (bot, req, res) => {
        const { number, message } = req.body
        await bot.sendMessage(number, message, {})
        return res.end('send')
    }))
}

main()

Send with Media

Request

POST
/v1/messages
curl https://api.example.chat/v1/messages \
  -d number="34000000" \
  -d message="Ey! send media"

In the following example you will understand how to send files, images or videos from an api when the file is in a public URL or also if you want to upload it through a request.

import 'dotenv/config'
import { createBot, MemoryDB, createProvider } from '@builderbot/bot'
import { BaileysProvider } from '@builderbot/provider-baileys'
import flow from './flows';

const PORT = process.env.PORT ?? 3001

const main = async () => {
    const provider = createProvider(BaileysProvider)

    const { handleCtx, httpServer } = await createBot({
        database: new MemoryDB(),
        provider,
        flow,
    })

    httpServer(+PORT)

    provider.server.post('/v1/messages', handleCtx(async (bot, req, res) => {
        const { number, message, media } = req.body
        await bot.sendMessage(number, message, { media }) // https://i.imgur.com/0HpzsEm.png
        return res.end('send')
    }))
}

main()

Block Users

Request

POST
/v1/blacklist
curl https://api.example.chat/v1/blacklist \
  -d number="34000000" \
  -d intent="'add' or 'remove'"

In the following example you will understand how to add numbers to a blacklist to prevent the bot from answering those numbers, very useful when we want to talk to a person without the bot answering.

blacklist-api.ts

import { createBot, MemoryDB, createProvider } from '@builderbot/bot'
import { BaileysProvider } from '@builderbot/provider-baileys'
import flow from './flows';

const PORT = process.env.PORT ?? 3001

const main = async () => {
    const provider = createProvider(BaileysProvider)

    const { handleCtx, httpServer } = await createBot({
        database: new MemoryDB(),
        provider,
        flow,
    })

    httpServer(+PORT)

    provider.server.post('/v1/blacklist', handleCtx(async (bot, req, res) => {
        const { number, intent } = req.body
        if (intent === 'remove') bot.blacklist.remove(`340000000`)
        if (intent === 'add') bot.blacklist.add(`340000000`)

        res.writeHead(200, { 'Content-Type': 'application/json' })
        return res.end(JSON.stringify({ status: 'ok', number, intent }))
    }))
}

main()

Trigger Flows

Request

POST
/v1/register
curl https://api.example.chat/v1/register \
  -d number="34000000" \
  -d name ="Joe"

In the following example you will understand how to start a flow to a given number from an API request, it is a new experimental function that may undergo changes in the future.

trigger-flow-api.ts

import { createBot, MemoryDB, createProvider } from '@builderbot/bot'
import { BaileysProvider } from '@builderbot/provider-baileys'

const PORT = process.env.PORT ?? 3001

const registerFlow = addKeyword(utils.setEvent('EVENT_REGISTER'))
    .addAnswer(`What is your name?`, { capture: true }, async (ctx, { state }) => {
        await state.update({ name: ctx.body })
    })
    .addAnswer('What is your age?', { capture: true }, async (ctx, { state }) => {
        await state.update({ age: ctx.body })
    })
    .addAction(async (_, { flowDynamic, state }) => {
        await flowDynamic(`${state.get('name')}, thanks for your information!: Your age: ${state.get('age')}`)
    })

const main = async () => {
    const provider = createProvider(BaileysProvider)

    const { handleCtx, httpServer } = await createBot({
        database: new MemoryDB(),
        provider,
        flow: createFlow([registerFlow]),
    })

    httpServer(+PORT)

    provider.server.post('/v1/register', handleCtx(async (bot, req, res) => {
        const { number, name } = req.body
        await bot.dispatch('EVENT_REGISTER', { from: number, name })
        return res.end('trigger')
    }))
}

main()

Guides

My first chatbot

Learn how build your first chatbot in few minutes

Read more

Concepts

Understand the essential concepts for building bots

Read more

Add Functions

The key to learning how to write flows is add-functions.

Read more

Plugins

Unlimitate and start implementing the community plugins.

Read more

Resources

Modularize

Learn how to modularise flows so that you can have a more maintainable bot.

Send Message

How to send a message via HTTP to start conversations, you can send multimedia as well.

Dockerizer

A good practice is to dockerise your bots to make them more maintainable and effective.

Events

Learning about events will make us more fluent when creating chatbots.