Back to Nodes

OpenBSP

Last updated Oct 7, 2026

Send and receive WhatsApp and Instagram messages through OpenBSP — the open-source WhatsApp/Instagram Business Platform on Meta's official Cloud API.

201 Weekly Downloads
219 Monthly Downloads

Included Nodes

OpenBSP
OpenBSP Trigger

Description

n8n-nodes-openbsp

n8n community nodes for
OpenBSP, the open-source
WhatsApp and Instagram Business Platform built on Meta’s official Cloud API.

Send and receive WhatsApp and Instagram messages from your n8n workflows.
Trigger on incoming messages and delivery-status changes; send text, media,
templates, locations, and contacts; and read conversations, contacts, and
templates.

Context comes with the message. Every trigger event (and the Get Context
action) can carry the whole conversation: the organization, the contact, and the
recent messages in chronological order. Your AI node replies with full history
and no extra wiring. There is no memory node to configure, no chat-history
database to host, and no contact lookup keyed by phone number.

This package provides two nodes:

  • OpenBSP: actions organized by resource. Message (Send Text / Media /
  • Template / Location / Contacts, Get Status, Get Context),
    Conversation, Contact, Template, Account.

  • OpenBSP Trigger: starts a workflow on On Message, **On Message
  • Status, or On Conversation** events. It registers and removes the OpenBSP
    webhook for you when the workflow is activated or deactivated, so there is no
    manual webhook setup.

    Installation · Credentials ·
    Quickstart ·
    Example workflows · Get Context ·
    Operations · Development ·
    Compatibility

    Installation

    In n8n, open Settings → Community Nodes → Install and enter
    n8n-nodes-openbsp. See the n8n
    community nodes guide.

    !Install the community node

    Credentials

    You need an OpenBSP project with at least one connected WhatsApp or Instagram
    number. Use the hosted instance at web.openbsp.dev, or self-host from the
    OpenBSP repo.

    Create one OpenBSP API credential:

    | Field | Notes |
    | —————————- | ————————————————————————— |
    | OpenBSP API Key | OpenBSP UI → Settings → API Keys. Admin role required for the Trigger node. |
    | Supabase Publishable Key | Pre-filled for the hosted instance. Self-hosters use their own. |
    | Supabase Project URL | Pre-filled for the hosted instance. Self-hosters use their own project URL. |

    Hosted-instance users only paste the API key; the other two default to
    web.openbsp.dev. The credential authenticates REST calls with the
    apikey/api-key headers and Edge Function calls with Authorization: Bearer
    automatically. See
    AUTH.md.

    !Create the OpenBSP API credential

    Quickstart: your first workflow

    This walkthrough takes you from zero to a working WhatsApp auto-responder. It
    assumes you have installed the node and have an OpenBSP API key.

    1. Add the OpenBSP API credential

    In n8n go to Credentials → New → OpenBSP API. Paste your **OpenBSP API
    Key**. If you use the hosted instance at web.openbsp.dev, leave the publishable
    key and project URL at their defaults; self-hosters override all three. Click
    Save, and n8n runs a connection test against your OpenBSP project.

    > Use an Admin API key if you plan to use the OpenBSP Trigger. It needs
    > permission to register webhooks.

    2. Send your first message

    1. Create a new workflow and add a Manual Trigger.
    2. Add an OpenBSP node and set:
    – Resource: Message
    – Operation: Send Text
    – Account: pick your sender from the list (your WhatsApp number)
    – To: a recipient in international format, digits only (e.g.
    5491155551234)
    – Text: Hello from n8n 👋
    3. Click Execute step.

    !The OpenBSP Send Text action

    > Service window: plain text only reaches contacts inside the 24-hour
    > customer-service window. To start a brand-new conversation, use **Send
    > Template** with an approved template instead.

    3. Auto-reply to incoming messages (echo bot)

    1. Start a new workflow with an OpenBSP Trigger node.
    – Event: Message
    – Direction: Incoming Only
    2. Add an OpenBSP node (Message → Send Text) connected to the trigger:
    – Account: ={{ $json.data.organization_address }}
    – To: ={{ $json.data.conversation_address }}
    – Service: ={{ $json.data.service }}
    – Text: =You said: {{ $json.data.content.text }}
    3. Activate the workflow. Activating registers the OpenBSP webhook
    automatically; deactivating removes it.

    !The echo-bot workflow

    Send a WhatsApp message to your number, and the workflow echoes it back.

    !Workflow execution output

    > Your n8n instance must be reachable from the public internet for the trigger
    > to receive events. See Development for local testing options.

    4. See it in OpenBSP

    Open the OpenBSP web UI. The conversation shows your message and the automated
    reply alongside everything else your team handles.

    !The conversation in OpenBSP

    You can also import a ready-made version of these workflows from
    Example workflows instead of building them by hand.

    Example workflows

    Import via Workflows → ⋯ (top-right) → Import from File (or copy the JSON and
    paste it onto the canvas). After importing, open each OpenBSP node and select
    your OpenBSP API credential.

    Ready-to-import files live in examples/:

    | Workflow | File | What it does |
    | ————- | ———————————————————— | ——————————————————————————————————————————————————- |
    | Echo bot | examples/echo-bot.json | Replies to every incoming message with its own text. The smallest end-to-end example. |
    | AI auto-reply | examples/ai-auto-reply.json | Loads the conversation thread as context and lets an LLM reply with full history, no memory node required. Needs a chat-model credential (e.g. OpenAI). |

    Echo bot (JSON)

    {
    	"name": "OpenBSP — Echo bot",
    	"nodes": [
    		{
    			"parameters": { "event": "onMessage", "direction": "incoming", "serviceFilter": "any" },
    			"name": "On incoming message",
    			"type": "n8n-nodes-openbsp.openBspTrigger",
    			"typeVersion": 1,
    			"position": [380, 300],
    			"credentials": { "openBspApi": { "id": "REPLACE_ME", "name": "OpenBSP account" } }
    		},
    		{
    			"parameters": {
    				"resource": "message",
    				"operation": "sendText",
    				"account": {
    					"__rl": true,
    					"value": "={{ $json.data.organization_address }}",
    					"mode": "id"
    				},
    				"service": "={{ $json.data.service }}",
    				"to": "={{ $json.data.conversation_address }}",
    				"text": "=You said: {{ $json.data.content.text }}"
    			},
    			"name": "Echo back",
    			"type": "n8n-nodes-openbsp.openBsp",
    			"typeVersion": 1,
    			"position": [680, 300],
    			"credentials": { "openBspApi": { "id": "REPLACE_ME", "name": "OpenBSP account" } }
    		}
    	],
    	"connections": {
    		"On incoming message": { "main": [[{ "node": "Echo back", "type": "main", "index": 0 }]] }
    	}
    }
    
    AI auto-reply (with conversation context) (JSON)

    Turn on Load Conversation Context in the trigger so the recent thread is
    attached to the event. The AI Agent reads that thread straight from
    $json.context.messages in its system prompt, so no n8n memory node is needed.
    Connect any chat model to the AI Agent.

    {
    	"name": "OpenBSP — AI auto-reply (with context)",
    	"nodes": [
    		{
    			"parameters": {
    				"event": "onMessage",
    				"direction": "incoming",
    				"serviceFilter": "any",
    				"loadContext": true
    			},
    			"name": "On incoming message",
    			"type": "n8n-nodes-openbsp.openBspTrigger",
    			"typeVersion": 1,
    			"position": [340, 320],
    			"credentials": { "openBspApi": { "id": "REPLACE_ME", "name": "OpenBSP account" } }
    		},
    		{
    			"parameters": {
    				"promptType": "define",
    				"text": "={{ $json.data.content.text }}",
    				"options": {
    					"systemMessage": "=You are a helpful WhatsApp assistant for our business. Keep replies short.nnConversation so far (oldest to newest):n{{ $json.context.messages.map(m => (m.sender_address ? 'Customer' : 'Assistant') + ': ' + (m.content && m.content.text ? m.content.text : '[non-text message]')).join('\n') }}"
    				}
    			},
    			"name": "AI Agent",
    			"type": "@n8n/n8n-nodes-langchain.agent",
    			"typeVersion": 1.7,
    			"position": [640, 320]
    		},
    		{
    			"parameters": { "model": "gpt-4o-mini", "options": {} },
    			"name": "OpenAI Chat Model",
    			"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
    			"typeVersion": 1,
    			"position": [640, 520],
    			"credentials": { "openAiApi": { "id": "REPLACE_ME", "name": "OpenAI account" } }
    		},
    		{
    			"parameters": {
    				"resource": "message",
    				"operation": "sendText",
    				"account": {
    					"__rl": true,
    					"value": "={{ $('On incoming message').item.json.data.organization_address }}",
    					"mode": "id"
    				},
    				"service": "={{ $('On incoming message').item.json.data.service }}",
    				"to": "={{ $('On incoming message').item.json.data.conversation_address }}",
    				"text": "={{ $json.output }}"
    			},
    			"name": "Send reply",
    			"type": "n8n-nodes-openbsp.openBsp",
    			"typeVersion": 1,
    			"position": [1000, 320],
    			"credentials": { "openBspApi": { "id": "REPLACE_ME", "name": "OpenBSP account" } }
    		}
    	],
    	"connections": {
    		"On incoming message": { "main": [[{ "node": "AI Agent", "type": "main", "index": 0 }]] },
    		"OpenAI Chat Model": {
    			"ailanguageModel": [[{ "node": "AI Agent", "type": "ailanguageModel", "index": 0 }]]
    		},
    		"AI Agent": { "main": [[{ "node": "Send reply", "type": "main", "index": 0 }]] }
    	}
    }
    

    Get Context

    Webhooks deliver a single row. The Message → Get Context action (and the
    trigger’s Load Conversation Context option) enrich that event with the whole
    thread: the organization, the contact, and the recent messages in chronological
    order. It is the same shape OpenBSP’s agent-client builds for an AI agent, so
    you can pass it directly to an AI or LLM node.

    This is what replaces the usual memory plumbing. Instead of adding a chat-memory
    node, keying a session by phone number, and standing up Postgres or Redis to
    remember the conversation, you read the thread from a field that is already on
    the item.

    The trigger emits the changed row under data, plus entity and action. With
    context loading on, a context object is attached. Here is a real event for an
    incoming WhatsApp message, trimmed for readability:

    {
    	"data": {
    		"id": "msg_3f9a",
    		"conversationid": "conv7c2e",
    		"organization_address": "552398765432",
    		"conversation_address": "5491155551234",
    		"sender_address": "5491155551234",
    		"service": "whatsapp",
    		"timestamp": "2026-06-27T14:05:03.000Z",
    		"content": {
    			"version": "1",
    			"type": "text",
    			"kind": "text",
    			"text": "Great, what time do you close today?"
    		}
    	},
    	"entity": "messages",
    	"action": "insert",
    	"context": {
    		"organization": { "id": "org_1b4d", "extra": { "name": "Acme Café" } },
    		"conversation": {
    			"id": "conv_7c2e",
    			"service": "whatsapp",
    			"organization_address": "552398765432",
    			"conversation_address": "5491155551234"
    		},
    		"contact": { "name": "María López", "extra": {} },
    		"contact_address": { "address": "5491155551234", "extra": {} },
    		"messages": [
    			{
    				"sender_address": "5491155551234",
    				"timestamp": "2026-06-27T14:02:11.000Z",
    				"content": { "type": "text", "kind": "text", "text": "Hi, do you have oat milk?" }
    			},
    			{
    				"sender_address": null,
    				"timestamp": "2026-06-27T14:02:40.000Z",
    				"content": { "type": "text", "kind": "text", "text": "Yes! Oat, almond and soy." }
    			},
    			{
    				"sender_address": "5491155551234",
    				"timestamp": "2026-06-27T14:05:03.000Z",
    				"content": {
    					"type": "text",
    					"kind": "text",
    					"text": "Great, what time do you close today?"
    				}
    			}
    		]
    	}
    }
    

    context.messages is the full thread in chronological order (each row also
    carries id, conversationid, status, and createdat, trimmed above). The
    newest message is both the last entry here and the row under data.

    What the AI node receives

    The AI auto-reply example folds that thread into the
    agent’s system prompt with a single expression
    ($json.context.messages.map(...).join('n')). For the event above, the model
    reads:

    You are a helpful WhatsApp assistant for our business. Keep replies short.

    Conversation so far (oldest to newest): Customer: Hi, do you have oat milk? Assistant: Yes! Oat, almond and soy. Customer: Great, what time do you close today?

    The latest message (Great, what time do you close today?) is passed separately
    as the user input. The history is already on the item, so there is nothing else
    to wire up.

    That example expression only reads each message’s text, so text turns and
    media captions come through, while uncaptioned media, locations, contacts,
    and templates collapse to [non-text message]. To surface those, branch on
    content.type and content.kind in the expression: a media file lives at
    content.file.uri, a location at content.data.latitude /
    content.data.longitude, and a template under content.data.name.

    Operations

    The OpenBSP action node, by resource:

    | Resource | Operations |
    | —————- | ————————————————————————————————- |
    | Message | Send Text · Send Media · Send Template · Send Location · Send Contacts · Get Status · Get Context |
    | Conversation | Get · Get Many |
    | Contact | Search · Get · Create |
    | Template | Get Many |
    | Account | Get Many |

    The OpenBSP Trigger fires on On Message, On Message Status, or **On
    Conversation, with Direction (incoming / outgoing / any) and Service**
    (WhatsApp / Instagram / any) filters and an optional **Load Conversation
    Context**.

    Development

    Requires Node.js ≥ 22, Docker, and Git.

    npm install
    npm run build      # compile to dist/
    npm run lint       # eslint-plugin-n8n-nodes-base (+ n8n community rules)
    npm run dev        # run n8n with this node loaded + hot reload (http://localhost:5678)
    

    Testing in a Docker container

    npm run dev is the fastest loop. To instead test inside the official n8n image,
    mount the built package as a custom extension:

    docker volume create n8n_data
    npm run build
    docker run -it --rm --name n8n -p 5678:5678 
      -v n8n_data:/home/node/.n8n 
      -v "$(pwd)":/home/node/.n8n/custom/n8n-nodes-openbsp 
      -e N8NCUSTOMEXTENSIONS=/home/node/.n8n/custom 
      docker.n8n.io/n8nio/n8n
    

    Open http://localhost:5678 and search the node panel for OpenBSP.

    > Triggers need a public URL. Cloud OpenBSP cannot reach localhost. Either
    > run n8n with a tunnel, or point the credential at a local Supabase stack
    > (npx supabase start). The action node needs neither.

    Compatibility

  • n8n nodes API version 1; Node.js ≥ 22.
  • OpenBSP runs on Meta’s official Cloud API: no QR or session to manage; messages
  • outside the 24-hour service window require an approved template; groups and
    status broadcasts are not available.

    Resources

  • OpenBSP repo
  • n8n community nodes docs

License

MIT