TypeScript client library for WAHA (WhatsApp HTTP API) - Unofficial
✨ This library is fully auto-generated and maintained by GitHub Copilot
- ✅ Complete API Coverage: All 147 WAHA API endpoints implemented
- � Auto-Generated Types: 200+ TypeScript types generated from OpenAPI schema
- �🌐 Universal Compatibility: Works in both Node.js and browser environments
- 🚫 Zero Dependencies: No axios or other HTTP libraries - uses native fetch API
- 🔑 Default Configuration: Set API key, base URL, and default session on initialization
- 🔄 Config Override: Override session, timeout, retry attempts, and retry delay per API call
- 🔁 Automatic Retries: Built-in retry logic with configurable attempts and delays
- 📝 Fully Typed: Complete TypeScript support with JSDoc comments
- 🚀 Easy to Use: Simple and intuitive API
- 🛡️ Safe Send Methods: Built-in number verification to prevent blocking
npm install waha-api-client-tsThis package ships multiple bundle formats so it works both in Node.js and in web browsers:
- dist/index.cjs.js — CommonJS (Node require)
- dist/index.esm.js — ES Module (Node & modern bundlers)
- dist/index.cjs.min.js / dist/index.esm.min.js — Minified versions
- dist/index.umd.js / dist/index.umd.min.js — UMD bundle for browsers (script tag / CDN)
The package.json browser and unpkg entry point point to the UMD minified bundle for CDN usage.
import { WAHAClient } from 'waha-api-client-ts';
const client = new WAHAClient({ baseURL: 'https://your-waha-instance.com' });const { WAHAClient } = require('waha-api-client-ts');
const client = new WAHAClient({ baseURL: 'https://your-waha-instance.com' });If your app supports ES modules in the browser, you can import the ESM build directly from a bundler or local server:
<script type="module">
import { WAHAClient } from '/node_modules/waha-api-client-ts/dist/index.esm.js';
const client = new WAHAClient({ baseURL: 'https://your-waha-instance.com' });
// use client...
</script>Include the UMD bundle and access the library via the global name (package name or WAHA):
<script src="https://unpkg.com/waha-api-client-ts@latest/dist/index.umd.min.js"></script>
<script>
// If package name is not a valid JS identifier the global is also available as 'WAHA'
const client = (window.WAHA || window['waha-api-client-ts']).WAHAClient
? new (window.WAHA || window['waha-api-client-ts']).WAHAClient({ baseURL: 'https://...' })
: null;
// use client...
</script>Types are generated from the included OpenAPI specification. Regenerate types and build the library with:
# regenerate types from OpenAPI
npm run generate:types
# build all bundles (CJS/ESM/UMD + d.ts)
npm run build
# or build only browser-targeted bundles
npm run build:browserThe build process will output files to dist/ including index.d.ts for TypeScript consumers.
import { WAHAClient } from 'waha-api-client-ts';
// Initialize client with default configuration
const client = new WAHAClient({
baseURL: 'https://your-waha-instance.com',
apiKey: 'your-api-key',
session: 'default',
timeout: 30000,
retryAttempts: 3,
retryDelay: 1000,
});
// Send a text message
await client.sendText({
chatId: '1234567890@c.us',
text: 'Hello from WAHA!',
});When initializing the client, you can set default values:
const client = new WAHAClient({
baseURL: 'https://your-waha-instance.com', // Required: Your WAHA API base URL
apiKey: 'your-api-key', // Optional: API key for authentication
session: 'default', // Optional: Default session name (default: 'default')
timeout: 30000, // Optional: Request timeout in ms (default: 30000)
retryAttempts: 3, // Optional: Number of retry attempts (default: 3)
retryDelay: 1000, // Optional: Delay between retries in ms (default: 1000)
});You can override configuration for individual API calls:
await client.sendText({
chatId: '1234567890@c.us',
text: 'Hello!',
config: {
session: 'custom-session', // Override session for this request
timeout: 60000, // Override timeout for this request
retryAttempts: 5, // Override retry attempts
retryDelay: 2000, // Override retry delay
},
});To prevent your WhatsApp account from being blocked, it's recommended to check if a number is registered on WhatsApp before sending messages. This library provides "safe send" methods that automatically implement WhatsApp's anti-blocking best practices.
When you send messages to numbers that don't exist on WhatsApp, it can lead to your account being flagged or blocked. Safe send methods help prevent this by implementing the following anti-blocking measures:
- Number Verification: Checks if the number is registered on WhatsApp before sending
- Seen Receipt: Sends a "seen" indicator to appear more human-like
- Typing Indicators: Shows "typing..." with realistic delays based on message type and length
- Random Delays: Adds random delays between actions to simulate human behavior
- Smart Timing: Calculates appropriate delays based on message length (1-5 seconds for text, 2-6 seconds for media)
These methods return null if the number doesn't exist, preventing failed delivery attempts that could flag your account.
Delay Timings:
- Text messages: 1-5 seconds (calculated based on message length)
- Images: 2-4 seconds
- Videos: 3-6 seconds
- Files: 2-5 seconds
- Voice, Location, Contacts, Buttons, Lists, Polls: 1.5-3 seconds
All safe send methods follow the same pattern: they check the number status first, then send only if the number exists.
safeSendText()- Safe version ofsendText()safeSendImage()- Safe version ofsendImage()safeSendFile()- Safe version ofsendFile()safeSendVoice()- Safe version ofsendVoice()safeSendVideo()- Safe version ofsendVideo()safeSendLocation()- Safe version ofsendLocation()safeSendContactVcard()- Safe version ofsendContactVcard()safeSendLinkPreview()- Safe version ofsendLinkPreview()safeSendButtons()- Safe version ofsendButtons()safeSendList()- Safe version ofsendList()safeSendPoll()- Safe version ofsendPoll()
When you call a safe send method, the following sequence occurs automatically:
- Verify Number: Check if the recipient's number exists on WhatsApp
- Send Seen: Mark the chat as "seen" (if applicable)
- Start Typing: Show typing indicator in the chat
- Wait: Realistic delay based on message type (see "Delay Timings" above: 1-6 seconds depending on content)
- Stop Typing: Hide typing indicator
- Send Message: Deliver the actual message
This mimics human behavior and significantly reduces the risk of being flagged as a bot or spam account.
// Safe send text message with anti-blocking measures
const result = await client.safeSendText({
chatId: '1234567890@c.us',
text: 'Hello! How are you?',
});
if (result === null) {
console.log('Number does not exist on WhatsApp - message not sent');
} else {
console.log('Message sent successfully with anti-blocking measures:', result);
}
// Safe send image with anti-blocking measures
const imageResult = await client.safeSendImage({
chatId: '1234567890@c.us',
file: 'https://example.com/image.jpg',
caption: 'Check this out!',
});
if (imageResult === null) {
console.log('Number does not exist on WhatsApp - image not sent');
} else {
console.log('Image sent successfully:', imageResult);
}
// Safe send file with anti-blocking measures
const fileResult = await client.safeSendFile({
chatId: '1234567890@c.us',
file: 'https://example.com/document.pdf',
filename: 'document.pdf',
caption: 'Important document',
});
if (fileResult === null) {
console.log('Number does not exist on WhatsApp - file not sent');
} else {
console.log('File sent successfully:', fileResult);
}Following WhatsApp's guidelines to avoid getting blocked:
✅ DO:
- Use safe send methods for new/unknown contacts
- Add random delays between messages (the safe send methods do this automatically)
- Only reply to messages, never initiate conversations with strangers
- Send personalized messages that vary in content
- Respect rate limits (maximum 4 messages per hour per contact is a safe guideline - exceeding this may trigger spam detection)
- Have a profile picture and status
- Use HTTPS URLs and avoid previously marked spam links
❌ DON'T:
- Send messages to numbers not on WhatsApp
- Send bulk messages without delays
- Use the same message template repeatedly
- Send messages 24/7 without breaks
- Send long texts or multiple messages to new contacts
- Ignore user reports (if users block/report you, stop messaging them)
-
Use Safe Send when:
- Sending to numbers from external sources (databases, forms, APIs)
- You're not sure if the number is on WhatsApp
- You want maximum protection against blocking
- You're doing any form of bulk messaging
- Initiating conversations with new contacts
- Building a bot or automated system
-
Use Regular Send when:
- Sending to group chats (groups don't need number verification)
- Replying to received messages (they initiated the conversation)
- You're certain the number exists and you have an ongoing conversation
- You need minimal latency and have already verified the number
- Sending to your own saved contacts from your phone
This client implements all 147 WAHA API endpoints organized into the following categories:
getQR()- Get QR code for pairingrequestCode()- Request authentication code
getSessions()- Get all sessionsgetSession()- Get session infocreateSession()- Create new sessionupdateSession()- Update session configdeleteSession()- Delete sessionstartSession()/startSessionAlt()- Start sessionstopSession()/stopSessionAlt()- Stop sessionlogoutSession()/logoutSessionBulk()- Logout sessionrestartSession()- Restart sessiongetSessionMe()- Get session "me" info
getProfile()- Get my profilesetProfileName()- Set profile namesetProfileStatus()- Set profile statussetProfilePicture()- Set profile picturedeleteProfilePicture()- Delete profile picture
sendText()/sendTextAlt()/sendTextGet()- Send text messagesendImage()/sendImageAlt()- Send imagesendFile()/sendFileAlt()- Send filesendVoice()- Send voice messagesendVideo()- Send videosendButtons()- Send buttonssendList()- Send list messagesendPoll()- Send pollsendPollVote()- Vote in pollsendLocation()- Send locationsendContactVcard()- Send contact vCardsendLinkPreview()- Send link with previewsendLinkCustomPreview()- Send link with custom previewforwardMessage()- Forward messagereply()- Reply to messagereplyButton()- Reply to buttonsendSeen()- Mark as seenstartTyping()- Start typing indicatorstopTyping()- Stop typing indicatorreaction()- React to messagestar()- Star/unstar messagegetMessages()/getMessagesAlt()- Get messagescheckNumberStatus()- Check if number is on WhatsApp
We made the client follow the OpenAPI canonical endpoints for sending messages. Concretely:
- The library now uses the documented POST endpoints such as
POST /api/sendText,POST /api/sendImage,POST /api/sendFile,POST /api/sendVoice, andPOST /api/sendVideoand includes the requiredsessionfield in the request body when calling those endpoints. - Legacy/alternative helpers (for example
sendTextGet(),getMessagesAlt(),sendTextAlt()) remain in the client for backwards compatibility but are annotated as deprecated in the source. Prefer the modern methods such assendText()andgetMessages(chatId).
If you previously relied on internal session-prefixed send URLs (e.g. /api/{session}/messages/text), update your calls to use the canonical methods above. If you need the library to retain automatic fallback to legacy endpoints (try canonical first, fallback to legacy), tell me and I can add graceful retry/fallback behavior.
getChats()- Get all chatsgetChatsOverview()- Get chats overviewcreateChatsOverview()- Create chats overviewdeleteChat()- Delete chatgetChatPicture()- Get chat picturegetMessage()- Get specific messagedeleteMessage()- Delete messageeditMessage()- Edit messagedeleteAllMessages()- Delete all messagesreadMessages()- Mark messages as readpinMessage()- Pin messageunpinMessage()- Unpin messagearchiveChat()- Archive chatunarchiveChat()- Unarchive chatmarkChatUnread()- Mark chat as unread
getChannels()- Get all channelscreateChannel()- Create channelgetChannel()- Get channel by IDdeleteChannel()- Delete channelgetChannelMessagesPreview()- Get messages previewfollowChannel()- Follow channelunfollowChannel()- Unfollow channelmuteChannel()- Mute channelunmuteChannel()- Unmute channelsearchChannelsByView()- Search channels by viewsearchChannelsByText()- Search channels by textgetChannelSearchViews()- Get search viewsgetChannelSearchCountries()- Get search countriesgetChannelSearchCategories()- Get search categories
postTextStatus()- Post text statuspostImageStatus()- Post image statuspostVoiceStatus()- Post voice statuspostVideoStatus()- Post video statusdeleteStatus()- Delete statusgetNewMessageId()- Get new message ID
getLabels()- Get all labelscreateLabel()- Create labelupdateLabel()- Update labeldeleteLabel()- Delete labelgetChatLabels()- Get labels for chatsetChatLabels()- Set labels for chatgetChatsByLabel()- Get chats by label
getAllContacts()- Get all contactsgetContact()- Get contact infocheckContactExists()- Check if contact existsgetContactAbout()- Get contact aboutgetContactProfilePicture()- Get contact profile pictureblockContact()- Block contactunblockContact()- Unblock contactupdateContact()- Update contactgetLids()- Get LIDsgetLidsCount()- Get LIDs countgetLid()- Get LID by IDgetLidByPhone()- Get LID by phone
createGroup()- Create groupgetGroups()- Get all groupsgetGroup()- Get group by IDdeleteGroup()- Delete groupgetGroupsCount()- Get groups countrefreshGroups()- Refresh groupsgetGroupJoinInfo()- Get group join infojoinGroup()- Join groupleaveGroup()- Leave groupgetGroupPicture()- Get group picturesetGroupPicture()- Set group picturedeleteGroupPicture()- Delete group picturesetGroupDescription()- Set group descriptionsetGroupSubject()- Set group subjectgetGroupInfoAdminOnly()- Get info admin only settingsetGroupInfoAdminOnly()- Set info admin onlygetGroupMessagesAdminOnly()- Get messages admin only settingsetGroupMessagesAdminOnly()- Set messages admin onlygetGroupInviteCode()- Get invite coderevokeGroupInviteCode()- Revoke invite codegetGroupParticipants()- Get participantsaddGroupParticipants()- Add participantsremoveGroupParticipants()- Remove participantspromoteGroupParticipant()- Promote to admindemoteGroupParticipant()- Demote from admin
setPresence()- Set presencegetAllPresence()- Get all presence infogetPresence()- Get presence for chatsubscribePresence()- Subscribe to presence
ping()- Ping endpointhealth()- Health checkgetVersion()- Get API versiongetServerVersion()- Get server versiongetServerEnvironment()- Get server environmentgetServerStatus()- Get server statusstopServer()- Stop servergetHeapSnapshot()- Get heap snapshotgetBrowserTrace()- Get browser trace
convertToVoice()- Convert audio to voice formatconvertVideo()- Convert video
takeScreenshot()- Take screenshot
sendEvent()- Send event
getApps()- Get all appscreateApp()- Create appgetApp()- Get app by IDupdateApp()- Update appdeleteApp()- Delete appgetChatwootLocales()- Get Chatwoot locales
await client.sendText({
chatId: '1234567890@c.us',
text: 'Hello, World!',
reply_to: 'message-id', // Optional: Reply to a specific message
config: { ... }, // Optional: Override config
});await client.sendImage({
chatId: '1234567890@c.us',
file: 'https://example.com/image.jpg', // URL or base64
caption: 'Check this out!', // Optional
reply_to: 'message-id', // Optional
config: { ... }, // Optional
});await client.sendFile({
chatId: '1234567890@c.us',
file: 'https://example.com/document.pdf',
filename: 'document.pdf', // Optional
caption: 'Important document', // Optional
reply_to: 'message-id', // Optional
config: { ... }, // Optional
});// Create a group
const groupResponse = await client.createGroup({
name: 'My Group',
participants: ['1234567890@c.us', '0987654321@c.us']
});
// Add participants (use the group ID from the response)
const groupId = 'group-id@g.us'; // Extract from response
await client.addGroupParticipants(groupId, {
participants: ['1111111111@c.us']
});
// Promote to admin
await client.promoteGroupParticipant(groupId, {
participants: ['1234567890@c.us']
});const session = await client.getSession({
session: 'custom-session', // Optional: Override session
});const session = await client.startSession({
session: 'new-session', // Optional: Override session to start
});await client.stopSession({
session: 'session-to-stop', // Optional: Override session
});const sessions = await client.getSessions();const chats = await client.getChats({
session: 'custom-session', // Optional: Override session
});const messages = await client.getMessages('1234567890@c.us', {
session: 'custom-session', // Optional: Override session
});const status = await client.checkNumberStatus('1234567890', {
session: 'custom-session', // Optional: Override session
});
console.log(status.exists); // true if number is on WhatsAppYou can work with multiple WhatsApp sessions using the same client:
const client = new WAHAClient({
baseURL: 'https://your-waha-instance.com',
apiKey: 'your-api-key',
session: 'default',
});
// Send from default session
await client.sendText({
chatId: '1234567890@c.us',
text: 'From default session',
});
// Send from a different session
await client.sendText({
chatId: '1234567890@c.us',
text: 'From custom session',
config: { session: 'session-2' },
});Adjust retry behavior for specific operations:
// For a critical message that needs more retries
await client.sendText({
chatId: '1234567890@c.us',
text: 'Important message',
config: {
retryAttempts: 10,
retryDelay: 5000,
},
});
// For a quick operation with no retries
await client.sendText({
chatId: '1234567890@c.us',
text: 'Quick message',
config: {
retryAttempts: 0,
},
});try {
await client.sendText({
chatId: '1234567890@c.us',
text: 'Hello!',
});
} catch (error) {
console.error('Failed to send message:', error);
}The library exports TypeScript types for all configurations and responses:
import type {
WAHAConfig,
RequestConfig,
SendTextParams,
SendImageParams,
SendFileParams,
SessionInfo,
ChatInfo,
MessageInfo,
APIResponse,
} from 'waha-api-client-ts';See src/example.ts for code examples and src/demo.ts for a complete feature demonstration.
To run the demo:
npm install
npx tsx src/demo.tsOnce deployed, the API documentation will be available at:
- GitHub Pages:
https://myusp.github.io/waha-api-client-ts/
You can also generate documentation locally:
npm run docs
# Documentation will be generated in the ./docs directoryISC
Contributions are welcome! Please feel free to submit a Pull Request.
This is an unofficial client library for WAHA API. It is not affiliated with or endorsed by the WAHA project.
USE AT YOUR OWN RISK: This software is provided "as is" without warranty of any kind, either expressed or implied. The authors and contributors are not responsible for any damages, data loss, account bans, or other issues that may arise from using this library. You are solely responsible for ensuring your use complies with WhatsApp's Terms of Service and applicable laws. By using this library, you acknowledge and accept all risks associated with automated messaging and API usage.