Description
n8n-nodes-easyhook
Easyhook integration for n8n.
Easyhook is a lightweight multichannel messaging and reviews API for WhatsApp, Telegram, TikTok Business Messaging,
Gmail, Outlook, generic IMAP/SMTP email, Mercado Libre, and Google Business Profile. This node focuses on the workflows
developers normally automate:
Message Actiongroups cross-channel text and media actions. Use Send Buttons for standardized reply buttons on WhatsApp, Messenger, Instagram, Telegram, and TikTok Business Messaging. Use Send Quick Replies when Messenger or Instagram needs more than three text choices.Message Controlgroups read, typing, reply, and reaction actions and onlyEmail Onlyworks consistently with Gmail, Outlook, and IMAP/SMTP: send,Commentlists public Facebook Page and Instagram professional-accountOnboardingcreates or sends hosted connection links for any supported channel.WhatsApp Onlygroups WhatsApp sends, templates, Flows, and consent.Reviewlists Google reviews, returns the aggregate location rating, and publishes business replies.Templatelists, synchronizes, checks categories, creates, and deletes templates.- Use standard or humanized delivery on WhatsApp, Messenger, Instagram, Telegram, and TikTok Business Messaging.
- Schedule supported WhatsApp, Messenger, Instagram, Telegram, Mercado Libre, and TikTok Business Messaging messages.
- Upload organization-wide reusable media and send it later by
media_name. - Download protected incoming media into an n8n binary field.
- For TikTok webhooks, keep
contact.idas the stable recipient and - List/sync templates and media
- Cancel scheduled messages before processing begins
- Receive Easyhook webhook events in n8n with the Easyhook Trigger node
lists channels that support the selected operation.
reply, forward, read/unread, archive, and create/edit/send drafts.
comments and publishes public replies without treating them as private messages.
message.thread_id as the provider conversation. Easyhook accepts either
value as to and resolves the TikTok thread internally.
For Mercado Libre, use the same Send Text operation. Select the connected
seller as From and map To from an incoming trigger item:
question: answers a product question and pack: replies in a
post-sale conversation. Mercado Libre does not permit arbitrary new
conversations, so the destination must come from a previous event.
Install
In n8n, open Settings > Community Nodes and install:
n8n-nodes-easyhook
For self-hosted n8n, you can also install it manually in your n8n custom nodes folder.
Credentials
Create an Easyhook API credential:
ehlive... key from Easyhookn8n validates the credential with GET /v1/me, so no WhatsApp number is needed just to test the API key.
Common Examples
Receive Webhooks
Use Easyhook Trigger as the first node in a workflow.
1. Add the Easyhook Trigger node.
2. Select your Easyhook API credential.
3. Choose a provider. Easyhook filters the available events and scope types automatically.
4. Choose a scope. For WABAs, WhatsApp numbers, Messenger Pages, or Instagram accounts, select a connected account from the list loaded with your API credential.
5. Activate the workflow.
Public comments require their own connection and provider. Choose **Facebook
Comments or Instagram Comments*, then subscribe to comment.. Messenger
and Instagram providers remain limited to private messages. Comment events
include comment.post.id and may include publication context under
interaction.object.
n8n registers its Production URL in Easyhook automatically and stores the HMAC signing secret in the workflow’s private static data. Deactivating or deleting the workflow removes the Easyhook subscription. No portal setup or secret copy/paste is required.
WhatsApp uses the same three levels as the Easyhook portal: Entire Organization → WABA → WhatsApp Number. Selecting a WABA receives matching events from all numbers connected to it. Meta Business Portfolios stay internal and never appear as n8n scopes.
The trigger outputs the normalized Easyhook webhook JSON directly.
For Google Business Profile, choose provider Google Business Profile and
subscribe to review.created and/or review.updated. Map review.id when a
later node needs to reply to that review.
Manage Google Reviews
ReviewList Reviews, Get Rating, or Reply to ReviewList Reviews returns normalized reviews and nextpagetoken. Get Rating
returns the aggregate rating and total review count. To respond publicly,
choose Reply to Review, map review.id from the trigger or list result, and
enter the reply. Google may update an existing reply when the same review is
answered again.
Send Text
Message ActionSend Text5215660069997Hello from n8nThe channel selector stores the same provider-native value delivered as
account.id by the Easyhook Trigger. WhatsApp uses the Meta Phone Number ID;
Messenger uses the Page ID; Instagram uses the Instagram account ID; and
Telegram uses its connected account ID. Legacy page and ig aliases remain
accepted by the API, but new workflows do not need prefixes.
Choose Delivery: Humanized to apply the supported read, pause, and typing
behavior before sending through WhatsApp, Messenger, Instagram, or Telegram.
Send Messenger Or Instagram Quick Replies
Message ActionSend Quick Repliescontact.idThe title is visible and accepts up to 20 characters. The payload is returned
unchanged in message.quick_reply.payload; use it to route the workflow.
For scheduled text, media, or templates, add:
Schedule At: ISO 8601 execution timeOptions > Client Reference: optional identifier from your applicationOptions > Idempotency Key: optional stable key used only when retrying the same scheduled sendUse resource Cancel Scheduled Message to cancel a pending delivery before processing begins.
Send Email
Email OnlySend EmailTo answer an existing email, choose Reply to Email instead. Map the inbound
Easyhook Trigger value message.id into Original Email ID. Easyhook resolves
the Gmail thread, Outlook reply, or IMAP headers automatically. You do not need
to configure Thread ID, In-Reply-To, or References in n8n.
All email providers use POST /v1/messages/email and return the same normalized
response. Treat inbound message.html as untrusted content.
Add files under Attachments by selecting an input binary field. Easyhook
uses its file name and MIME type automatically. Use Forward Email with the
trigger’s message.id; use Update Email to mark that ID read, unread, or
archived. Draft operations return a Draft ID that can later be edited or sent.
Send Read, Typing, Or Reaction
Message ControlMark as Read, Show Typing, React, or Replymessage.id from Easyhook TriggerThe channel list is filtered by capability. WhatsApp supports all four
operations. Messenger and Instagram support read, typing, and reply. Telegram
supports typing, reply, and reaction. Unsupported combinations are rejected
explicitly without charging the wallet.
For a reaction, also set To and Reaction. Leave the reaction empty to remove
it. For a contextual reply, map the original message.id, recipient, and reply
text.
Send Reusable Media
First upload media:
MediaUploadpromo_imageImageBinary PropertydataReusable media belongs to the Easyhook organization, not to one WABA or channel.
The same media_name can be used by supported WhatsApp, Messenger, Instagram,
and Telegram senders in that organization.
Then send it:
Message ActionSend MediaImageReusable Media Namepromo_imageTo read protected incoming media, map message.media.url from Easyhook Trigger
into Media → Download → Media URL. The node authenticates with the Easyhook
credential and returns the file in the selected binary field. Do not use a
generic HTTP Request node without the API key: protected URLs intentionally
return an authorization error.
Send Template
WhatsApp OnlySend TemplateEnter ManuallyesMX or enUSMap Automatically to load the template definition by name and language, or Custom Components (JSON) to provide raw components.Both template sources support the same data modes. Choose From Easyhook selects an approved template from a list; Enter Manually resolves the approved template using the typed name and selected language. Map Automatically then creates only the fields required at send time:
Use Custom Components (JSON) when you need to provide raw Meta components. The value can be a components array or { "components": [...] }. Template text itself remains fixed by the approved Meta template.
Text header, body variables, and dynamic URL button:
[
{
"type": "header",
"parameters": [{ "type": "text", "text": "PED-1048" }]
},
{
"type": "body",
"parameters": [
{ "type": "text", "text": "Benjamin" },
{ "type": "text", "text": "15 July" }
]
},
{
"type": "button",
"sub_type": "url",
"index": "0",
"parameters": [{ "type": "text", "text": "PED-1048" }]
}
]
Media header and named body variable:
{
"components": [
{
"type": "header",
"parameters": [
{
"type": "document",
"document": {
"link": "https://cdn.example.com/invoice.pdf",
"filename": "invoice.pdf"
}
}
]
},
{
"type": "body",
"parameters": [
{
"type": "text",
"parametername": "customername",
"text": "Benjamin"
}
]
}
]
}
Media links must use HTTPS and be downloadable by Meta without authentication. A dynamic URL button value is the variable suffix, not the complete URL. Use [] when the template has no runtime components.
Send WhatsApp Flow
WhatsApp OnlySend FlowSend Consent
WhatsApp OnlySend Opt-In or Opt-OutOpt-In or Opt-OutTo store consent collected on a website, CRM, or external form, use
Record Opt-In or Opt-Out instead. Select the marketing or service scope and
provide auditable Evidence JSON, for example:
{
"form_id": "lead-form-v3",
"accepted_at": "2026-07-29T18:00:00.000Z",
"source_url": "https://example.com/contact"
}
Easyhook records this evidence but does not manufacture consent. The Easyhook
customer remains responsible for collecting valid permission and honoring
opt-outs.
Use Get Consent Status with the same sender and contact to read the current
service and marketing states. Each scope returns optin, optout,
pendingoptout, or unknown; unknown is not permission.
Voice AI Calls
Use Voice Call > Record Consent before any automated outreach. Select the
Easyhook number, destination, opt-in or opt-out state, capture time, source,
and auditable Evidence JSON. Easyhook stores the customer’s evidence but does
not manufacture consent.
Use Voice Call > Start AI Call with the same number and destination after a
distinct outbound ElevenLabs agent has been assigned in the Easyhook portal.
Set a maximum duration, optional scalar Context JSON, and a stable Idempotency
Key. Easyhook enforces consent, frequency limits, number ownership, provider
capabilities, wallet reservation, and settlement. Get Call and Hang Up
operate on the returned Easyhook call ID.
Hosted Onboarding
OnboardingGet Onboarding URL or Send Onboarding LinkOutlook, IMAP/SMTP, or Mercado Libre
WhatsApp Coexistence or WhatsApp Business API when theprovider is WhatsApp
Spanish or EnglishGet Onboarding URL returns the hosted URL without sending a message. Send Onboarding Link creates the same session and sends its URL from the selected Easyhook WhatsApp number to To. Subscribe with Easyhook Trigger to onboarding events when the workflow must continue after the customer connects a number.
Hosted links expire after one hour and are consumed after a successful connection. The sent message is
localized by Easyhook and always includes the hosted URL.
Webhook Automation
Easyhook webhooks are handled with Easyhook Trigger. It is not a polling node: activation creates a /v1/webhooks subscription for the n8n Production URL and deactivation removes it. Deliveries are authenticated automatically with X-Easyhook-Signature: sha256=.
The trigger starts with no provider or event selected. Choose one provider and
at least one compatible event. The option names and values match the Easyhook
portal; All events must be selected alone.
Useful event scopes:
message.*: incoming messages from the selected provider, includingWhatsApp, Messenger, Instagram, Telegram, TikTok Business Messaging, Gmail, Outlook, and IMAP/SMTP
status.*: message delivery/read/failure statustemplate.*: template status changesflow.submission.*: WhatsApp Flow responsessmbmessageecho.*: WhatsApp Business App coexistence message echoessmbappstate_sync.*: WhatsApp Business App coexistence contact/app state synchistory.*: coexistence history sync eventsaccount_update.*: WhatsApp account updatesmedia.*: media lifecycle events, when enabled in Easyhookmessage.text, message.image, status.failed: narrower event filters matching the Easyhook portalMessenger and Instagram hooks use the same event values with a separate
provider filter. Do not add provider prefixes to event names.
Receive Coexistence History
Configure the Easyhook Trigger before connecting the WhatsApp Business App number or requesting coexistence sync:
1. Select Provider: WhatsApp.
2. Select Event: Coexistence history (history.*).
3. Choose the organization, WABA, or WhatsApp number scope.
4. Activate the workflow.
5. Allow history sharing in the WhatsApp Business App and keep the app open while synchronization starts.
Easyhook creates the webhook subscription and stores its HMAC secret in n8n automatically. Do not create a second portal webhook. message.* only covers live messages; it does not include history imports.
Easyhook delivers History and App State in signed batches of at most 100 events. One batch starts one workflow execution, and the trigger expands every normalized event into a separate n8n item. This keeps large imports fast without creating one execution per historical message. Historical inbound messages use type: message.received; historical outbound messages use type: message.echo. Both include message.source: history, and every item includes _sync with its batch and progress metadata:
{
"id": "event_uuid",
"type": "message.echo",
"channel": "whatsapp",
"account": { "id": "980912725115744", "phone": "5218661479075" },
"contact": { "id": "5214445087305" },
"message": {
"id": "wamid...",
"direction": "out",
"source": "history",
"type": "text",
"text": "Previous reply",
"history": {
"thread_id": "5214445087305",
"status": "READ",
"phase": 1,
"chunk_order": 2,
"progress": 80
}
},
"_sync": {
"batchid": "deliveryuuid",
"source": "history",
"progress": 80,
"count": 100
}
}
Use message.id for idempotency because deliveries are at-least-once. Keep live auto-replies disabled when message.source is history. Media does not block the import: a historical message can first include message.media.storagestatus: pending, followed later by type: message.mediaavailable with the same message.id and a protected download URL.
The same history. trigger receives sync.started, sync.progress, sync.completed, and sync.failed lifecycle items. Wait for sync.completed instead of inferring completion from Meta’s progress value. App State contact records are delivered under smbappstate_sync.; they can arrive before or after History, so use contact.id and message.id rather than array position to join and deduplicate records.
History covers up to approximately 180 days and excludes group conversations. Historical media availability is normally limited to recent messages (approximately 14 days). Easyhook offers three import policies in the portal: messages only, recent media without video, and recent media including video. Missing or expired media never fails the message import.
Only one synchronization runs per WhatsApp number. An organization may have any number of connected numbers, with up to two numbers importing concurrently for fair capacity sharing. Failed webhook deliveries retry five times and can be replayed without changing the original message IDs or idempotency keys.
If the business disables history sharing, Meta can return error 2593109; the trigger receives it as type: sync.failed under the same history.* selection.
Development
npm ci
npm run lint
npm run typecheck
npm run build
npm pack --dry-run
Releases are published from GitHub Actions with npm provenance. See CONTRIBUTING.md for the validation and release workflow.