WhatsApp Cloud provides a REST API for connecting WhatsApp numbers using Baileys. Create sessions, configure webhooks, and send messages programmatically. Designed for deployment on Heroku or any long-running server.
https://<your-domain>All API endpoints are relative to this base URL. When running locally, this is typically http://localhost:3000.
Each session has a unique API key. Include it in the Authorization header for endpoints that require authentication (primarily the send message endpoint).
Authorization: Bearer wapi_your_api_key_here # The API key is generated when you create a session # and can be found in the session detail page.
/api/sessionsList all WhatsApp sessions.
{
"sessions": [
{
"id": "uuid",
"name": "My Bot",
"phoneNumber": "+1234567890",
"status": "connected",
"apiKey": "wapi_...",
"webhooks": [...],
"messageCount": 42,
"createdAt": "2026-01-01T00:00:00.000Z",
"lastConnected": "2026-01-01T12:00:00.000Z"
}
]
}/api/sessionsCreate a new WhatsApp session.
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | Display name for this session |
{
"session": {
"id": "uuid",
"name": "My Bot",
"status": "disconnected",
"apiKey": "wapi_..."
}
}/api/sessions/:idGet details of a specific session.
{
"session": { ... }
}/api/sessions/:idUpdate a session's name.
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | New display name |
/api/sessions/:idDelete a session and all associated data.
{ "success": true }/api/sessions/:id/connectConnect or disconnect a WhatsApp session. Use action='connect' for QR login, action='pairing_code' with a phone number to get a pairing code, or action='disconnect' to close the session.
| Field | Type | Required | Description |
|---|---|---|---|
| action | string | No | "connect" (default), "pairing_code", or "disconnect" |
| phoneNumber | string | No | Required when action is 'pairing_code'. Include country code. |
{
"session": {
"status": "connecting"
},
"pairingCode": "123-456"
}/api/sendSend a WhatsApp message through a connected session. The session must be in 'connected' status.
Authorization: Bearer <api-key>
| Field | Type | Required | Description |
|---|---|---|---|
| to | string | Yes | Recipient phone number with country code (e.g. "+1234567890") |
| message | string | Yes | The text message to send |
{
"success": true,
"messageId": "uuid",
"from": "+1987654321",
"to": "+1234567890",
"status": "sent"
}curl -X POST https://your-domain.com/api/send \
-H "Authorization: Bearer wapi_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"to": "+1234567890",
"message": "Hello from WhatsApp Cloud!"
}'Configure webhook URLs to receive real-time notifications when events occur. Each webhook receives a POST request with a JSON body and a signature header for verification.
/api/sessions/:id/webhooksList all webhooks for a session.
{
"webhooks": [
{
"url": "https://your-server.com/webhook",
"secret": "whsec_...",
"events": ["*"],
"enabled": true,
"createdAt": "2026-01-01T00:00:00.000Z"
}
]
}/api/sessions/:id/webhooksAdd a new webhook to a session.
| Field | Type | Required | Description |
|---|---|---|---|
| url | string | Yes | The URL to receive webhook events |
| events | string[] | No | Array of event types (default: ["*"]) |
{
"webhook": {
"url": "https://your-server.com/webhook",
"secret": "whsec_...",
"events": ["*"],
"enabled": true
}
}/api/sessions/:id/webhooksToggle a webhook's enabled/disabled state.
| Field | Type | Required | Description |
|---|---|---|---|
| url | string | Yes | The webhook URL to toggle |
/api/sessions/:id/webhooksRemove a webhook from a session.
| Field | Type | Required | Description |
|---|---|---|---|
| url | string | Yes | The webhook URL to remove |
Webhook payloads include a signature header for verification. Use the webhook secret to verify the HMAC-SHA256 signature.
X-WAPi-Signature: HMAC-SHA256 signature of the body
X-WAPi-Event: The event type
Content-Type: application/json
| Event | Description |
|---|---|
| message.received | A new message was received on the connected number |
| message.sent | A message was sent via the API |
| session.connected | The WhatsApp session was successfully connected |
| session.disconnected | The WhatsApp session was disconnected |
| * | Wildcard - receive all events |
{
"event": "message.received",
"sessionId": "uuid",
"timestamp": "2026-01-01T12:00:00.000Z",
"data": {
"from": "+1234567890",
"message": "Hello!",
"messageId": "uuid"
}
}const crypto = require('crypto');
function verifySignature(body, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(body)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
// In your webhook handler:
app.post('/webhook', (req, res) => {
const signature = req.headers['x-wapi-signature'];
const isValid = verifySignature(
JSON.stringify(req.body),
signature,
'whsec_your_webhook_secret'
);
if (!isValid) {
return res.status(401).send('Invalid signature');
}
// Process the event
console.log(req.body.event, req.body.data);
res.status(200).send('OK');
});WhatsApp Cloud is designed to run on a Heroku dyno as a long-running Node.js process. Baileys maintains persistent WebSocket connections to WhatsApp servers, which requires a non-serverless environment.
# Clone the repo and deploy to Heroku heroku create your-wapi-cloud git push heroku main # Set the buildpack heroku buildpacks:set heroku/nodejs # Scale the web dyno heroku ps:scale web=1 # Your API is now live at: # https://your-wapi-cloud.herokuapp.com