Recipe · n8n, Node-RED & Make

Human approval in your n8n flow: no Twilio, no WABA.

Your flow reaches the step that spends money, deletes records or emails a customer, and you want a human to say yes first. n8n's native WhatsApp node wants Meta or Twilio credentials, business verification and template approval before it sends anything. pingwa is the n8n-nodes-pingwa community node and one click: connect, drop in the Pingwa node, your phone buzzes with buttons, the flow waits for your tap. On Make or Node-RED (or without the node), one HTTP request to /v1/ask does the same.

Native WhatsApp Business node

  • Create a Meta developer app
  • Get a WhatsApp Business Account (WABA)
  • Pass business verification
  • Get message templates approved
  • Or route it all through Twilio
Setup: days

pingwa

  • Install n8n-nodes-pingwa
  • Connect with one click
  • Drop in the Pingwa node
Setup: 60 seconds

Honest note: if you already run a WABA and message customers, the native node is the right choice. That's what it's for. pingwa is for the other case: the flow asking you, its operator, for a decision.

§ 1

The n8n community node

On n8n, skip the HTTP plumbing: n8n-nodes-pingwa is the official community node, live on npm. It adds a Pingwa node that sends a WhatsApp message or, as the human-in-the-loop step, asks a question and holds the workflow until you answer (approve or reject), plus Pingwa Trigger and Pingwa Poll Trigger to start a workflow on an inbound WhatsApp message.

install
Where
n8n → Settings → Community Nodes → Install
Package
n8n-nodes-pingwa
Result
Pingwa, Pingwa Trigger and Pingwa Poll Trigger appear in the node panel
connect: one click
1
Add a Pingwa OAuth2 API credential and click Connect: a pingwa tab opens
2
Continue with Google, or connect a number directly
3
Pick which WhatsApp number n8n uses, or add a new one
4
New number only: tap Open WhatsApp & verify and send the pre-filled message (or scan the QR from another phone). pingwa spots it and continues on its own
5
The tab closes; n8n stores the token and reuses it from then on

Picking a number that's already verified skips step 4: you go straight back to n8n. Prefer a key? Add a Pingwa API credential instead and paste your pw_ key.

§ 2

Without the node, or for Make & Node-RED

Everything above is also one plain HTTP call: the only route on Make and Node-RED, and fine on n8n if you'd rather not install a community node. Two importable n8n templates wrap the core (HTTP Request to /v1/ask → IF on the button reply) inside a complete, runnable workflow with the approve, reject and no-answer paths all wired. Pick by how your flow starts:

a · outbound-only: no public URL
Download
pingwa-ask.n8n.json
Shape
Schedule → Set → Ask on WhatsApp → IF → run action · WhatsApp receipt on reject/timeout
For
a scheduled or manual flow that reaches a risky step. The reply returns on the same outbound call, so a self-hosted n8n behind NAT needs no webhook, no public URL, no tunnel.
b · webhook: an incoming request triggers it
Download
pingwa-webhook-approval.n8n.json
Shape
Webhook → Set → Ask on WhatsApp → IF → run action → Respond to Webhook (approved / rejected / timeout)
For
an external system (Stripe, your app, a form) that POSTs an event and gets the decision back. Only the trigger needs a public URL (the caller's requirement, not pingwa's); the WhatsApp reply is still outbound-only.
import & key (both)
Import
n8n → Workflows → ⋯ → Import from File
Key
set PINGWA_KEY as an environment variable on the n8n host. On n8n Cloud, $env is blocked in expressions (it fails with an opaque “access denied” error). Create a Header Auth credential there instead (name Authorization, value Bearer pw_...) and attach it to the pingwa HTTP node(s).

The Ask on WhatsApp HTTP Request node, the heart of both templates, spelled out:

http request node: settings
Method
POST
URL
https://pingwa.dev/v1/ask
Header
Authorization: =Bearer {{ $env.PINGWA_KEY }} (the leading = is workflow-export notation: in the UI you toggle the value field to Expression and type the rest)
Body (JSON)
{"text": "Approve this step?", "buttons": ["approve", "reject"], "timeout": 90}
Timeout
95000 ms: a hair over the 90 s the API will hold the question open

timeout: 90 in the body is the maximum the API accepts; the node's own 95 s timeout just makes sure n8n outlasts the long-poll instead of cutting it off. Put anything you like in text: an n8n expression interpolating the item being approved works fine.

§ 3

Branch on the answer

A successful response looks like this. button_id is positional: b0 is the first button you passed, b1 the second.

200 response from /v1/ask
{
  "message_id": 123,
  "billing_class": "template",
  "answered": true,
  "reply": {"answer_id": 124, "text": "approve", "button_id": "b0",
            "created_at": "2026-07-16T14:03:07Z"}
}

So the IF node's condition is a plain string-equals: left value {{ $json.reply.button_id }}, right value b0. True branch = approved, false branch = rejected.

If the ask lands outside your 24h reply window (likely, for approvals that arrive out of the blue), the buttons arrive as a numbered list instead of tap buttons. Replying 1 (or the button's text, approve) works the same and still maps to b0.

If nobody answers within the 90 seconds, /v1/ask returns HTTP 408 and the HTTP Request node errors. Treat that as a reject: silence should never approve anything. Wire the node's error output to the same path as the false branch (enable “Settings → On Error → Continue (using error output)”). The question was still delivered to your phone; a late tap is retrievable afterwards via GET /v1/messages/<id>/reply if your flow wants a second look.

§ 4

Node-RED variant

Same shape: a function node prepares the request, an http request node (set to POST, “return a parsed JSON object”) makes the call, and a second function (or switch) node branches on the button.

function node → http request node
// function node BEFORE the http request node
msg.url = "https://pingwa.dev/v1/ask";
msg.method = "POST";
msg.headers = {
  "Authorization": "Bearer " + env.get("PINGWA_KEY"),
  "Content-Type": "application/json"
};
msg.payload = {text: "Approve this step?", buttons: ["approve", "reject"], timeout: 90};
return msg;
function node AFTER the http request node
// output 1 = approved, output 2 = rejected (set the node to 2 outputs)
if (msg.statusCode === 200 && msg.payload.reply.button_id === "b0") {
  return [msg, null];
}
return [null, msg];  // includes the 408 nobody-answered case → fail-safe reject
§ 5

Make.com

In Make, it's the generic HTTP module (“Make a request”): POST the same JSON to /v1/ask with the same Authorization: Bearer header, then add a Router with a filter on reply.button_id equals b0 for the approved route and a fallback route for everything else: rejections and timeouts alike.

§ 6

FAQ

How do I get an n8n WhatsApp approval without Twilio?

Install the n8n-nodes-pingwa community node (Settings → Community Nodes), connect with one click, and use the Pingwa node's Ask operation, or POST to https://pingwa.dev/v1/ask with a plain HTTP Request node (template above, importable). pingwa carries the message over its own official Meta Cloud API number, so you never touch Twilio, a WABA or Meta credentials.

Does this work with n8n's send-and-wait?

It is the send-and-wait: POST /v1/ask long-polls, so the HTTP Request node itself holds the flow until the human answers (or 90 s pass). You don't need a separate Wait node, a webhook resume URL, or any special node type: the one HTTP call sends the question and returns with the answer.

What if nobody answers?

After 90 seconds /v1/ask returns HTTP 408 and the node errors. Route the error output to your rejected path: fail-safe means silence never approves. The question stays on the phone, and a late reply can still be fetched with GET /v1/messages/<id>/reply.

Does it work on self-hosted n8n?

Yes: this recipe is outbound-only HTTPS from your n8n host to https://pingwa.dev. No inbound webhook, no public URL, no tunnel needed: the reply comes back on the same long-polled request. A homelab n8n behind NAT works exactly like a cloud one.

QR code to join pingwa on WhatsApp

Scan the code and get instant access. It opens WhatsApp with “join” ready to send, and your API key comes straight back.

Approvals are exactly the messages you want rare and deliberate. The free plan's 30 paid messages a month cover a lot of “Approve this step?”. Your button-tap replies inside the 24h window are free.