Checklist for migrating from another WhatsApp API to ZapZap without losing history
Anyone already running on a WhatsApp API (Evolution, Z-API, WAHA or another) and wanting to migrate fears three things: downtime, losing history and breaking clients' systems. The good news is that, for a REST API with a webhook, migration is a change of address and format, done number by number. The conversation history in your system stays yours and does not migrate on its own: ZapZap does not import the previous API's database. ZapZap is an unofficial solution, like many of the alternatives mentioned, and WhatsApp may limit or block numbers on any of them.
Published on · 4 min read
Step 1: inventory before touching anything
List, per number: client, who uses it, daily volume, the integrations that call the API (CRM, n8n, chatbot), the current webhook address and the event format your system expects. Mark critical numbers and low-risk ones. The first to migrate is the lowest-risk one, not the biggest client.
Also inventory the history: what sits in your database (conversations, leads) and what exists only in the old API. Export what exists only there before cancelling anything. For a comparison of what each alternative delivers, see the comparisons.
Step 2: swap the HTTP client, not your system
Create a small layer in your code (a sendText function) and let the API swap happen only there. On ZapZap, sending text is POST https://api.zapzapapi.com/api/v1/{instanceId}/send/text, with number and text in the body and the x-api-key and x-api-secret headers. The reference and the OpenAPI file list the other endpoints (media, buttons, polls, groups), and there are SDKs for Node.js, Python and PHP.
Do the same for the webhook: an adapter that converts ZapZap's envelope to your system's internal format. Validate the signature and dedupe, as in the guide on idempotent webhooks.
The main calls of a migration
# 1) Inventory: list the instances already created on ZapZap
curl "https://api.zapzapapi.com/api/v1/instances" \
-H "x-api-key: $ZAPZAP_API_KEY" -H "x-api-secret: $ZAPZAP_API_SECRET"
# 2) Point the new webhook at your system and keep the old one running during the cutover
curl -X PUT "https://api.zapzapapi.com/api/v1/instances/INSTANCE_ID/webhook" \
-H "Content-Type: application/json" \
-H "x-api-key: $ZAPZAP_API_KEY" -H "x-api-secret: $ZAPZAP_API_SECRET" \
-d '{"webhook_url":"https://your-system.example/webhook","events":"messages,messages_update"}'
# 3) Optional: ask for older messages of ONE chat (they arrive through the webhook, not in the response)
curl -X POST "https://api.zapzapapi.com/api/v1/INSTANCE_ID/message/history-sync" \
-H "Content-Type: application/json" \
-H "x-api-key: $ZAPZAP_API_KEY" -H "x-api-secret: $ZAPZAP_API_SECRET" \
-d '{"number":"5511999999999@s.whatsapp.net","count":50}'
# 4) Switch the send call: same idea, new base URL and headers
curl -X POST "https://api.zapzapapi.com/api/v1/INSTANCE_ID/send/text" \
-H "Content-Type: application/json" \
-H "x-api-key: $ZAPZAP_API_KEY" -H "x-api-secret: $ZAPZAP_API_SECRET" \
-d '{"number":"5511999999999","text":"Test after migration"}'Step 3: connect the number and run both sides in parallel
Connecting the number on ZapZap means scanning a QR code, and that requires the device in hand: schedule the window with the client. Changing tools is a session change for the number, so avoid sending in the first hours and start with conversations from people who already talk to the client.
During the cutover, keep the old and the new webhook active for the same number only if your system dedupes. Test with the webhook test POST, send a test message and confirm that a real reply arrives.
Step 4: what to do with the history
The conversation history in your database is still there: nothing needs to migrate. What the old API kept and your system did not, you export through it. On ZapZap's side there is POST /{instanceId}/message/history-sync, which requests the sync of older messages of a chat; the messages arrive through the webhook or SSE, not in the response, and the parameters are the chat JID, a reference message and the count. Ask per chat and handle the volume received, because what WhatsApp returns depends on what it still keeps.
Do not promise the client the full history. Agree on what stays: what is in your database, plus whatever the sync brings. Look up messages already received with POST /{instanceId}/message/find.
Step 5: gradual cutover, one number at a time
Migrate one number, watch a full business day (deliveries, replies, webhook errors, instance status) and only then migrate the next. Keep the old API paid until the last number settles, because it is your way back. ZapZap costs R$15 per active number per month, prepaid with no per-message fee, plus the activation fee per instance: check GET /instances/cost and the pricing page.
Close each number with a short review: a webhook with a low error rate, a reply rate similar to before and the client informed. For those operating at scale, see AI agencies, resale under the client's brand and chip warm-up.
Quick summary
- Migrating is swapping HTTP calls, the webhook and the number's connection; your system should have a single sending layer.
- The history in your database remains yours; ZapZap does not import the previous API's database.
- message/history-sync requests older messages of a chat and delivers them by webhook or SSE, with no guarantee of full history.
- Migrate one number at a time, watch a business day and keep the old API until the end.
- ZapZap is an unofficial solution: the risk of limits or blocks exists on any unofficial API.
Keep reading
Also read
Frequently asked questions
Does ZapZap import the history from my current API?
There is no import of another API's database. Your system's history stays with you, and you can request older messages of a chat with message/history-sync.
Do I need to reconnect the number by QR code?
Yes. Each number is connected to ZapZap by QR code, with the device in hand. Schedule the window with the client.
Can I keep the old API during the migration?
You can, and should, until the last number settles. Only leave both webhooks active if your system dedupes events.
Is the webhook format the same as my current API's?
Probably not. ZapZap's envelope has delivery_id, event_id, instance_id, event and data; build an adapter to your internal format.
Does migrating reduce the risk of blocks?
Not by itself. ZapZap is an unofficial solution and WhatsApp may limit or block numbers. What helps is pace, consent and warm-up.
Migrate the first number and compare
Create the account, connect a test number and swap one call. R$15 per active number per month, with no per-message fee. When you verify your phone there is a welcome credit, subject to the current campaign.
