n8n node
The PrivacyFlow n8n community node — install it, send and poll encrypted messages from visual workflows, and preserve routing fields when replying.
The PrivacyFlow n8n community node is an n8n node package that exposes two nodes: Send (an Action node) and Poll Trigger (a Trigger node). Both call the public API using a credential you store in n8n’s encrypted credential store.
Install
In your n8n instance:
- Open Settings → Community Nodes.
- Install
n8n-nodes-privacyflowfrom npm. - Restart n8n if prompted.
You need n8n 1.x or newer and Node 22+. The package has no runtime dependencies beyond n8n-workflow (vendored by n8n).
Dev install (for contributors):
git clone https://github.com/privacyflow-app/n8n-nodes-privacyflow
cd n8n-nodes-privacyflow
npm install
npm run dev # links into your local n8n community-nodes directory
Configure the credential
Create a new PrivacyFlow API credential in n8n:
| Field | Value |
|---|---|
| API Key | pf_live_… — your key from the dashboard Credentials section. |
| Base URL | https://privacyflow.app (the default). Override only for self-hosted instances. |
The credential stores apiKey and baseUrl. The node sends the key as Authorization: Bearer <apiKey> on every call. Click Test in the credential editor — it pings GET /api/v1/auth/verify and asserts valid === true. See verify.
Note
Older n8n-nodes-privacyflow releases ship with https://api.privacyflow.app as the Base URL preset. The canonical host is https://privacyflow.app — type it in explicitly as the Base URL value, until a future node release updates the preset.
The Send node (Action)
PrivacyFlow → Send a text message in the node menu. Required and optional fields per message:
| Field | Required | Notes |
|---|---|---|
appId | yes | Must be one of the appIds the credential’s key can access. |
contactId | yes | Recipient in the messenger’s native format. See contact formats. |
messenger | yes | signal, simplex, or session. |
message | yes | 1–10,000 characters. |
groupId | no | Set when replying to a group message (matches the inbound’s groupId). |
The node validates inputs locally with the same rules as the API (see send). On success it returns the same {successfulMessages, failedMessages, totalAccepted, totalFailed} envelope so downstream nodes can branch on per-message failure.
Send one
A single-trigger-to-action workflow:
[Schedule Trigger] → [PrivacyFlow Send]
In the Send node, fill appId, contactId, messenger, message. Run. The node returns:
{
"successfulMessages": [/* … */],
"failedMessages": [],
"totalAccepted": 1,
"totalFailed": 0
}
Send a batch
PrivacyFlow accepts up to 50 messages per call. Build the batch with a Code node:
[Manual Trigger] → [Code] → [PrivacyFlow Send]
In the Code node, return an array of objects shaped like { appId, contactId, messenger, message }:
return [
{ appId: "app_123", contactId: "+12025550104", messenger: "signal", message: "Your order shipped." },
{ appId: "app_123", contactId: "+12025550105", messenger: "signal", message: "Your order shipped." },
{ appId: "app_123", contactId: "+12025550106", messenger: "signal", message: "Your order shipped." }
];
In the Send node, set the messages field to {{ $json }} (or use the node’s “Many” mode if available) so the array posts to POST /api/v1/messages/send as one batch. One request, three messages, three units off your send rate budget.
The Poll Trigger node
PrivacyFlow Trigger in the node menu. Emits one n8n item per inbound message. One field:
| Field | Default | Range |
|---|---|---|
Message Limit | 50 | 1–50 |
The trigger polls GET /api/v1/messages/poll?limit=N on the schedule n8n assigns to the trigger (configure the polling interval in n8n’s trigger settings; 3–5 seconds is reasonable for chat, 30–60 for batch processing). Each polled item becomes an n8n item with the PolledMessage shape.
Preserving routing fields when replying
The single most important rule when building a Poll → Reply workflow: copy appId, contactId, messenger, and groupId from the polled item into the Send node’s fields. Getting any of them wrong produces a per-message failure in failedMessages or lands the reply in the wrong thread.
The trigger node surfaces this in its UI:
⚠ When sending a reply, preserve
appId,contactId,messenger, and (if present)groupIdfrom the polled message. Changing the messenger or contactId will route the reply to the wrong recipient or fail.
A correct Poll → Reply loop:
[PrivacyFlow Trigger (limit: 50)] → [n8n Set/Code: extract appId, contactId, messenger, groupId, content] → [PrivacyFlow Send: pass those fields through]
In the Send node, bind each field to the trigger’s output:
appId={{ $json.appId }}contactId={{ $json.contactId }}messenger={{ $json.messenger }}groupId={{ $json.groupId }}(only present on group messages; leave blank when not)message= your reply text, however you generate it.
Why batch matters
The free-tier send limit is 600 messages per minute, not 600 requests. A 50-message batch consumes 50 units of the same budget that a 1-message request consumes 1 unit of — but the overhead of 50 separate requests is far higher than one batched one. For broadcasts, always batch. See rate limiting and the broadcast prompt on the MCP server for the same idea from the agent side.
Warning
The Poll trigger is a destructive read. Each trigger run pops the message off your queue. If n8n re-runs the workflow (a manual re-execution, a failed downstream node), the message is already gone — there is no replay. Design your workflow to be idempotent or to persist the polled item before doing work.
Related endpoints
Both nodes use the same four endpoints behind the scenes:
| Node action | Endpoint |
|---|---|
| Credential test | GET /api/v1/auth/verify |
| Poll trigger | GET /api/v1/messages/poll?limit=N |
| Send node | POST /api/v1/messages/send |
| (Health check) | GET /api/v1/health (not used by the node, but available for monitoring) |
See the API Reference for full request/response schemas.