WhatsApp Cloud API Reference

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.

Base URL

https://<your-domain>

All API endpoints are relative to this base URL. When running locally, this is typically http://localhost:3000.

Authentication

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.

Sessions

GET/api/sessions

List all WhatsApp sessions.

Response

{
  "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"
    }
  ]
}
POST/api/sessions

Create a new WhatsApp session.

Request Body

FieldTypeRequiredDescription
namestringYesDisplay name for this session

Response

{
  "session": {
    "id": "uuid",
    "name": "My Bot",
    "status": "disconnected",
    "apiKey": "wapi_..."
  }
}
GET/api/sessions/:id

Get details of a specific session.

Response

{
  "session": { ... }
}
PATCH/api/sessions/:id

Update a session's name.

Request Body

FieldTypeRequiredDescription
namestringYesNew display name
DELETE/api/sessions/:id

Delete a session and all associated data.

Response

{ "success": true }

Connect / Disconnect

POST/api/sessions/:id/connect

Connect 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.

Request Body

FieldTypeRequiredDescription
actionstringNo"connect" (default), "pairing_code", or "disconnect"
phoneNumberstringNoRequired when action is 'pairing_code'. Include country code.

Response

{
  "session": {
    "status": "connecting"
  },
  "pairingCode": "123-456"
}

Send Messages

POST/api/send

Send a WhatsApp message through a connected session. The session must be in 'connected' status.

Authorization: Bearer <api-key>

Request Body

FieldTypeRequiredDescription
tostringYesRecipient phone number with country code (e.g. "+1234567890")
messagestringYesThe text message to send

Response

{
  "success": true,
  "messageId": "uuid",
  "from": "+1987654321",
  "to": "+1234567890",
  "status": "sent"
}

Example

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!"
  }'

Webhooks

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.

GET/api/sessions/:id/webhooks

List all webhooks for a session.

Response

{
  "webhooks": [
    {
      "url": "https://your-server.com/webhook",
      "secret": "whsec_...",
      "events": ["*"],
      "enabled": true,
      "createdAt": "2026-01-01T00:00:00.000Z"
    }
  ]
}
POST/api/sessions/:id/webhooks

Add a new webhook to a session.

Request Body

FieldTypeRequiredDescription
urlstringYesThe URL to receive webhook events
eventsstring[]NoArray of event types (default: ["*"])

Response

{
  "webhook": {
    "url": "https://your-server.com/webhook",
    "secret": "whsec_...",
    "events": ["*"],
    "enabled": true
  }
}
PATCH/api/sessions/:id/webhooks

Toggle a webhook's enabled/disabled state.

Request Body

FieldTypeRequiredDescription
urlstringYesThe webhook URL to toggle
DELETE/api/sessions/:id/webhooks

Remove a webhook from a session.

Request Body

FieldTypeRequiredDescription
urlstringYesThe webhook URL to remove

Webhook Events

Webhook payloads include a signature header for verification. Use the webhook secret to verify the HMAC-SHA256 signature.

Webhook Headers

X-WAPi-Signature: HMAC-SHA256 signature of the body

X-WAPi-Event: The event type

Content-Type: application/json

EventDescription
message.receivedA new message was received on the connected number
message.sentA message was sent via the API
session.connectedThe WhatsApp session was successfully connected
session.disconnectedThe WhatsApp session was disconnected
*Wildcard - receive all events

Webhook Payload Example

{
  "event": "message.received",
  "sessionId": "uuid",
  "timestamp": "2026-01-01T12:00:00.000Z",
  "data": {
    "from": "+1234567890",
    "message": "Hello!",
    "messageId": "uuid"
  }
}

Signature Verification (Node.js)

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');
});

Deploying to Heroku

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