Migration

Migrate from WAHA to ZapZap: migration guide (n8n included)

Migrating from WAHA to ZapZap swaps a container you maintain for a managed service. In code, the send address changes (from /api/sendText to /api/v1/{instanceId}/send/text), so do authentication (from X-Api-Key to x-api-key and x-api-secret) and the webhook format. The facts about WAHA come from its official documentation, read on 10/27/2026.

Published on · 4 min read

This article is also available in: Português · Español

What changes when you leave WAHA

WAHA is an unofficial HTTP API you run in Docker; the project site describes it as free and open source. You choose the connection engine (WEBJS, NOWEB, GOWS), the server and when to update. WAHA's own documentation warns that WhatsApp does not allow bots or unofficial clients and that this can lead to a ban.

On ZapZap, hosting, updates and monitoring are on us, billing is R$15 per active number per month and the risk to the number still exists, because it is also an unofficial solution. In return, you lose control of the server and the engine.

Endpoint mapping: WAHA to ZapZap

The WAHA column comes from the official documentation (waha.devlike.pro, 10/27/2026). WAHA uses session and a suffixed chatId (@c.us); ZapZap uses the instance ID in the URL and the number with digits only.

ActionWAHAZapZap
AuthenticationX-Api-Key headerx-api-key and x-api-secret
Send textPOST /api/sendText with session, chatId (for example 5511999999999@c.us) and textPOST /api/v1/{instanceId}/send/text with number (5511999999999) and text
Send fileendpoints per media typePOST /api/v1/{instanceId}/send/media with type, file, text and docName
Sessionsession (for example default)instance, with its own ID
Receive a messagemessage event with payload.from, payload.body, payload.fromMemessages event with data.message.chatid, data.message.text, data.message.fromMe
Connectsession QR codeQR code in instance QR

How to swap the WAHA node in n8n

If your flow uses the WAHA node or an HTTP Request pointing at WAHA, the swap is direct. Install the community node n8n-nodes-zapzap in Settings, Community Nodes (unverified community nodes only work on self-hosted n8n, according to n8n's documentation) or use an HTTP Request with the x-api-key and x-api-secret headers. Step by step on the n8n integration page.

On the receiving trigger, replace WAHA's Webhook with n8n's Webhook using the production URL (not the test one) and set that URL in configure webhook. In the following nodes, adjust the expressions: where you had payload.from and payload.body, use data.message.chatid and data.message.text. The 12 n8n templates already come in ZapZap's format.

n8n: Code node para normalizar o evento

// Entrada: evento da ZapZap. Saída: o formato que seus nós já esperavam do WAHA.
const e = $input.first().json.body ?? $input.first().json;
const m = e?.data?.message;
if (e?.event !== "messages" || !m || m.fromMe) return [];
return [{
  json: {
    payload: {
      from: String(m.chatid || "").replace(/\D/g, "") + "@c.us",
      body: m.text || "",
      fromMe: false,
    },
  },
}];

How to change sending in code

Sending is a swap of URL, headers and fields: session and the chatId with @c.us become the instance ID in the URL and a digits-only number. Isolate sending in one function and change its contents.

Node.js

// ANTES: WAHA
// POST {WAHA_URL}/api/sendText   header: X-Api-Key
// body: { session: "default", chatId: "5511999999999@c.us", text: "Olá!" }

// DEPOIS: ZapZap
export async function enviarWhatsApp(numero, texto) {
  const r = await fetch(
    "https://api.zapzapapi.com/api/v1/" + process.env.ZAPZAP_INSTANCE_ID + "/send/text",
    {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "x-api-key": process.env.ZAPZAP_API_KEY,
        "x-api-secret": process.env.ZAPZAP_API_SECRET,
      },
      body: JSON.stringify({ number: numero.replace(/@.*/, ""), text: texto }),
      signal: AbortSignal.timeout(15000),
    }
  );
  if (!r.ok) throw new Error("ZapZap " + r.status + " " + (await r.text()));
  return r.json();
}

Cutover checklist and when to stay on WAHA

Checklist: 1) create the account and test with a number of your own; 2) swap the send function or the n8n node; 3) point the webhook and validate the signature (guide); 4) export whatever you want to keep from WAHA; 5) connect the production number by QR code at cutover, without keeping it active on both; 6) shut the old container down after a few stable days.

Stay on WAHA if you have DevOps, want the code and data inside your environment and prefer to pick the connection engine. See the WAHA vs ZapZap comparison and the cost math in hosted Evolution and WAHA vs managed. If you need a channel sanctioned by Meta, the option is the official API.

Quick summary

  • In code, the URL, authentication and webhook format change; session and chatId become instance and number.
  • In n8n, swap the node and adjust the payload.from and payload.body expressions to data.message.
  • Both are unofficial: the ban risk to the number exists on both sides.
  • Use n8n's production webhook URL, not the test one.

Also read

Frequently asked questions

Do my WAHA n8n templates work on ZapZap?

With adjustments. Swap the send node and the incoming-event expressions (payload.from and payload.body become data.message.chatid and data.message.text). ZapZap's templates come ready.

Does WAHA Plus change anything?

According to the WAHA documentation read on 10/27/2026, features that used to be WAHA Plus became part of Core since version 2026.6.1. Recheck the documentation, because this may change.

Do I need to keep the WAHA server?

Only during the transition. After a few stable days on ZapZap you can shut the container down. Export what you want to keep first.

Does ZapZap guarantee the number will not be banned?

No. No unofficial API can guarantee that. Automatic delay and typing reduce the risk, but opt-in, pace and a clean list remain on you.

Try ZapZap with your flow

Create the account, connect a test number and swap the node. R$15 per active number per month, no per-message fee.