Migration

Migrate from Z-API to ZapZap: endpoint mapping and step by step

Migrating from Z-API to ZapZap is, in practice, swapping the send URL, the authentication headers and the webhook reader, and reconnecting the number by QR code. Both services are unofficial WhatsApp APIs, so the risk to the number is of the same kind on both sides. The facts about Z-API come from its documentation and site, read on 10/27/2026; recheck before migrating, because it may change.

Published on · 5 min read

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

What changes and what stays the same

Stays the same: you connect a WhatsApp number by QR code and use an HTTP API with JSON to send and a webhook to receive. Both are unofficial solutions with no Meta badge, and on both the number can be limited or banned if use is abusive.

Changes: authentication (Z-API uses the Client-Token header; ZapZap uses x-api-key and x-api-secret), field names (phone and message on Z-API; number and text on ZapZap), the webhook format and the pricing model. According to the Z-API site on 10/27/2026, the Ultimate plan costs R$99.99 per instance per month and Partner, for 10 or more instances, R$89.99. ZapZap charges R$15 per active number per month, with no per-message fee. The plans have different features, so compare what you actually use before deciding.

Endpoint mapping: Z-API to ZapZap

The table covers what almost every project uses. For the rest, the ZapZap reference lists every endpoint. The Z-API column comes from its documentation (developer.z-api.io, 10/27/2026); where the page did not carry the data, the cell says to check.

ActionZ-APIZapZap
AuthenticationClient-Token header (account token, enabled in the panel); instanceId and instance token on the callx-api-key and x-api-secret headers; the instance ID in the URL
Send textfields phone and message (optional delayMessage and delayTyping); response with zaapId and messageIdPOST /api/v1/{instanceId}/send/text with number and text (optional delay and digitando); response with messageId and status
Send fileendpoints per media typePOST /api/v1/{instanceId}/send/media with type, file, text and docName
Check if a number has WhatsAppcheck Z-API's documentationPOST /api/v1/{instanceId}/chat/check with numbers
Receive a messageincoming-message webhook URL (HTTPS only)PUT /api/v1/instances/{id}/webhook, messages event
Instance statuscheck Z-API's documentationGET /api/v1/{instanceId}/instance/status

On each row, read the Send Text, Send Media and Check Number references before switching.

How to change sending: before and after

The send change is mechanical. Swap the URL, remove the Client-Token, add the two ZapZap headers and rename the fields. The number keeps country code and digits only.

Create a thin function in your code (sendWhatsApp(number, text)) and change only what is inside it. That keeps the migration in one place, and going back too.

Antes (Z-API) e depois (ZapZap), em Node.js

// ANTES: Z-API (confira a URL e o corpo na documentação da Z-API)
// headers: { "Client-Token": process.env.ZAPI_CLIENT_TOKEN }
// body:    { phone: "5511999999999", message: "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, text: texto }),
      signal: AbortSignal.timeout(15000),
    }
  );
  if (!r.ok) throw new Error("ZapZap " + r.status + " " + (await r.text()));
  return r.json(); // { messageId, status }
}

How to change the receiving webhook

On Z-API, an incoming message arrives with top-level fields such as phone, fromMe, messageId, instanceId and text.message (callback documentation, 10/27/2026). On ZapZap, the event comes in an envelope: event, data.message.text, data.message.chatid and data.message.fromMe, plus delivery_id and instance_id.

Write an adapter that converts the ZapZap event into the internal format your system already understands. Then the rest of the code does not change. Set the URL in configure webhook, turn on only the messages event and validate the signature as described in the webhooks in production guide.

Adaptador em Node.js

// Converte o evento da ZapZap para o formato que o seu sistema já usa
export function deZapZap(evento) {
  const m = evento?.data?.message;
  if (evento?.event !== "messages" || !m || m.fromMe) return null;
  return {
    telefone: String(m.chatid || "").replace(/\D/g, ""),
    texto: m.text || "",
    idMensagem: evento.event_id || evento.delivery_id,
  };
}

How to move the number and a cutover checklist

The number is yours: in ZapZap you create an instance (Create Instance) and connect the same number by QR code. Conversation history from the other service is not migrated through an API; save what you need before. The same number should not be active on both services at once, so plan a short switching window, preferably off-peak.

Checklist: 1) create the account and the instance; 2) test send and receive with a number of your own; 3) swap the send function; 4) point the webhook and validate the signature; 5) cut over at a calm hour; 6) disconnect the old instance only after confirming the new flow; 7) watch the first hours in the logs and in webhook deliveries.

When not to migrate

Z-API has extensive documentation, local support and, according to its site, an Ultimate plan with no message limit and no per-message cost. If your use depends on a specific feature of theirs that ZapZap lacks, or if the operation is stable and the cost makes sense, migrating may not be worth the effort. If you need a channel sanctioned by Meta, neither fits: the option is the official API. The Z-API vs ZapZap comparison details price and limits with source and date.

Quick summary

  • The migration swaps the send URL, headers, field names and the webhook reader.
  • Both services are unofficial: the risk to the number is of the same kind.
  • Isolate sending in one function and the webhook in one adapter to migrate (and roll back) in a single place.
  • Conversation history does not migrate through an API; do not keep the same number active on both at once.

Also read

Frequently asked questions

Do I lose message history when migrating?

History from the old service is not transferred through an API. Export what you need before disconnecting the number.

Can I use the same number on both services during the test?

Avoid it. Use a test number on ZapZap to validate the flow and only reconnect the production number at cutover.

How much does migrating cost?

There is no migration fee. You pay for the active number on ZapZap (R$15 a month) and the one-time activation fee described on /precos. The real cost is the time to swap sending and the webhook.

Is ZapZap safer against bans than Z-API?

We cannot promise that. Both are unofficial and the number can be limited or banned on either. ZapZap offers features that reduce risk, such as automatic delay and typing, but opt-in, pace and a clean list stay on you.

Try ZapZap before migrating

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