Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

@builderbot/plugin-chatwoot

Package Overview
Dependencies
Maintainers
1
Versions
13
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@builderbot/plugin-chatwoot

Plugin de Chatwoot para BuilderBot - Crea inbox, guarda contactos y sincroniza conversaciones automáticamente

latest
Source
npmnpm
Version
1.3.15-alpha.21
Version published
Maintainers
1
Created
Source

@builderbot/plugin-chatwoot

Syncs every WhatsApp conversation to Chatwoot automatically.
Agents can reply directly from Chatwoot and their messages are forwarded to WhatsApp in real time.

What it does

FeatureDetails
Inbox auto-creationCreates an API-channel inbox on first run and reuses it on subsequent starts
Contact syncFinds or creates the Chatwoot contact for every phone number
Conversation syncFinds or creates the open conversation and caches it in memory
Media attachmentsImages, audio, video and documents are sent as attachments in both directions
Media-only messagesWhatsApp media-only messages (no caption) are synced with a readable label ([image], [audio], [file], …)
Multiple attachmentsWhen an agent sends several files from Chatwoot, each one is forwarded to WhatsApp
Bidirectional messagesBot outgoing messages → Chatwoot (outgoing) · User messages → Chatwoot (incoming)
Agent repliesChatwoot agent messages → WhatsApp via webhook
Blacklist integrationWhen an agent takes a conversation, the user is added to the bot blacklist so the bot stops responding
Webhook auto-registrationRegisters the webhook URL in Chatwoot and the HTTP route on the provider server automatically
Group message filter@g.us group messages are silently ignored
Startup validationCredentials are verified before anything runs; the plugin self-disables on failure
Serialized API callsAn internal queue ensures no race conditions against the Chatwoot API

Installation

pnpm add @builderbot/plugin-chatwoot

Quick start

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

const chatwoot = createChatwootPlugin({
    token: 'YOUR_CHATWOOT_USER_TOKEN',
    url: 'https://app.chatwoot.com',
    accountId: 1,
    // Optional but recommended: enables agent → WhatsApp replies
    webhookUrl: 'https://your-bot.example.com/v1/chatwoot',
})

const bot = await createBot({
    flow: createFlow([...]),
    provider: createProvider(BaileysProvider),
    database: new MemoryDB(),
})

// One call wires everything up — including the webhook HTTP route
await chatwoot.attach(bot)

That's it. Every message exchanged through your bot is now mirrored in Chatwoot, and agent replies are forwarded back to WhatsApp automatically.

Configuration

const chatwoot = createChatwootPlugin({
    /** User or Agent API access token from Chatwoot → Profile → Access Token */
    token: 'xxxxxxxxxxxxxxxxxxxxxxxx',

    /** Base URL of your Chatwoot instance */
    url: 'https://app.chatwoot.com',

    /** Numeric account ID visible in the Chatwoot URL */
    accountId: 1,

    /** Optional: custom inbox name (default: 'BuilderBot Inbox') */
    inboxName: 'WhatsApp Bot',

    /**
     * Optional: public URL where Chatwoot will POST webhook events.
     * When provided, the plugin registers (or reuses) the webhook on startup.
     * Required for agent replies to reach WhatsApp.
     */
    webhookUrl: 'https://your-bot.example.com/v1/chatwoot',
})

How to get your token

  • Open Chatwoot → click your avatar (bottom-left) → Profile Settings
  • Scroll down to Access Token and copy it

How to find your accountId

It is the number in the URL after /app/accounts/:

https://app.chatwoot.com/app/accounts/42/conversations
                                       ↑
                                   accountId = 42

Receiving agent replies (webhook)

When a Chatwoot agent sends a message, Chatwoot fires a webhook to your bot. As long as you set webhookUrl in the config, attach() handles everything automatically — it registers the webhook in Chatwoot and wires the HTTP route on the provider's server.

import { createBot, createFlow, addKeyword } from '@builderbot/bot'
import { BaileysProvider } from '@builderbot/provider-baileys'
import { createChatwootPlugin } from '@builderbot/plugin-chatwoot'

const chatwoot = createChatwootPlugin({
    token: 'YOUR_TOKEN',
    url: 'https://app.chatwoot.com',
    accountId: 1,
    webhookUrl: 'https://your-bot.example.com/v1/chatwoot',
})

const bot = await createBot({
    flow: createFlow([...]),
    provider: createProvider(BaileysProvider, { name: 'bot' }),
    database: new MemoryDB(),
})

// Registers the Chatwoot account webhook AND the /v1/chatwoot HTTP route automatically
await chatwoot.attach(bot)

Note: The URL you pass as webhookUrl must be reachable by your Chatwoot server.
For local development use ngrok or a similar tunnel.

Advanced: manual route registration

If you use a custom HTTP server outside of BuilderBot's provider, you can still call handleWebhook directly:

myServer.post('/v1/chatwoot', async (req, res) => {
    await chatwoot.handleWebhook(bot, req.body)
    res.end(JSON.stringify({ status: 'ok' }))
})

What handleWebhook handles

Chatwoot eventPlugin action
conversation_updated — agent assignedAdds the user's phone to the bot blacklist (bot stops responding)
conversation_updated — agent unassignedRemoves the phone from the blacklist (bot resumes)
message_created — outgoing on API channelForwards the agent's message (text + optional media) to WhatsApp
message_created — private noteIgnored — private notes are not forwarded
Event for a different inboxIgnored — only events for the plugin's inbox are processed

How agent takeover works

Agent assigned to conversation
          │
          ▼
  phone added to blacklist ──► bot stops responding to that user
          │
  Agent types in Chatwoot
          │
          ▼
  handleWebhook receives message_created
          │
          ▼
  Message forwarded to WhatsApp

Agent unassigns from conversation
          │
          ▼
  phone removed from blacklist ──► bot resumes normally

Advanced usage

Accessing the Chatwoot API directly

const api = chatwoot.getApi()

// Create a contact manually
const contact = await api.findOrCreateContact('+5215511223344', 'John Doe')

// Send a message to an existing conversation
await api.sendMessage(conversationId, 'Hello from the API!', 'outgoing')

// Send a message with a media attachment
await api.sendMessage(conversationId, 'See attached', 'outgoing', 'https://example.com/image.png')
// Or from a local file:
await api.sendMessage(conversationId, 'See attached', 'outgoing', '/tmp/photo.jpg')

Inspecting the active inbox

const inbox = chatwoot.getInbox()
console.log(inbox?.id, inbox?.name)

Checking plugin health

if (!chatwoot.status) {
    console.warn('Chatwoot plugin is disabled — check your credentials')
}

Store sensitive values in a .env file instead of hardcoding them:

CHATWOOT_TOKEN=your-access-token
CHATWOOT_URL=https://app.chatwoot.com
CHATWOOT_ACCOUNT_ID=1
CHATWOOT_WEBHOOK_URL=https://your-bot.example.com/v1/chatwoot
const chatwoot = createChatwootPlugin({
    token: process.env.CHATWOOT_TOKEN!,
    url: process.env.CHATWOOT_URL!,
    accountId: Number(process.env.CHATWOOT_ACCOUNT_ID),
    webhookUrl: process.env.CHATWOOT_WEBHOOK_URL,
})

Supported media types

The plugin handles media in both directions.

WhatsApp → Chatwoot

When an incoming WhatsApp message carries media, the file is attached to the Chatwoot message. The plugin resolves the media source through two strategies, tried in order:

  • options.media URL — used when the provider already exposes a public media URL in payload.options.media.
  • provider.saveFile fallback — used when the provider carries the raw message context (e.g. Baileys) but does not populate options.media. The plugin calls bot.provider.saveFile(payload) to download the file to a temporary path, uploads it to Chatwoot, then cleans up the temp file automatically. If the download fails the message is still forwarded with the readable label as caption.

If the message body is a provider event string, it is also converted to a human-readable caption that appears alongside the attachment:

WhatsApp eventLabel shown in Chatwoot
_event_media_[image]
_event_voice_note_[audio]
_event_document_[file]
_event_video_[video]
_event_location_[location]
_event_sticker_[sticker]
_event_order_[order]

Chatwoot → WhatsApp

When an agent uploads files in Chatwoot, each attachment is forwarded as a separate WhatsApp message. The plugin detects the MIME type from the file extension when uploading local files:

ExtensionMIME type
.jpg / .jpegimage/jpeg
.pngimage/png
.gifimage/gif
.webpimage/webp
.mp4video/mp4
.pdfapplication/pdf
.mp3audio/mpeg
.ogg / .opusaudio/ogg
.wavaudio/wav
.svgimage/svg+xml
otherapplication/octet-stream

For remote URLs, the MIME type is taken from the HTTP Content-Type response header automatically.

API reference

createChatwootPlugin(config)

Creates the plugin instance. Returns a ChatwootPlugin.

chatwoot.attach(bot)

Wires the plugin into the bot. Must be called once after createBot.

  • Validates Chatwoot credentials (checkAccount)
  • Finds or creates the API-channel inbox
  • Registers the account webhook in Chatwoot if webhookUrl is configured
  • Auto-registers the HTTP route on provider.server if webhookUrl is configured
  • Listens to send_message and provider.message events

chatwoot.handleWebhook(bot, body)

Processes a raw webhook body sent by Chatwoot. Call this from your HTTP route handler.

chatwoot.getApi()

Returns the underlying ChatwootApi instance for direct API calls.

chatwoot.getInbox()

Returns the ChatwootInbox object ({ id, name }) or null before attach().

chatwoot.status

true while the plugin is operational. Set to false automatically if credentials fail.

Keywords

chatwoot

FAQs

Package last updated on 02 Apr 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts