n8n
The BlueBot community node for n8n, with every resource and operation in the API and a trigger node that starts a workflow when a text arrives. Installing it on n8n Cloud and on your own server.
n8n-nodes-bluebot adds two nodes to n8n. The BlueBot node calls every operation in the BlueBot API: send a text, schedule one, read texts, check a number, manage webhooks. The BlueBot Trigger node starts a workflow when something happens, such as a text coming in, through a webhook BlueBot posts to.
Texts sent from n8n go through your sending rules like every other text and show source: "n8n" in BlueBot. Because n8n can run on your own server, a workflow’s logic and the data it reads stay on machines you control; only the texts themselves pass through BlueBot and your Mac. walks through one.
Install the node
The package is n8n-nodes-bluebot on npm. It needs n8n 1.85 or newer.
On your own n8n, as the owner or an admin:
Open Community Nodes
Go to Settings → Community Nodes and press Install a community node.
Install it
Type n8n-nodes-bluebot, tick the box that says you understand the risks of community nodes, and press Install. n8n downloads it and restarts its node list. Search the nodes panel for “BlueBot” to check.
If your n8n can’t install from the panel (community packages turned off, no network from the container, or a read-only image), install it by hand in n8n’s folder and restart n8n:
mkdir -p ~/.n8n/nodes
cd ~/.n8n/nodes
npm install n8n-nodes-bluebot
# then restart n8nIn Docker, run the same inside a volume mounted at /home/node/.n8n, or build your own image FROM n8nio/n8n with the package installed there, so it survives the container being replaced. In queue mode, every worker runs nodes too, so each worker’s image needs the package.
n8n Cloud installs only community nodes that n8n has verified. The BlueBot node follows n8n’s rules for verified nodes; until n8n Cloud lists it, use n8n’s HTTP Request node there, as described in .
Add your credentials
Make a key
In BlueBot, open Developers → API keys, press New key, name it “n8n” and tick the scopes your workflows need. The trigger needs webhooks:manage, and the credential test needs account:read. Copy the key; it is shown once.
Make the credential
In n8n, open Credentials, press Add credential and choose BlueBot API.
| Field | Required | What it is |
|---|---|---|
| API Key | Yes | Your bb_live_… key. n8n stores it encrypted with your instance’s encryption key. |
| Base URL | No | Leave it as https://usebluebot.com/api/v1. |
Press Save. n8n tests it with GET /v1/me and shows Connection tested successfully, or BlueBot’s message (such as “That key isn’t valid. It may have been revoked.”) when it fails.
The BlueBot node
Pick a Resource, then an Operation. Each operation is one API call, and every field matches the API’s field of the same name. The node sends one request per input item, so 30 items in means 30 texts, paced by your sending rules.
| Resource | Operations | Calls |
|---|---|---|
| Message | Send Text, Get, Get Many, Update, Cancel, Resolve | |
| File | Upload, Get | |
| Chat | Get, Get Many | |
| Conversation | Get, Get Many | |
| Lookup | Check iMessage | |
| Device | Get Mac, Get BlueBot Status | |
| Account | Get | |
| Settings | Get, Update | |
| Stop | Add, Get Many, Remove | |
| Template | Get, Get Many | |
| Event | Get, Get Many | |
| Webhook | Create, Get, Get Many, Update, Delete, Send Test Event, Rotate Secret | |
| Webhook Delivery | Get Many, Replay |
Message: Send Text
| Field | Type | Required | What it is |
|---|---|---|---|
| Send To | Options: Person, Group Chat | Yes | Who gets it. Default: Person. |
| To | String | For Person | A mobile number in any format (US numbers can leave off +1), or an email address the person uses for iMessage. |
| Group Chat ID | String | For Group Chat | A chat_ id from Chat → Get Many. BlueBot can’t start a new group. |
| Text | String | Unless files are added or a template is set | Up to 2,000 characters. Use expressions such as {{ $json.first_name }}. |
Under Add Field:
| Field | Type | What it is |
|---|---|---|
| Files | Options: File IDs, Binary Properties | File IDs takes file_ ids from File → Upload. Binary Properties names binary properties on the item (such as data), which the node uploads first. Up to 10, each up to 25 MB. |
| Service | Options: Auto, iMessage, SMS | Auto (the default) uses what the newest chat with the person used, else iMessage, and resends an iMessage that never went once as SMS. SMS needs your iPhone with Text Message Forwarding. |
| Send At | Date and time | Schedules the text. It waits as scheduled and can be changed or canceled until then. |
| Expires At | Date and time | Give up if it’s still waiting then. Default: 24 hours after it’s due. |
| Metadata | Key and value pairs | Up to 20 keys of up to 40 characters, values up to 500. Echoed on every webhook about the text. |
| Template ID | String | Send one of your templates instead of words, by its tpl_ id from Template → Get Many. Leave Text empty. |
| Template Variables | Name and value pairs | A value for each {{name}} in the template. A variable you leave out comes from the contact (first_name, last_name, company and custom fields) or your business name (business), else from the template’s own fallback. One with none of those stops the send with invalid_request, naming it. |
| Idempotency Key | String | Defaults to one made from the execution, the node and the item’s index, so Retry On Fail never sends a text twice. Set your own to make a send safe across executions, such as the record’s id. |
The output item is the message, usually state: "queued". A text that can’t go yet (quiet hours, your Mac offline, a daily limit) still succeeds, with hold.reason and hold.until. A text to somebody on your stop list comes back state: "canceled" with cancel_reason: "opted_out".
Message: Get Many
| Field | Type | What it is |
|---|---|---|
| Return All | Boolean | Follow the cursor to the end. Off by default. |
| Limit | Number | How many to return when Return All is off. Default 50. |
| Filters | Collection | Direction (In, Out), State, Person, Contact ID, Chat ID, Source, Created After, Created Before. |
Each text is one output item, newest first.
Message: Update, Cancel and Resolve
Update changes a scheduled text before it’s due: Text, Send At, Expires At and Metadata (which replaces the metadata whole). Cancel takes a Message ID and cancels a scheduled or queued text; one the Mac already took fails with conflict. Resolve settles an unconfirmed text with Action Mark Sent (the person got it) or Send Again (a new text with the same words).
File: Upload and Get
Upload takes a binary property (default data) and an optional Name, and outputs the file with its file_ id. Get takes a File ID and outputs the file; turn on Download to put its bytes in a binary property as well, which is how you save a picture or voice memo someone sent you. A file’s url works for an hour.
Lookup: Check iMessage
Takes a Number (a phone number or email address) and outputs service (imessage, sms or unknown), basis and last_seen_at. It reads your own Messages history through your Mac and waits up to 15 seconds. A number you’ve never texted is unknown, because Apple gives no way to ask.
Webhook operations
Create takes a URL (public https) and Events, and outputs the webhook with its signing secret, the one time the API shows it. Send Test Event sends an example of the type you pick to that webhook. Rotate Secret makes a new secret; the old one signs beside it for 24 hours. Webhook Delivery → Replay sends one delivery again. You rarely need these with the trigger node, which manages its own webhook.
When a call fails
The node shows BlueBot’s message as the error, its hint as the description, and the code, HTTP status and request id in the details, such as “Send to or chat_id.” with “Check the fields named in the message and send it again.” Quote the request id if you write to support.
- Turn on Retry On Fail in the node’s settings for
rate_limited(429) and the 5xx errors. The node waits at least theretry_afterBlueBot asks for, and its default idempotency key keeps a retried send from going twice. - Turn on Continue On Fail to let the other items go on when one has a bad number. The failed item’s output carries the error.
- A held text is not an error, and neither is a text that fails after it was accepted. Catch those with the trigger node on Message Failed, Message Expired and Message Unconfirmed.
The BlueBot Trigger node
Starts a workflow when BlueBot posts an event. It makes its own webhook in your BlueBot account when the workflow is activated, pointing at n8n’s production webhook URL, and deletes it when the workflow is deactivated.
| Field | Type | Required | What it is |
|---|---|---|---|
| Credential | BlueBot API | Yes | Needs webhooks:manage. |
| Events | Multi-options | Yes | Any of the , such as Message Received, Message Failed or Contact Stopped. Default: Message Received. |
| Output | Options: Record, Whole Event | No | Record (the default) outputs data: the message, contact or enrollment. Whole Event adds the envelope: id, type, api_version, timestamp. |
The node keeps the webhook’s signing secret in the workflow and checks webhook-signature on every request. A request without a valid signature, or more than five minutes old, is answered 401 and never starts the workflow, so nobody who learns the URL can fake a text.
To try it, press Listen for test event. The node makes a webhook to n8n’s test URL for as long as it listens. Then text your BlueBot number from another phone, one you’ve texted through BlueBot before (BlueBot copies only those chats unless Which chats to copy is set to Everything). The event shows in the node’s output.
| You got | It means | Do next |
|---|---|---|
| The event in the output | It works. | Build the rest of the workflow, then activate it. |
| “BlueBot couldn’t reach this URL” when listening or activating | n8n’s webhook URL isn’t public https, so BlueBot refused it. | Set WEBHOOK_URL as in . |
| Still listening after your text | No event came. | Check that your Mac is online and the chat is one BlueBot copies. |
On your own server
BlueBot only posts to public https addresses on the default port, and doesn’t follow redirects. A self-hosted n8n behind a reverse proxy must tell its nodes the public address, or the trigger node registers http://localhost:5678/…, which BlueBot refuses.
WEBHOOK_URL=https://n8n.example.com/
N8N_PROXY_HOPS=1- Put n8n behind a proxy that ends TLS (Caddy, nginx, Traefik) with a real certificate. A self-signed certificate fails BlueBot’s check.
- For a laptop with no public address, run a tunnel such as
cloudflared tunnel --url http://localhost:5678and setWEBHOOK_URLto the address it prints. Restart n8n after changing it. - Deactivate and activate a workflow after the address changes, so the trigger node makes a new webhook at the new address.
- Keep n8n’s encryption key (
N8N_ENCRYPTION_KEY) when you move servers, or the BlueBot credential can’t be read.
Without the node
Any n8n, n8n Cloud included, can call the API with the HTTP Request node.
Make a header credential
Make a Header Auth credential with Name Authorization and Value Bearer bb_live_….
Send a text
Add an HTTP Request node: Method POST, URL https://usebluebot.com/api/v1/messages, Authentication Generic Credential Type → Header Auth with that credential. Under Send Headers, add BlueBot-Client: n8n and an Idempotency-Key, such as {{ $execution.id }}-{{ $itemIndex }}. Under Send Body, choose JSON and send to and text.
To receive events without the trigger node, use n8n’s Webhook node and make the webhook yourself with POST /v1/webhooks. Check each request’s signature in a Code node before trusting it, as shows.