n8n node

WhatsApp, as an n8n node.

Trigger a workflow on an inbound message, send text, media, templates and interactive messages as actions, and reach the thousand other apps n8n already speaks to. On every plan, including Free.

Installing

Two nodes in one package — an action node and a trigger node — installed the way n8n installs any community node.

n8n → Settings → Community nodes
# install from npm
n8n-nodes-cosend

The action node is marked usable as a tool, so an n8n AI agent can call it directly rather than needing a wrapper workflow around it.

The trigger, and the two events worth installing for

Webhook, not polling, and that is a decision rather than a convenience. n8n's polling granularity bottoms out around a minute, and a thirty-second average reply delay is a product failure for a chat product. Polling every active workflow would also mean roughly 1,440 requests a day each, mostly returning nothing, against a product whose core tier is free. And status transitions are transient: a cursor-based poll coalesces them, a webhook delivers each one.

Filtering happens on our side, so a workflow subscribed to inbound messages never sees status noise.

Events the Cosend Trigger node can subscribe to, and when each fires.
Event Fires when
message.received An inbound message — text, media, reaction or reply
message.status sent · delivered · read · failed
message.echo The owner replied from the WhatsApp Business app. It exists only on coexistence numbers, which is why no cloud-API-only vendor can emit it — and it is what lets a workflow cancel its own follow-up when a human has already answered Coexistence only
conversation.created A new thread opened
conversation.updated State, assignee, control or labels changed
conversation.window_expiring The 24-hour service window closes in one hour. This turns the most common WhatsApp integration bug — sending into a closed window — into something you can build a workflow on
contact.consent_changed An opt-in or an opt-out was recorded
automation.run_finished A run reached a terminal state. Also run_failed
connection.disconnected The WhatsApp connection broke. Also needs_reauth
usage.threshold_reached 80% or 100% of a meter

Every delivery is signed and the node verifies it before your workflow sees an item, rejecting anything stale. The webhook is created, checked and deleted for you as you activate and deactivate the workflow — you never paste a URL anywhere.

The honest limitation. A self-hosted n8n behind NAT with no public URL cannot receive webhooks from anyone, us included. n8n Cloud and any tunnelled or reverse-proxied instance work as they are; for a locked-down one, point a Cosend outbound webhook at n8n's built-in Webhook node instead and use the action node for the sending half.

The action node

Five resources. The parameter descriptions are generated from the same schemas the API validates against, so a field cannot be named one thing in n8n and another on the API.

The action node’s resources, the operations on each, and what is worth knowing.
Resource Operations Worth knowing
Message Send · Get · Get Many · Mark as Read · React Send takes a message type sub-selector: text, media, template or interactive. Media comes from a binary field, a URL or a media ID.
Contact Create · Get · Get Many · Update · Upsert · Delete · Add Tags · Remove Tags Upsert looks up by phone number and then writes, so a workflow does not need an IF node in front of it.
Conversation Get · Get Many · Update · Set Control · Mark Read · Add Note There is no Create and no Close. A conversation exists because a message exists, and closing is Update with a state of resolved.
Automation Trigger · Get Many · Get Run · Get Run Events Get Run Events is the per-step trace, so a failing automation is debuggable from inside n8n.
Usage Get · Get Breakdown So a workflow can react to its own consumption — post to Slack when AI conversations pass 80% of what is included.

One dropdown value is deliberately missing. Conversation control can be set to bot, pending human or human — but not to app, which is the coexistence state meaning the owner is replying from their phone. That state is observed, never set, and offering it would be offering you a guaranteed error.

Credentials

One credential type, an API key, and the choice of which key is the interesting part:

  • An organization key for a workflow that touches several numbers.
  • A connection key when the workflow is about one number — because it cannot reach any other one. Least privilege, by default, without configuring anything.

The base URL is a credential field rather than a constant, so EU-residency and staging users can repoint the node. n8n bans environment variables inside a community node, and this is the supported way to make a host configurable.

Saving the credential runs a real request against our identity endpoint, which is guaranteed never to fail for authorization reasons if the credential resolves at all — so you get a green tick before you build anything.

How the node is built, and why that is on a marketing page

n8n's requirements for a community node are strict, public, and mostly invisible from the outside. They are here because they are also the reasons this node cannot quietly become a liability in your workflow:

Zero runtime dependencies
The package declares none. It speaks raw HTTP through n8n's own helpers rather than bundling a Cosend SDK, which means nothing arrives in your n8n instance except the node itself.
MIT, and the source is the published source
Releases carry npm provenance from a public GitHub Actions workflow, so the package on npm is attestably built from the commit it names — and anyone, including n8n's own scanner, can re-download that commit and check it.
Declarative, with two exceptions
Most of the node is JSON rather than code, which is what n8n recommends and what keeps the surface small. Two operations need more than one request — sending media from a binary field, and upserting a contact — and only those two are written as code.