REST API

Every endpoint is authenticated with a workspace API key and scoped to your data. Create keys under Settings → API keys.

Authentication

Send the key as a bearer token (or X-Api-Key). Rate limits are per key, per minute.

curl http://localhost:8010/api/v1/sessions \
  -H "Authorization: Bearer wsk_ab12cd.0123456789abcdef…"

Successful responses are { "success": true, "data": … }; failures are { "success": false, "error": "…" } with a 4xx/5xx status.

Sending messages

One endpoint covers every content type. Use phone for a raw number or chatId for a JID (…@c.us, …@g.us, …@newsletter).

POST /api/v1/sessions/{session}/messages

// Text with a mention and a quote
{ "phone": "15551234567", "type": "text", "text": "Hi @15550001111!",
  "mentions": ["15550001111"], "quotedMessageId": "false_1555…@c.us_ABC" }

// Image from a URL with a caption
{ "phone": "15551234567", "type": "image",
  "mediaUrl": "https://example.com/promo.jpg", "caption": "New drop 🎉" }

// Document from base64
{ "phone": "15551234567", "type": "document", "mediaBase64": "JVBERi0…",
  "media_mime": "application/pdf", "media_filename": "invoice.pdf" }

// Voice note (plays as PTT)
{ "phone": "15551234567", "type": "voice", "mediaUrl": "https://example.com/note.ogg" }

// Sticker, view-once photo, GIF
{ "phone": "…", "type": "sticker", "mediaUrl": "https://example.com/logo.png" }
{ "phone": "…", "type": "image", "mediaUrl": "…", "viewOnce": true }
{ "phone": "…", "type": "gif", "mediaUrl": "https://example.com/clip.mp4" }

// Location
{ "phone": "…", "type": "location", "latitude": 51.5072, "longitude": -0.1276,
  "locationName": "London", "locationAddress": "Trafalgar Square" }

// Poll
{ "phone": "…", "type": "poll",
  "poll": { "name": "Pick a slot", "options": ["9am","1pm","4pm"],
            "allowMultipleAnswers": false } }

// Contact card
{ "phone": "…", "type": "contact", "contactIds": ["15550002222"] }

Sessions

MethodPathDescription
GET /api/v1/sessions List every WhatsApp number in the workspace.
POST /api/v1/sessions Create a number. Body: name, auth_mode (qr|pairing), phone_number.
GET /api/v1/sessions/{session} Live status snapshot (refreshed from the gateway).
GET /api/v1/sessions/{session}/qr Current QR string and PNG data URL.
POST /api/v1/sessions/{session}/pairing-code Request an 8-character pairing code.
GET /api/v1/sessions/{session}/state Raw WhatsApp connection state.
POST /api/v1/sessions/{session}/restart Restart the browser session.
POST /api/v1/sessions/{session}/logout Unlink the number from WhatsApp.
POST /api/v1/sessions/{session}/sync Import contacts, chats, groups, channels, labels.
GET|PATCH /api/v1/sessions/{session}/profile Read or update display name, status, picture.
POST /api/v1/sessions/{session}/presence Go online/offline. Body: available.
POST /api/v1/sessions/{session}/settings Auto-download and background-sync toggles.
DELETE /api/v1/sessions/{session} Delete the number and all its local data.

Messaging

MethodPathDescription
POST /api/v1/sessions/{session}/messages Send any message type (see below).
POST /api/v1/sessions/{session}/messages/bulk Up to 200 messages with pacing.
GET /api/v1/sessions/{session}/messages/{id} Fetch a message by WhatsApp id.
GET /api/v1/sessions/{session}/messages/{id}/media Download attachment as base64.
POST /api/v1/sessions/{session}/messages/{id}/reply Reply, quoting the message.
POST /api/v1/sessions/{session}/messages/{id}/react React with an emoji ("" removes).
GET /api/v1/sessions/{session}/messages/{id}/reactions List reactions.
POST /api/v1/sessions/{session}/messages/{id}/edit Edit sent text. Body: text.
POST /api/v1/sessions/{session}/messages/{id}/forward Forward to another chat.
POST /api/v1/sessions/{session}/messages/{id}/star Star / unstar.
POST /api/v1/sessions/{session}/messages/{id}/pin Pin / unpin. Body: pinned, duration.
GET /api/v1/sessions/{session}/messages/{id}/info Per-recipient delivery receipts.
GET /api/v1/sessions/{session}/messages/{id}/poll-votes Poll results.
POST /api/v1/sessions/{session}/messages/{id}/vote Vote in a poll. Body: options[].
GET /api/v1/sessions/{session}/messages/{id}/order Commerce order details.
DELETE /api/v1/sessions/{session}/messages/{id} Delete. Body: everyone.
GET /api/v1/sessions/{session}/search Search WhatsApp messages. Query: query, chatId, limit.
GET /api/v1/messages Search locally stored history.

Chats

MethodPathDescription
GET /api/v1/sessions/{session}/chats List chats. Query: limit, groups, archived, unread.
GET /api/v1/sessions/{session}/chats/{chatId} Chat details with group/channel metadata.
GET /api/v1/sessions/{session}/chats/{chatId}/messages Fetch recent messages.
POST /api/v1/sessions/{session}/chats/{chatId}/actions seen, typing, archive, pin, mute, unread, clear, delete, sync_history, labels, customer_note.

Contacts

MethodPathDescription
GET /api/v1/sessions/{session}/contacts WhatsApp address book. Query: only_my, only_wa, search.
GET /api/v1/sessions/{session}/contacts/{contactId} Profile, about text, common groups, device count.
POST /api/v1/sessions/{session}/contacts/{contactId}/block Block / unblock.
GET /api/v1/sessions/{session}/contacts/blocked List blocked contacts.
GET /api/v1/sessions/{session}/check/{number} Is this number on WhatsApp?
POST /api/v1/sessions/{session}/check Bulk number validation. Body: numbers[].
GET|POST|PATCH|DELETE /api/v1/contacts CRM contacts stored in the workspace.

Groups

MethodPathDescription
GET /api/v1/sessions/{session}/groups List groups.
POST /api/v1/sessions/{session}/groups Create a group. Body: title, participants[].
POST /api/v1/sessions/{session}/groups/join Join via invite code.
GET /api/v1/sessions/{session}/groups/{groupId} Group details and participants.
POST /api/v1/sessions/{session}/groups/{groupId}/actions add, remove, promote, demote, update, invite_code, revoke_invite, membership_requests, approve, reject, leave.

Channels

MethodPathDescription
GET /api/v1/sessions/{session}/channels List channels.
POST /api/v1/sessions/{session}/channels Create a channel. Body: title, description.
GET /api/v1/sessions/{session}/channels/search Search the channel directory.
GET|POST /api/v1/sessions/{session}/channels/{channelId}/messages Read or broadcast.
POST /api/v1/sessions/{session}/channels/{channelId}/actions subscribers, update, subscribe, unsubscribe, mute, unmute, seen, admin_invite, admin_accept, admin_revoke, admin_demote, transfer, delete.

Labels, broadcasts, calls

MethodPathDescription
GET /api/v1/sessions/{session}/labels WhatsApp Business labels.
GET /api/v1/sessions/{session}/labels/{labelId}/chats Chats carrying a label.
POST /api/v1/sessions/{session}/labels/assign Body: label_ids[], chat_ids[].
GET /api/v1/sessions/{session}/broadcasts Status/broadcast lists.
POST /api/v1/sessions/{session}/call-link Create a call link. Body: call_type (video|voice).

Campaigns & webhooks

MethodPathDescription
GET|POST /api/v1/campaigns List or create campaigns.
GET /api/v1/campaigns/{id} Campaign with progress breakdown.
POST /api/v1/campaigns/{id}/actions start, pause, cancel.
GET /api/v1/campaigns/{id}/recipients Per-recipient delivery report.
GET|POST /api/v1/webhooks List or subscribe to events.
DELETE /api/v1/webhooks/{id} Remove a subscription.
GET /api/v1/usage Current period usage against plan limits.

Webhooks

Subscribe to any of these events. Each delivery carries X-WaSaaS-Signature: sha256=<hmac> computed over the raw body with your webhook secret. Retries use exponential backoff for up to six attempts.

message message_create message_ack message_edit message_reaction message_revoke_everyone message_revoke_me media_uploaded session.status qr code ready authenticated auth_failure disconnected change_state group_join group_leave group_update group_admin_changed group_membership_request chat_archived chat_removed contact_changed incoming_call vote_update
// Express / Node verification example
import crypto from 'node:crypto';

app.post('/webhooks/wasaas', express.raw({ type: '*/*' }), (req, res) => {
  const raw = req.body.toString('utf8');
  const expected =
    'sha256=' + crypto.createHmac('sha256', process.env.WASAAS_WEBHOOK_SECRET)
      .update(raw)
      .digest('hex');

  if (expected !== req.get('x-wasaas-signature')) {
    return res.sendStatus(401);
  }

  const event = JSON.parse(raw);
  // handle event…
  res.sendStatus(204);
});