WA Bot Server
Complete REST API reference. All endpoints accept and return JSON. All /api/* routes require a valid Bearer token.
http://localhost:3000
All /api/* endpoints require authentication. Include your token in every request:
๐ Get your token by calling POST /auth/register or POST /auth/login.
๐ Tokens are long-lived โ they never expire unless you reset your password.
๐ Resetting your password generates a new token, invalidating all old sessions.
๐ Each user has isolated data โ messages, webhooks, stats, and WhatsApp sessions are fully separated.
Request Body
| Param | Type | Description | |
|---|---|---|---|
| string | Required | Your email address | |
| password | string | Required | Min 6 characters |
Example
Response
Request Body
| Param | Type | Description | |
|---|---|---|---|
| string | Required | Your email address | |
| password | string | Required | Your password |
Example
Example
Response
Request Body
๐ก The 6-digit OTP will appear in your server console. Valid for 15 minutes. Max 5 attempts.
Request Body
โ ๏ธ Resets your token โ all existing sessions are invalidated. You'll receive a new token in the response.
Request Body
| Param | Type | Description | |
|---|---|---|---|
| number | string | Required | Phone number with country code (e.g. 254712345678) |
| message | string | Required | The message text to send |
Example
Example
Example
Example
Example
Example
Example
Example
Example
Webhook Payload
When a message is received, the following JSON is POSTed to your URL:
Example
Example
Response
Example
Response
A WhatsApp/email-style view built from the message log: messages are grouped by conversation, with each conversation's most recent message surfaced, newest first. chat is a contact or group JID (e.g. 12345@s.whatsapp.net or 12345-67890@g.us).
| GET | /api/inbox | ?enrich=true&limit= โ conversation list + last message; enrich adds profile picture, name & about/topic |
| GET | /api/conversation | ?chat=&limit= โ messages of one conversation (oldest first) |
| GET | /api/conversation/actions | ?chat= โ actions available for the contact/group |
| POST | /api/conversation/action | chat, action, …params |
Actions โ contacts: block, unblock, subscribe_presence. Groups: exit, set_name, set_description, set_photo, announce, lock, invite_link, add/remove/promote/demote.
curl -X POST http://localhost:3000/api/conversation/action \ -H "Authorization: Bearer YOUR_TOKEN" -H "Content-Type: application/json" \ -d '{"chat":"12345-67890@g.us","action":"set_name","name":"New group name"}'
Realtime new messages still arrive over the WebSocket (message events); these endpoints serve the cached history and the conversation list.
Media fields (image/video/audio/...) accept an https:// URL, a data: URI, or a raw base64 string. to accepts a phone number or a full JID.
| POST | /api/send-image | to, image, caption |
| POST | /api/send-video | to, video, caption, gifPlayback |
| POST | /api/send-audio | to, audio, ptt (voice note) |
| POST | /api/send-document | to, document, filename, caption, mimetype |
| POST | /api/send-sticker | to, sticker (WebP) |
| POST | /api/send-location | to, latitude, longitude, name, address |
| POST | /api/send-contact | to, displayName, phone or vcard |
| POST | /api/send-poll | to, name, options[], selectableCount |
curl -X POST http://localhost:3000/api/send-image \ -H "Authorization: Bearer YOUR_TOKEN" -H "Content-Type: application/json" \ -d '{"to":"254712345678","image":"https://picsum.photos/600","caption":"Hi ๐"}'
For reactions / deletes on someone else's message, pass participant (group sender) and fromMe:false.
| POST | /api/reply-message | to, messageId, participant, text, quotedText |
| POST | /api/send-reaction | to, messageId, emoji, fromMe (empty emoji removes) |
| POST | /api/edit-message | to, messageId, newText |
| POST | /api/revoke-message | to, messageId, participant, fromMe (delete for everyone) |
| POST | /api/mark-read | chat, sender, messageIds[] |
| POST | /api/presence | presence: available / unavailable |
| POST | /api/chat-presence | to, state: composing/paused, media |
| POST | /api/subscribe-presence | jid |
| GET | /api/group-info | ?groupId= |
| POST | /api/create-group | name, participants[] |
| POST | /api/group/participants | groupId, action (add/remove/promote/demote), participants[] |
| POST | /api/group/name | groupId, name |
| POST | /api/group/topic | groupId, topic |
| POST | /api/group/photo | groupId, image (empty removes) |
| POST | /api/group/announce | groupId, announce |
| POST | /api/group/locked | groupId, locked |
| GET | /api/group/invite-link | ?groupId=&reset= |
| GET | /api/group/info-from-link | ?link= |
| GET | /api/group/join-requests | ?groupId= |
| POST | /api/group/join-requests | groupId, action (approve/reject), participants[] |
| POST | /api/group/member-add-mode | groupId, mode |
| POST | /api/group/disappearing | groupId, seconds |
| GET | /api/group/subgroups | ?communityId= |
| POST | /api/group/link ยท /api/group/unlink | parent, child |
| POST | /api/check-number | numbers[] โ is on WhatsApp |
| GET | /api/user-info | ?jids= (csv) โ status, picture id, devices |
| GET | /api/profile-picture | ?jid=&preview= |
| GET | /api/business-profile | ?jid= |
| GET | /api/user-devices | ?jids= (csv) |
| GET | /api/contacts | local contact cache |
| GET | /api/blocklist | list blocked users |
| POST | /api/block ยท /api/unblock | jid |
| GET | /api/privacy-settings | read privacy settings |
| POST | /api/set-status | status (your "about" text) |
| GET | /api/newsletters | followed channels |
| GET | /api/newsletter/info | ?jid= |
| GET | /api/newsletter/info-from-invite | ?key= |
| POST | /api/newsletter/create | name, description |
| POST | /api/newsletter/follow ยท /unfollow | jid |
| POST | /api/newsletter/mute | jid, mute |
Incoming media (image/video/audio/document/sticker) is cached in memory as it arrives. Download it by message id; the response is a base64 dataUri you can preview or save. Only recently received media is available (cache is bounded and cleared on restart).
| GET | /api/download-media | ?messageId= โ { mediaType, mimetype, filename, size, dataUri } |
curl http://localhost:3000/api/download-media?messageId=ABCD1234 \ -H "Authorization: Bearer YOUR_TOKEN"
Connect to /ws for a live push stream instead of polling. Authenticate with a Bearer header, a ?token= query param, or the wa_token cookie. Every frame is a JSON envelope { event, data, timestamp }; a status snapshot is sent on connect.
Events: status, pair_success, message, receipt, presence, chat_presence, group_info, joined_group, picture, call.
const ws = new WebSocket(`ws://localhost:3000/ws?token=${'$'}{token}`); ws.onmessage = (e) => { const { event, data, timestamp } = JSON.parse(e.data); console.log(event, data); // status | message | receipt | presence | ... };