Send WhatsApp messages from n8n with an HTTP Request node

Build an n8n workflow that sends WhatsApp order updates and sign-in codes through a REST API, with a test key, idempotent retries and a webhook for delivery status and replies.

October 15, 2026 · 6 min read

If you automate with n8n, WhatsApp is usually the step you put off: Meta's developer setup, template approval, then the API calls. The calls themselves are small. This guide builds a workflow that sends a WhatsApp template message from n8n with one HTTP Request node, then closes the loop with a Webhook node for delivery status and replies.

SendFromChat doesn't have a dedicated n8n node, so this uses n8n's generic nodes against the REST API. SendFromChat is an independent product and is not affiliated with Meta, WhatsApp or n8n. It runs on Meta's official WhatsApp Cloud API; you keep your own WhatsApp Business account. Node names and menus in n8n change between versions, so treat the labels below as a guide.

What you need first

  • A SendFromChat account (30-day free trial, no card) with a WhatsApp number connected. Connecting takes about two minutes with Continue with Facebook (getting started).
  • One approved template for the message you want to send. Messages you start outside a 24-hour conversation window must use one (how the window works). An order update is a Utility template, for example: Hi {{1}}, your order {{2}} has shipped. Track it here: {{3}} (approval rules).
  • Customers who agreed to WhatsApp updates (how to collect opt-in).

Step 1: a test key, stored as an n8n credential

On the dashboard's Developers page, create a test key (sfc_test_…). It runs every check a real send would (plan, opt-outs, template, 24-hour window), then stops: nothing is sent, saved or counted. Build the whole workflow with it, then swap in a live key (sfc_live_…).

In n8n, create a Header Auth credential:

  • Name: Authorization
  • Value: Bearer sfc_test_…

Keeping the key in a credential means it isn't pasted into node fields or exported with the workflow JSON.

Step 2: the HTTP Request node

Add an HTTP Request node after whatever triggers your workflow (a new order in your shop, a row in a sheet, a form submission). Set:

  • Method: POST
  • URL: https://sendfromchat.com/api/v1/messages
  • Authentication: Generic credential type, Header Auth, the credential from step 1
  • Send Headers: add Idempotency-Key with an expression such as order-{{ $json.orderId }}-shipped
  • Send Body: JSON
{
  "to": "{{ $json.phone }}",
  "template": {
    "name": "order_shipped",
    "language": "en_US",
    "variables": ["{{ $json.firstName }}", "#{{ $json.orderNumber }}", "{{ $json.trackingUrl }}"]
  }
}

Enter the body as an expression so each {{ … }} is filled from the incoming item. to must be in international format with the country code, for example +491512345678.

Run the node. With a test key you get 200 and "status": "test". With a live key you get 202 and "status": "accepted", which means Meta took the message, not that the customer has read it.

Why the idempotency key matters in n8n

n8n workflows get re-run: you retry a failed execution, a trigger fires twice, or a node's retry-on-fail setting kicks in. If the Idempotency-Key comes from the event (order-4821-shipped) and not from the execution, a repeat returns the first response with Idempotent-Replayed: true instead of sending a second message. Reusing a key with a different body returns idempotency_mismatch.

Step 3: handle the refusals

Some errors are WhatsApp's rules, not bugs, and retrying won't fix them. In the HTTP Request node, turn on the option to continue on error (or output the error response), then add an IF node on {{ $json.error.type }}:

error.type What it means What to do
opted_out The customer replied STOP Stop; don't retry
window_closed Free-form text was sent outside the 24-hour window Send a template instead
template_not_approved The template isn't approved yet Wait, or fix the template
warmup_limit A new number reached today's cap (50, then 100, then 200 a day) Retry later
sending_paused Trial ended or plan limit reached Check the plan

The full list is in the REST API reference.

Step 4: delivery status and replies with a Webhook node

For what happens after the send, add a second workflow that starts with a Webhook node (method POST). Copy its production URL, then on the Developers page add it as a webhook endpoint and subscribe to:

  • message.status: sent, delivered, read, or failed with a reason
  • message.received: the customer replied (with their text and phone number)
  • contact.opted_out: someone replied STOP, so you can remove them from your own lists too

Three things to get right:

  1. Answer fast. Your endpoint must return a 2xx within 5 seconds. Respond immediately and do the slow work after.
  2. Skip repeats. Deliveries can repeat, so keep the event id (evt_…) of what you've handled, for example in a data table or a sheet, and ignore duplicates.
  3. Verify the signature. Each request carries SendFromChat-Signature: t=…,v1=…, an HMAC-SHA256 of <t>.<raw body> keyed with the endpoint secret. In n8n you need the raw body (the Webhook node has a Raw Body option) and a Code node using the crypto module, which a self-hosted n8n may need to be configured to allow. The REST API reference has the verification function and the payloads. If you can't verify in your setup, don't let unverified events trigger anything sensitive.

A reply path that fits n8n

With message.received flowing into a workflow, you can route replies: create a task in your tracker, post to your team chat, or look up the order and answer. When a customer writes in, a 24-hour window opens and you can answer with free-form text via POST /messages with { "to": "…", "text": "…" }, no template needed. Replies, auto-replies and chatbot messages are free and unlimited on every plan; only messages you start count toward the monthly allowance (plans and limits). For the common questions, a chatbot flow can answer and hand over to a person without any workflow.

Costs, in plain terms

Two separate things: SendFromChat's flat monthly plan (from $19, with 5,000 messages a month that you start on Starter), and Meta's per-message charge, which Meta bills to your own WhatsApp Business account at its published rates, with no markup from us. Rates depend on the message category and the recipient's country; see WhatsApp API pricing.

A note for EU and UK customers

SendFromChat stores data in Mumbai, India. Transfers from the EU and UK are covered by the Standard Contractual Clauses and the UK Addendum in our Data Processing Agreement, and the sub-processors are listed publicly. Read it before you decide; our GDPR guide covers consent, opt-out and records on your side.

Prefer to ask instead of build?

The same account works from Claude, ChatGPT and Claude Code, so an assistant can draft the template or send a one-off message while the n8n workflow handles the repeatable events (connect your assistant, WhatsApp MCP server for editors and terminals). Building the same thing in code instead? See WhatsApp order notifications from your app.

Try it

Start the 30-day free trial (no card), connect a number, create a test key and run the HTTP Request node above. If you're weighing other routes, see SendFromChat vs Twilio and using Meta's Cloud API directly.

Do this from your AI assistant

SendFromChat connects Claude, ChatGPT, Cursor or any MCP client to the WhatsApp Business API — templates, bulk sends, inbox, chatbots and sequences, just by asking. 30 days free, no card.

Start free