socialmate

n8n community node for SocialMate — automate WhatsApp messaging through your self-hosted SocialMate desktop server (send, schedule and queue personalized messages, manage chats, contacts, groups, media, and react to incoming messages).

Documentation

n8n-nodes-socialmate

SocialMate

npm version npm downloads license node version

Official n8n community node for SocialMate — the self-hosted WhatsApp automation server. Run it as a desktop app (Windows/macOS/Linux) or headless on your own VPS with Docker; this node talks to either the same way. On the desktop it sends from your own residential IP (same network as your phone); on a VPS (a datacenter IP) you can route an account through your own residential/mobile proxy — set it in the app//admin or via PUT /v1/accounts/:id/proxy (Pro).

Automate WhatsApp from n8n: send and schedule personalized messages, queue and batch-import to opted-in contacts (an opt-in Pro feature), manage chats, contacts, groups and media, and react to incoming messages and lifecycle events — all through your own SocialMate server.

Installation

In n8n: Settings → Community Nodes → Install and enter n8n-nodes-socialmate.

Or self-hosted via npm:

npm install n8n-nodes-socialmate

Connecting

  1. In the SocialMate app: API & Integrations → n8n → New connection. Pick the account
    scope, and SocialMate mints an API key (and a self-registering webhook) for it. Use an
    admin-scope key if you want the Trigger to register its webhook automatically.
  2. In n8n, create a SocialMate API credential:
    • Server URL — http://127.0.0.1:3456 when n8n runs on the same machine as the
      app, or your named-tunnel hostname (Pro) for a remote n8n. No trailing slash.
    • API Key — the key from step 1.
  3. Click Test — you should see your server version and license tier.

Quick tunnels are not supported. A free quick tunnel gets a new
*.trycloudflare.com URL on every restart, which breaks a saved credential. Run n8n on
the same machine as the app (localhost) or use a stable named tunnel (Pro).

Account scope (v2.1+)

Every SocialMate API key carries an account scope, chosen when you create the
connection in the app:

Scope The key can act on In the node
This account exactly one account the Account field auto-selects it — nothing to pick
Selected accounts a chosen subset the Account dropdown lists only those accounts; pick one per operation
All accounts every account (incl. future) the Account dropdown lists all; pick one per operation

There is no "Default Account ID" — the key already knows which accounts it may use:
GET /v1/accounts is filtered to that set server-side, so the node's Account dropdown
only ever shows accounts you can actually use, and auto-resolves when the key is bound to a
single account. The SocialMate Trigger registers its webhook with the same key, so the
server scopes deliveries automatically (an optional account filter exists to further narrow
an "All accounts" key).

Upgrading from v2.0: an old credential's Default Account ID is still honored as a
fallback, but you can clear it — the scope-aware Account picker replaces it.

Nodes

  • SocialMate (action) — Message, Chat, Contact, Group, Media, Queue, Account, Sync, Webhook, API Key and System operations.
  • SocialMate Trigger — fires your workflow on SocialMate events. It self-registers its webhook with the server and verifies the HMAC signature on every delivery.

Operations — Free vs Pro

Operations marked Pro require a SocialMate Pro license; on Free they return a clear
402 naming the missing feature.

Resource Free Pro
Message Send Text (with Reply To) · React · Mark Read · Send Typing Send Media · Send Poll · Get Poll Results · Send Location · Send Contact · Get AI Context · Search / List history
Chat Get Many —
Contact Get · Get Many Update (Agent Memory — save a name/notes/tags your agent learned)
Group Get Many · Get · Get Invite Link Create · Update Participants · Set Subject · Set Description · Leave
Media Get Many · Get · Get Stats · Download File · Download Thumbnail · Get Download Queue Force Download · Delete · Run Cleanup · Set Context (Agent Memory — cache an AI description)
Queue Get Status · Get Items · Get Batches Enqueue · Queue a Batch · Pause · Resume · Cancel/Retry Item · Cancel/Retry Batch
Account Get Many · Get · Get Anti-Ban Status · Get Proxy (masked) Set Proxy · Clear Proxy (need an admin-scope key)
Sync Get Status Trigger
Webhook Get Many · Get · Create · Update · Delete · Test · Get Deliveries —
API Key Get Many · Create · Rotate · Delete —
System Get Capabilities · Get Status · Get Network Status · Get Version —

Every send still passes through SocialMate's anti-ban engine (rate limits, jitter, warming,
risk checks), so a runaway workflow can't burn your number.

Build an AI agent with full chat memory — Message → Get AI Context

The Trigger only hands your workflow the single new message. To give an AI agent the
whole conversation, drop Message → Get AI Context between the Trigger and your
AI Agent. It reads the chat's history from the SocialMate DB and returns it AI-ready:

  • transcript — a role-mapped string to paste straight into the agent's system message:
    Conversation so far:\n{{ $json.transcript }}.
  • messages — a structured [{ role: 'user'|'assistant', name, content, ts }] array for
    chat-model / memory nodes.
  • meta — { totalMessages, returnedMessages, truncated, tokenEstimate, … }.

It role-maps automatically (the contact = user, your account = assistant), windows the
history to a token budget (maxTokens, default 4000) and message cap (maxMessages,
default 50), supports order (oldest | newest), format (both | messages |
transcript), includeTimestamps, and beforeTs (window to messages before a Unix-ms time),
and labels media ([image], [voice],
…). (Requires SocialMate Pro — reading history.) See
examples/real-estate-deepseek-agent.json.

Use SocialMate as an AI Agent tool

Every SocialMate operation is exposed as an AI Agent tool (usableAsTool), so an n8n AI
Agent
can call them on its own — "send this reply", "look up the contact", "fetch the last 20
messages", "queue a reminder"
— choosing the operation from its description.

Enable it on your n8n instance (required for any community node used as a tool):

N8N_COMMUNITY_PACKAGES_ALLOW_TOOL_USAGE=true

Then add SocialMate as a tool on an AI Agent node and pick the operation. Pair it with
Message → Get AI Context (the conversation-memory tool) so the agent can read a whole thread
before replying — a combination no official / Business-API node offers.

Some n8n versions have an open bug where certain community-node tools hand the agent an empty
observation (n8n#26202). If you hit it, upgrade n8n,
call the operation from a normal (non-agent) node, or use MCP (below), which bypasses it.

Prefer MCP (Claude Desktop / Cursor / any client)? SocialMate ships a native Model Context
Protocol
server, socialmate-mcp, exposing 44 WhatsApp tools (see API & Integrations → MCP in
the app for the copy-paste config), plus an n8n MCP Server Trigger recipe. One thing to know: MCP is
request/response with no inbound push, so to auto-react to incoming messages you either poll the
whatsapp_fetch_new_messages tool or drive the loop from the SocialMate Trigger below. Full
walkthrough + the $fromAI pattern + 11 use cases in
docs/AI-AGENT-TOOL-GUIDE.md. Importable examples:
examples/ai-agent-tool.json and
examples/mcp-server-trigger.json.

Make it behave like a human

A drop-in System Message that teaches an agent the human reply cadence — mark read →
recall the thread → show typing → react or reply (threaded)
— plus the full tool inventory,
the tier and anti-ban error contract (402 / blocked / queueable:false /
signal_rate_limit), what the agent genuinely cannot do (no edit/delete/forward, it can't
see the contact typing, buttons are deprecated → send a poll), and the consent + honesty rules:

docs/AI-AGENT-SYSTEM-PROMPT.md

examples/ai-agent-tool.json ships with it pre-loaded and the tools wired
(Mark Read · Show Typing · React · Send Poll · Get Conversation Memory · Check My Limits).
Reactions, read receipts and the typing indicator are free on every tier and consume no
send budget — an agent can be human without spending its message allowance.

Trigger events

The SocialMate Trigger covers all 35 events. 9 are available on Free —
message.received, message.sent, account.connected, account.disconnected,
tunnel.url_changed, tunnel.stopped, license.activated, license.deactivated,
license.tier_changed; the other 26 (incl. tunnel.started, the delivery receipts
message.delivered / message.read, the conversational events message.reaction /
poll.vote / group.participants_updated, the Agent Memory media.context_updated event,
and the High-Volume Mode account.danger_mode_* events) require Pro and are labelled (Pro)
in the picker:

  • Messaging: message.received, message.sent, message.delivered (Pro), message.read (Pro), message.reaction (Pro), poll.vote (Pro)
  • Groups: group.participants_updated (Pro) — join, leave, promote, demote
  • Accounts: account.connected, account.disconnected, account.banned, contacts.updated, account.danger_mode_enabled, account.danger_mode_disabled
  • Tunnel: tunnel.started, tunnel.url_changed, tunnel.stopped
  • Sync: sync.started, sync.completed, sync.failed
  • Media: media.discovered, media.downloaded, media.failed, media.deleted, media.context_updated
  • Smart queue: queue.item.enqueued, queue.item.processing, queue.item.sent, queue.item.failed, queue.item.cancelled, queue.batch.created, queue.batch.completed, queue.batch.cancelled
  • License: license.activated, license.deactivated, license.tier_changed

Delivery receipts. message.sent only means "handed to WhatsApp". message.delivered and
message.read close the loop — but a contact with read receipts turned off never produces
message.read, so its absence is not proof the message went unread. Correlate on messageId.

Every delivery is a JSON envelope: { "version", "event", "timestamp", "tunnelUrl", "data": { … } }. A
message.received example:

{
  "version": 1,
  "event": "message.received",
  "timestamp": "2026-06-03T12:00:00.000Z",
  "tunnelUrl": "https://your-name.example.com",
  "data": {
    "accountId": "acc_123",
    "messageId": "ABCD1234",
    "chatId": "15551234567",
    "senderId": "15551234567",
    "body": "Is my order shipped?",
    "type": "text",
    "timestamp": 1750000000000,
    "fromMe": false
  }
}

In a workflow, read fields as {{ $json.data.body }}, {{ $json.data.chatId }}, etc.

Request & response examples

The action node builds these requests for you; the JSON below shows the underlying SocialMate
API shapes (handy when mapping fields). Responses are wrapped in the { "data": … } envelope.

Message → Send Text — when to use: the default outbound path; works on every tier.

// request
{ "chatId": "15551234567", "text": "Hello from n8n 👋" }
// 200
{ "data": { "sent": true, "messageId": "msg_abc", "chatId": "15551234567@s.whatsapp.net", "status": "sent" } }

Message → Send Media (Pro) — prefer a url so a rate-limited send can auto-queue (202):

{ "chatId": "15551234567", "media": { "type": "image", "url": "https://example.com/p.jpg", "caption": "Invoice" } }

Message → Get AI Context (Pro) — when to use: give an AI agent the whole thread in one call.
Note tokenEstimate lives inside meta, not at the top level:

{
  "data": {
    "account": { "id": "acct_1", "name": "Sales", "phone": "15551230000" },
    "chat": { "id": "15551234567", "name": "Jane" },
    "messages": [ { "role": "user", "name": "Jane", "content": "Hi", "ts": 1750000000000, "type": "text" } ],
    "transcript": "Jane: Hi",
    "meta": {
      "totalMessages": 1, "returnedMessages": 1, "truncated": false,
      "oldestReturnedTs": 1750000000000, "newestReturnedTs": 1750000000000,
      "tokenEstimate": 8,
      "window": { "maxMessages": 50, "maxTokens": 4000 }
    }
  }
}

Queue → Queue a Batch (Pro; opt-in, off by default) — when several people who are already
waiting on you
need the same news (an order delay, a new pickup time), queue one individual,
personalised message each
and let the anti-ban engine pace them — up to 5000 rows. Only for people
who contacted you or explicitly opted in; never a list you bought, scraped or guessed. This is not a
broadcast: identical text to many contacts is blocked by the duplicate guard, so personalise every
row.

{
  "template": "Hi {{name}}, your order {{order}} shipped 🚚",
  "batchName": "June shipping notices",
  "rows": [ { "chatId": "15551234567", "displayName": "Jane", "fields": { "name": "Jane", "order": "A-1001" } } ]
}

Account → Get Anti-Ban Status — when to use: check headroom before a burst; if paused or a
counter is near its max, back off (sending anyway just auto-queues on Pro or returns 429 on Free).

API-key scopes

Keys carry one or more scopes; an operation that needs more than the key has returns 403:

  • read — GET operations (accounts, chats, contacts, groups, media, status…).
  • send — sending messages, the signal lane (react / mark read / typing), enqueuing to the
    smart queue, and forcing a media download. Also the Agent Memory writes (Contact → Update,
    Media → Set Context) — saving what your agent learned shouldn't require account-admin rights.
  • admin — managing webhooks and API keys (the Trigger needs this to self-register),
    triggering a Sync, and Set / Clear Proxy. The rule of thumb: read means your WhatsApp
    data
    ; anything that changes how the server itself is wired is admin.

Errors

Status Meaning
401 Missing or invalid API key.
402 A Pro feature on a Free license — the response names the required feature.
403 The key lacks the required scope (read / send / admin).
429 Rate-limited. A transient per-key limit is retried automatically (up to 3×, capped backoff); an anti-ban send block is surfaced as data instead — see Send outcomes.

Send outcomes

A Send Text / Send Media call resolves one of these ways. The first three are returned as
data you can branch on (no error thrown), so one workflow can handle every case:

  • Sent — delivered immediately ({ sent: true, messageId, … }).
  • Queued (Pro) — anti-ban deferred it, so SocialMate auto-queued it and the worker
    retries when the number is eligible ({ queued: true, itemId, … }).
  • Blocked (typically Free) — anti-ban refused it and there's no auto-queue, so the node
    returns { blocked: true, reason, retryAfterMs, hint, upgrade }. Branch on blocked to back
    off, notify, or (on Pro) route to Queue → Enqueue. The node returns immediately — it
    never sleeps on the block's Retry-After (which can be hours during quiet hours).
  • 409 — the account isn't connected; link it in the app first.

The legacy POST /v1/accounts/:id/messages/media route is deprecated (no auto-queue,
sends a Sunset header) and is intentionally not exposed as an operation — use Send
Media
(the unified endpoint) instead.

License tiers & limits

Free covers text send, reads (chats/contacts/accounts/media), live webhooks, and
webhook/API-key management — one account. Pro adds media send, group management,
scheduling and opt-in batch sending, message history/search, sync, the smart queue, unlimited accounts
and a stable named tunnel.

Free is capped at 200 sends/day; Pro starts at 500/day per account and scales to
up to 5,000/day in High-Volume Mode (after 72h warming).

Examples

Importable workflows live in examples/:

  • ai-agent-tool.json — SocialMate as an AI Agent tool: an AI Agent that marks read, recalls the thread, shows a typing indicator, then reacts or replies (threaded). Ships with the human-cadence system prompt pre-loaded. See docs/AI-AGENT-SYSTEM-PROMPT.md and docs/AI-AGENT-TOOL-GUIDE.md.
  • mcp-server-trigger.json — WhatsApp MCP server built in n8n: expose SocialMate to Claude Desktop / Cursor via the MCP Server Trigger.
  • real-estate-deepseek-agent.json — a WhatsApp AI concierge (Trigger → Get AI Context → DeepSeek → reply).
  • auto-reply-trigger.json — a minimal Trigger → Send Text auto-reply round-trip.
  • scheduled-bulk-send.json — schedule a daily batch of queued, personalised reminders to opted-in contacts via the smart queue (Pro). One individual message per person, paced by the anti-ban engine — not a broadcast.
  • keyword-router.json — Trigger → IF on the message text → route to different replies (extend with more branches).
  • drip-onboarding-sequence.json — Trigger → three scheduled Queue Enqueues that drip a welcome sequence over a few days (Pro).
  • order-confirmation-webhook.json — your store's order webhook → Send Text order confirmation.
  • new-lead-alert.json — Trigger → forward a short summary of each inbound message to your team group.
  • vision-memory-loop.json — Agent Memory (Pro): media.discovered → skip already-described items → Download File → your vision/transcription model → Set Media Context. Each photo/voice note is described once and then comes back as [image: …] inside Get AI Context — no re-analysis, fewer tokens.

Development

npm install
npm run build      # tsc + copy icons to dist
npm run lint       # eslint-plugin-n8n-nodes-base

License

MIT

Discussion