README
¶
wago-api
WhatsApp REST API — native protocol, multi-session, production-ready.
- 129 REST endpoints — messaging, groups, communities, channels, privacy, business
- Multi-session — run hundreds of WhatsApp accounts in a single instance
- 32MB Docker image — single Go binary, zero external dependencies
- Production-ready — auto-reconnect, webhook retry, rate limiting, SSRF protection, request tracing
Quick Start
git clone https://github.com/arktnld/wago-api && cd wago-api
docker compose up
Start a session and scan the QR code:
curl localhost:3000/session/start/main
curl localhost:3000/session/qr/main/image --output qr.png
Send a message:
curl -X POST localhost:3000/client/sendMessage/main \
-H 'Content-Type: application/json' \
-d '{"chatId":"5511999999999@s.whatsapp.net","text":"Hello from wago-api!"}'
{"success":true,"messageId":"3EB0F85AB813A2BB26F73D","timestamp":1777744034}
Features
Messaging
Send text, images, videos, audio, and documents. Reply, forward, edit, and delete messages. Send reactions, create polls, and star messages. Upload media via URL or base64.
Groups
Create and manage groups. Add, remove, promote, and demote participants. Generate and revoke invite links. Set group name, description, photo, and permissions. Approve or reject membership requests.
Communities
Create WhatsApp Communities. Link and unlink sub-groups. List all sub-groups and participants. Control join approval mode and member add permissions.
Channels (Newsletters)
Create, follow, and unfollow channels. Send messages and fetch message history. Send reactions, mute/unmute, and mark as viewed.
Contacts & Presence
Access contact list and profile pictures. Subscribe to online/offline status. Send typing and recording indicators. Block and unblock contacts. Generate and resolve contact QR links.
Privacy
10 granular privacy settings: last seen, profile photo, about, status, groups, read receipts, online status, calls, messages, and stickers. Set disappearing messages globally or per-chat.
Business
Fetch verified business profiles and resolve wa.me message links. List official WhatsApp bots with their commands and prompts.
Calls
Reject incoming voice and video calls programmatically.
Labels
Create, edit, and delete labels with custom colors. Assign labels to chats and individual messages.
Infrastructure
- Auto-reconnect with error tracking
- Webhooks with 3x retry and exponential backoff
- WebSocket real-time event stream
- Per-IP rate limiting with auto-cleanup
- CORS headers for browser access
- API key authentication (header-only)
- Request tracing via
X-Request-Id - SSRF protection on media URL fetches
- SQLite session persistence with WAL mode
- Parallel session restore on startup
Architecture
┌──────────┐ REST ┌──────────┐ Native Protocol ┌──────────────────┐
│ Your App ├──────────────►│ wago-api ├──────────────────────►│ WhatsApp Servers │
└──────────┘ └────┬─────┘ └──────────────────┘
│
┌───────────┼───────────┐
▼ ▼ ▼
┌──────────┐ ┌────────┐ ┌──────────┐
│ Webhooks │ │ WS │ │ SQLite │
│ (retry) │ │ events │ │ sessions │
└──────────┘ └────────┘ └──────────┘
API Reference
Session
| Method | Endpoint | Description |
|---|---|---|
| GET | /ping |
Health check |
| GET | /session/getSessions |
List all sessions |
| GET | /session/start/{id} |
Start new session |
| GET | /session/stop/{id} |
Disconnect session |
| GET | /session/status/{id} |
Get session state |
| GET | /session/qr/{id} |
Get QR code string |
| GET | /session/qr/{id}/image |
Get QR code as PNG |
| POST | /session/requestPairingCode/{id} |
Get pairing code (no QR) |
| GET | /session/restart/{id} |
Restart session |
| GET | /session/terminate/{id} |
Terminate and delete session |
| GET | /session/terminateInactive |
Terminate inactive sessions |
| GET | /session/terminateAll |
Terminate all sessions |
Message
| Method | Endpoint | Description |
|---|---|---|
| POST | /client/sendMessage/{id} |
Send text or media message |
| POST | /client/sendPoll/{id} |
Send poll |
| POST | /message/reply/{id} |
Reply to a message |
| POST | /message/forward/{id} |
Forward a message |
| POST | /message/react/{id} |
React to a message |
| POST | /message/edit/{id} |
Edit a sent message |
| POST | /message/delete/{id} |
Delete a message |
| POST | /message/star/{id} |
Star a message |
| POST | /message/unstar/{id} |
Unstar a message |
| POST | /message/downloadMedia/{id} |
Download message media |
| POST | /message/downloadMediaAsData/{id} |
Download media as base64 |
| POST | /message/getReactions/{id} |
Get reactions info |
| POST | /message/getPollVotes/{id} |
Get poll votes info |
Client
| Method | Endpoint | Description |
|---|---|---|
| GET | /client/getContacts/{id} |
Get all contacts |
| GET | /client/getChats/{id} |
Get joined groups |
| GET | /client/getChannels/{id} |
Get subscribed channels |
| GET | /client/getState/{id} |
Get connection state |
| POST | /client/isRegisteredUser/{id} |
Check if phone is on WhatsApp |
| POST | /client/getNumberId/{id} |
Get JID for phone number |
| POST | /client/getContactById/{id} |
Get contact info |
| POST | /client/getChatById/{id} |
Get chat info |
| POST | /client/getProfilePicUrl/{id} |
Get profile picture URL |
| POST | /client/setProfilePicture/{id} |
Set profile picture |
| DELETE | /client/deleteProfilePicture/{id} |
Delete profile picture |
| POST | /client/setStatus/{id} |
Set status message |
| POST | /client/setPushName/{id} |
Set display name |
| POST | /client/sendPresenceAvailable/{id} |
Set presence to available |
| POST | /client/sendPresenceUnavailable/{id} |
Set presence to unavailable |
| POST | /client/subscribePresence/{id} |
Subscribe to contact presence |
| POST | /client/sendSeen/{id} |
Mark messages as read |
| POST | /client/getBlockedContacts/{id} |
Get blocked contacts |
| POST | /client/getPrivacySettings/{id} |
Get privacy settings |
| POST | /client/acceptInvite/{id} |
Join group via invite link |
| POST | /client/getInviteInfo/{id} |
Get group info from invite |
| POST | /client/archiveChat/{id} |
Archive a chat |
| POST | /client/unarchiveChat/{id} |
Unarchive a chat |
| POST | /client/muteChat/{id} |
Mute a chat |
| POST | /client/unmuteChat/{id} |
Unmute a chat |
| POST | /client/pinChat/{id} |
Pin a chat |
| POST | /client/unpinChat/{id} |
Unpin a chat |
| POST | /client/markChatUnread/{id} |
Mark chat as unread |
| POST | /client/syncHistory/{id} |
Request history sync |
| POST | /client/getCommonGroups/{id} |
Get common groups with contact |
| POST | /client/getContactDeviceCount/{id} |
Get linked device count |
| POST | /client/getUserDevices/{id} |
Get user's linked devices |
| POST | /client/getCountryCode/{id} |
Get country code from phone |
| POST | /client/getFormattedNumber/{id} |
Format phone number |
| POST | /client/getLabels/{id} |
Get labels |
| POST | /client/addOrRemoveLabels/{id} |
Add/remove label from chat |
| POST | /client/editLabel/{id} |
Create/edit/delete label |
| POST | /client/createGroup/{id} |
Create a group |
| POST | /client/createChannel/{id} |
Create a channel |
| POST | /client/subscribeToChannel/{id} |
Follow a channel |
| POST | /client/unsubscribeFromChannel/{id} |
Unfollow a channel |
| POST | /client/getChannelByInviteCode/{id} |
Get channel by invite code |
Chat
| Method | Endpoint | Description |
|---|---|---|
| POST | /chat/sendStateTyping/{id} |
Send typing indicator |
| POST | /chat/sendStateRecording/{id} |
Send recording indicator |
| POST | /chat/clearState/{id} |
Clear typing/recording state |
| POST | /chat/sendSeen/{id} |
Mark chat as read |
| POST | /chat/markUnread/{id} |
Mark chat as unread |
| POST | /chat/delete/{id} |
Delete a chat |
| POST | /chat/fetchMessages/{id} |
Request message history |
| POST | /chat/syncHistory/{id} |
Sync message history |
| POST | /chat/getContact/{id} |
Get contact for chat |
| POST | /chat/getLabels/{id} |
Get labels for chat |
| POST | /chat/changeLabels/{id} |
Change labels on chat |
Contact
| Method | Endpoint | Description |
|---|---|---|
| POST | /contact/block/{id} |
Block a contact |
| POST | /contact/unblock/{id} |
Unblock a contact |
| POST | /contact/getProfilePicUrl/{id} |
Get profile picture |
| POST | /contact/getAbout/{id} |
Get contact about/status |
| POST | /contact/getChat/{id} |
Get chat for contact |
| POST | /contact/getFormattedNumber/{id} |
Format phone number |
| POST | /contact/getCountryCode/{id} |
Get country code |
| POST | /contact/getCommonGroups/{id} |
Get common groups |
| POST | /contact/getQRLink/{id} |
Generate contact QR link |
| POST | /contact/resolveQR/{id} |
Resolve contact QR code |
Group
| Method | Endpoint | Description |
|---|---|---|
| POST | /groupChat/getClassInfo/{id} |
Get group info |
| POST | /groupChat/leave/{id} |
Leave group |
| POST | /groupChat/addParticipants/{id} |
Add members |
| POST | /groupChat/removeParticipants/{id} |
Remove members |
| POST | /groupChat/promoteParticipants/{id} |
Promote to admin |
| POST | /groupChat/demoteParticipants/{id} |
Demote from admin |
| POST | /groupChat/getInviteCode/{id} |
Get invite link |
| POST | /groupChat/revokeInvite/{id} |
Revoke invite link |
| POST | /groupChat/setSubject/{id} |
Set group name |
| POST | /groupChat/setDescription/{id} |
Set group description |
| POST | /groupChat/setPicture/{id} |
Set group picture |
| POST | /groupChat/deletePicture/{id} |
Delete group picture |
| POST | /groupChat/setMessagesAdminsOnly/{id} |
Toggle admin-only messages |
| POST | /groupChat/setInfoAdminsOnly/{id} |
Toggle admin-only info edit |
| POST | /groupChat/getGroupMembershipRequests/{id} |
Get join requests |
| POST | /groupChat/approveGroupMembershipRequests/{id} |
Approve join requests |
| POST | /groupChat/rejectGroupMembershipRequests/{id} |
Reject join requests |
Channel
| Method | Endpoint | Description |
|---|---|---|
| POST | /channel/getClassInfo/{id} |
Get channel info |
| POST | /channel/sendMessage/{id} |
Send channel message |
| POST | /channel/fetchMessages/{id} |
Fetch channel messages |
| POST | /channel/sendSeen/{id} |
Mark channel as viewed |
| POST | /channel/sendReaction/{id} |
React to channel message |
| POST | /channel/mute/{id} |
Mute channel |
| POST | /channel/unmute/{id} |
Unmute channel |
| POST | /channel/deleteChannel/{id} |
Delete channel |
Community
| Method | Endpoint | Description |
|---|---|---|
| POST | /community/create/{id} |
Create community |
| POST | /community/linkGroup/{id} |
Link group to community |
| POST | /community/unlinkGroup/{id} |
Unlink group from community |
| POST | /community/getSubGroups/{id} |
List sub-groups |
| POST | /community/getParticipants/{id} |
List all participants |
| POST | /community/setJoinApprovalMode/{id} |
Toggle join approval |
| POST | /community/setMemberAddMode/{id} |
Set member add permissions |
Privacy
| Method | Endpoint | Description |
|---|---|---|
| POST | /privacy/setSetting/{id} |
Set privacy setting |
| POST | /privacy/setDefaultDisappearingTimer/{id} |
Set default disappearing timer |
| POST | /privacy/setDisappearingTimer/{id} |
Set per-chat disappearing timer |
Business & Bot
| Method | Endpoint | Description |
|---|---|---|
| POST | /business/getProfile/{id} |
Get business profile |
| POST | /business/resolveLink/{id} |
Resolve wa.me link |
| GET | /bot/list/{id} |
List available bots |
Call
| Method | Endpoint | Description |
|---|---|---|
| POST | /call/reject/{id} |
Reject incoming call |
Status
| Method | Endpoint | Description |
|---|---|---|
| GET | /status/privacy/{id} |
Get status privacy settings |
WebSocket
Connect to /ws/{sessionId} for real-time events.
Events
Events are delivered via webhooks (HTTP POST) and/or WebSocket.
| Event | Trigger |
|---|---|
ready |
Session connected |
disconnected |
Session disconnected |
logged_out |
Session logged out |
temporary_ban |
Account temporarily banned |
connect_failure |
Connection attempt failed |
stream_replaced |
Session replaced by another device |
qr |
New QR code generated |
authenticated |
QR scanned successfully |
message |
Message received |
message_create |
Message sent by this session |
message_ack |
Message delivery/read receipt |
presence |
Contact typing/recording state |
group_update |
Group metadata changed |
group_join |
Added to a group |
call |
Incoming call |
contact_changed |
Contact name changed |
blocklist |
Block list updated |
blocklist_change |
Contact blocked/unblocked |
chat_archived |
Chat archived/unarchived |
chat_muted |
Chat muted/unmuted |
chat_pinned |
Chat pinned/unpinned |
chat_removed |
Chat deleted |
message_starred |
Message starred/unstarred |
message_revoke_me |
Message deleted for me |
unread_count |
Chat read state changed |
label_edit |
Label created/edited/deleted |
label_association_chat |
Label assigned to chat |
label_association_message |
Label assigned to message |
history_sync |
Message history synced |
identity_change |
Contact security code changed |
newsletter_message |
Channel message received |
newsletter_join |
Joined a channel |
newsletter_leave |
Left a channel |
newsletter_mute_change |
Channel mute state changed |
picture |
Profile picture changed |
Webhook payload example:
{
"sessionId": "main",
"event": "message",
"data": {
"id": "3EB0F85AB813A2BB26F73D",
"chat": "5511999999999@s.whatsapp.net",
"sender": "5511999999999@s.whatsapp.net",
"pushName": "John",
"body": "Hello!",
"type": "text",
"timestamp": 1777744034,
"isGroup": false,
"isFromMe": false
}
}
Webhook URL pattern: {BASE_WEBHOOK_URL}/{sessionId}/{event}
Failed webhooks are retried 3 times with exponential backoff (1s, 2s, 4s).
Configuration
| Variable | Default | Description |
|---|---|---|
PORT |
3000 |
HTTP server port |
API_KEY |
(empty) | API key for authentication (header X-Api-Key) |
BASE_WEBHOOK_URL |
(empty) | Base URL for webhook callbacks |
ENABLE_WEBHOOK |
true |
Enable webhook delivery |
ENABLE_WEBSOCKET |
false |
Enable WebSocket event stream |
AUTO_START_SESSIONS |
true |
Restore sessions on startup |
SESSIONS_PATH |
./sessions |
Path for session database files |
SET_MESSAGES_AS_SEEN |
false |
Auto-mark incoming messages as read |
LOG_LEVEL |
info |
Log level: trace, debug, info, warn, error |
RATE_LIMIT_MAX |
1000 |
Max requests per window per IP |
RATE_LIMIT_WINDOW_MS |
1000 |
Rate limit window in milliseconds |
DISABLED_CALLBACKS |
(empty) | Pipe-separated list of disabled events |
Docker
docker pull arktnld/wago-api:latest
services:
api:
image: arktnld/wago-api:latest
ports:
- "3000:3000"
volumes:
- ./sessions:/app/sessions
environment:
- API_KEY=your-secret-key
- BASE_WEBHOOK_URL=https://your-server.com/webhook
restart: unless-stopped
- Image size: 32MB
- Built-in healthcheck:
GET /pingevery 30s - Session data persisted in
/app/sessionsvolume
Build from Source
git clone https://github.com/arktnld/wago-api
cd wago-api
CGO_ENABLED=1 go build -ldflags="-s -w" -o wago-api .
./wago-api
Requires Go 1.25+ and a C compiler (for SQLite).
Security
- Authentication — API key via
X-Api-Keyheader (query parameter intentionally disabled to prevent key leakage in logs) - SSRF Protection — Media URL fetches validate against private IPs, loopback addresses, and cloud metadata endpoints
- Rate Limiting — Per-IP token bucket with automatic stale entry cleanup
- Request Tracing — Every response includes
X-Request-Idheader for debugging
Roadmap
- OpenAPI/Swagger spec
- Prometheus
/metricsendpoint - Admin web dashboard
- Multi-arch Docker images (ARM64)
- End-to-end test suite
Credits
Built on whatsmeow by tulir. API design inspired by wwebjs-api.
License
Documentation
¶
There is no documentation for this package.