What WAHA offers today
According to the official docs, WAHA runs on Docker and exposes a REST API with Swagger. Each WhatsApp account is a session, created with a name, and authentication uses the X-Api-Key header. It supports different connection engines:
- WEBJS and WPP: run a real WhatsApp Web instance in a browser controlled by Puppeteer.
- NOWEB and GOWS: talk to WhatsApp Web directly over WebSocket, without a browser, which saves CPU and memory. GOWS is written in Go.
About versions: for a long time there was WAHA Core, free, and WAHA Plus, with extra features unlocked by donation. The docs state that since version 2026.6.1, the Plus features have been merged into Core. If you're on an earlier version, check which of the two you run before planning any change.
The docs are also transparent about the risk: WhatsApp doesn't allow unofficial clients, so usage shouldn't be considered fully safe. That warning applies to any unofficial WhatsApp API, including D-API, and it's why isolation and sending best practices matter so much.
When it makes sense to look for a WAHA alternative
The project handles "connect and send" well. The pain shows up in another layer:
- Many sessions on one host. A container with dozens of numbers concentrates risk: if it restarts, they all drop together, and without a configured proxy they all go out through the same IP.
- Resource usage. Browser-based engines are heavy on memory; scaling means more machines and spreading sessions across them.
- A customer asking for the official API. The WAHA engines described in the docs connect to WhatsApp Web; teams that also need Meta's Cloud API want both behind the same integration.
- Nobody wants to be on call for WhatsApp. Updating images, tracking protocol changes and recovering stuck sessions eat hours that never become product.
WAHA and D-API on objective criteria
| Criteria | WAHA | D-API |
|---|---|---|
| Where it runs | Your server, via Docker | D-API infrastructure |
| Cost | Free software; you pay for servers and operations | Per connection, with a lower price as volume grows |
| Official connection (Cloud API) | Check with the project | Yes, in the same API as the unofficial one |
| Isolation between numbers | Depends on how you distribute sessions and containers | Per-instance isolation |
| IP per number | Depends on your network configuration | Dedicated proxy with its own IP per connection |
| Authentication | X-Api-Key header | Authorization header |
| Support | Community and supporter tier | D-API team, with support in English |
A broader comparison between hosting and buying is in self-hosted vs managed, and how the QR code connection works is covered in WhatsApp API with QR code.
Route mapping from WAHA to D-API
Since both are REST and organized around sessions, the translation is almost mechanical. The main differences are the recipient format and field names:
| WAHA | D-API |
|---|---|
POST /api/sessions with name | POST /api/v1/sessions with sessionId |
POST /api/sendText with session, chatId and text | POST /api/v1/messages/send/text with sessionId, to and text |
chatId in the format [email protected] | to with the number only: 14155550123 |
X-Api-Key header | Authorization header with the API key, without Bearer |
| Webhooks configured on the session | webhookUrl when creating the session, or webhook-config with one URL per event |
If your code calls WAHA from its own function, the change can stay inside it. A text-sending adapter in JavaScript looks like this:
// before: fetch('http://your-waha:3000/api/sendText', ...)
async function sendText(session, chatId, text) {
const to = chatId.replace('@c.us', '')
const res = await fetch('https://api.d-api.cloud/api/v1/messages/send/text', {
method: 'POST',
headers: {
Authorization: process.env.DAPI_API_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify({ sessionId: session, to, text }),
})
if (!res.ok) {
const { error, statusCode } = await res.json()
throw new Error(`D-API ${statusCode}: ${error}`)
}
}Keeping the old function signature (session, chatId, text) avoids touching its callers. In Node.js, the d-api-sdk SDK replaces the manual fetch with dapi.messages.sendText.
Five-step migration plan
- List the WAHA routes your system calls and the webhook events it consumes.
- Write the D-API adapter and a receiver for the event envelope, which carries
event,sessionIdanddata. - Create one D-API session per number, with the same name you used on WAHA to make tracking easier.
- Connect each number by QR code (
GET /api/v1/sessions/YOUR_ID/qr) and wait for theconnection.statusevent withconnected. - Stop the matching session on WAHA and, once none are left, shut down the container.
D-API is a WhatsApp API built for teams that need many stable connections, and the unofficial WhatsApp API is the natural starting point for anyone coming from WAHA. The 3-day free trial, no credit card, is enough to validate the adapter with a real number. If you're evaluating other options, see the Twilio alternative as well.
