@gamastudio/sendwave-provider
v1.0.5
Published
Official Sendwaves provider for BuilderBot. Multi-instance WhatsApp messaging library with intelligent message merging, media support, interactive buttons, lists, carousels, polls, and automatic queue flow.
Downloads
559
Maintainers
Readme
📖 Sendwaves Provider
A dynamic library for integrating and managing Sendwave instances for WhatsApp bot development.
🚀 Installation
npm install @gamastudio/sendwave-provider🔧 Basic Usage
Creating a Provider Instance
import { createSendWaveProvider } from "@gamastudio/sendwave-provider";
const provider = createSendWaveProvider({
name: "MyBot",
apiKey: "your-api-key-here",
port: 3000,
});
// Initialize the provider
await provider.initAll(provider.globalVendorArgs.port);Multi-Tenant: Multiple Instances with One Webhook
You can manage multiple Sendwave instances with a single provider. The webhook will route messages automatically based on instanceName in the payload.
import { createSendWaveProvider } from "@gamastudio/sendwave-provider";
const provider = createSendWaveProvider({
port: 3000,
url: "https://msg.sendwaves.cloud",
instances: [
{ name: "bot-sales", apiKey: "api-key-sales" },
{ name: "bot-support", apiKey: "api-key-support" },
{ name: "bot-marketing", apiKey: "api-key-marketing" },
],
});
await provider.initAll(provider.globalVendorArgs.port);
// Send message to a specific instance
await provider.sendText(
{ from: "573123456789", text: "Hello from sales!" },
{ instance: "bot-sales" }
);
// Notify admin on another instance
await provider.sendText(
{ from: "573199999999", text: "Nuevo pedido recibido" },
{ instance: "bot-admin" }
);
// Or use the default (first instance)
await provider.sendText({
from: "573123456789",
text: "Hello!",
});
// List registered instances
console.log(provider.getInstances().map((i) => i.name));Webhook routing: the provider reads instanceName from body.instanceName, body.inputs.instanceName, or body.instance.name. Point all your Sendwave webhooks to the same /webhook URL.
QR / State per instance:
/qr→ default instance/qr/bot-sales→ specific instance/state→ default instance/state/bot-sales→ specific instance
⚙️ Configuration
const provider = createSendWaveProvider({
name: "MyBot",
apiKey: "your-api-key-here",
url: "https://msg.sendwaves.cloud", // Optional
port: 3000,
host: "0.0.0.0",
readMessages: true, // Auto-mark incoming messages as read
message: {
mergeMessage: true, // Merge rapid messages from same user
timeMergeMessage: 3, // Base wait time in seconds
maxWaitTime: 30, // Maximum wait time in seconds
shortMessageThreshold: 10, // Short messages merge faster
adaptiveTimer: true, // Smart timing based on message patterns
},
queueFlow: {
enabled: true,
warningTimeout: 30 * 60 * 1000, // 30 minutes
endTimeout: 2 * 60 * 1000, // 2 minutes after warning
},
payloadLimits: {
json: "50mb",
urlencoded: "50mb",
text: "10mb",
media: {
image: "10mb",
video: "100mb",
audio: "50mb",
document: "25mb",
},
},
});📤 Sending Messages
Text Messages
await provider.sendText({
from: "573123456789",
text: "Hello! Welcome to our service.",
delay: 2000, // Optional typing delay
});
// Send to a specific instance (multi-tenant)
await provider.sendText(
{ from: "573123456789", text: "Hello!" },
{ instance: "bot-sales" }
);Presence Indicators
await provider.sendPresence({
from: "573123456789",
presence: "composing", // or "recording"
delay: 2000,
});Media Messages
// Image
await provider.sendImage({
from: "573123456789",
url: "https://example.com/image.jpg",
text: "Optional caption",
});
// Video
await provider.sendVideo({
from: "573123456789",
url: "https://example.com/video.mp4",
text: "Optional caption",
});
// Document/File
await provider.sendFile({
from: "573123456789",
url: "https://example.com/file.pdf",
fileName: "document.pdf",
text: "Optional caption",
});
// Audio
await provider.sendAudio({
from: "573123456789",
url: "https://example.com/audio.mp3",
});
// Voice message (PTT)
await provider.sendVoice({
from: "573123456789",
url: "https://example.com/voice.ogg",
});Interactive Buttons
The provider accepts multiple formats for buttons.
// 1. Super Simple (Quick Replies)
await provider.sendButton({
from: "573123456789",
title: "Main Menu",
body: "Select an option",
footer: "Sendwaves Provider",
buttons: ["🛒 Catalog", "🎁 Promotions", "📞 Support"]
});
// 2. Mixed Format (Text & Functional buttons)
await provider.sendButton({
from: "573123456789",
title: "Payment Options",
body: "Select your preferred method",
buttons: [
{ type: "reply", displayText: "Cash" },
{ type: "url", displayText: "Visit Web", url: "https://example.com" },
{ type: "call", displayText: "Call Us", phoneNumber: "+573123456789" },
{ type: "copy", displayText: "Copy Coupon", copyText: "SAVE20" },
{ type: "pix", displayText: "Pay with Pix", keyType: "email", key: "[email protected]" }
]
});Supported Button Types:
reply: Standard quick reply button.url: Opens a website.call: Triggers a phone call.copy: Copies text or code to clipboard.pix: Brazilian payment system integration.
Carousel Messages
Send a scrollable carousel with multiple cards. Each card supports its own buttons.
await provider.sendCarousel({
from: "573123456789",
title: "Featured Products",
description: "Swipe to see our best offers",
footer: "Sendwaves Store",
cards: [
{
text: "Premium Plan",
thumbnailUrl: "https://example.com/plan1.jpg",
footerText: "Best value",
buttons: [
{ type: "reply", displayText: "Buy Now" },
{ type: "url", displayText: "More Info", url: "https://example.com/plan1" }
]
},
{
text: "Basic Plan",
thumbnailUrl: "https://example.com/plan2.jpg",
footerText: "Affordable",
buttons: [
{ type: "reply", displayText: "Buy Now" }
]
}
],
delay: 2000
});Interactive Lists
// Simple List (Array of strings)
await provider.sendList({
from: "573123456789",
list: {
title: "Select an option",
button: "View Options",
content: ["Option 1", "Option 2", "Option 3"],
},
});
// Advanced List with sections
await provider.sendList({
from: "573123456789",
list: {
title: "Product Categories",
description: "Choose a category",
button: "Select Category",
footerText: "Sendwaves Provider",
content: [
{
title: "Electronics",
rows: [
{ title: "Smartphones", description: "Latest models" },
{ title: "Laptops", description: "Gaming and office" },
],
},
],
},
});Polls
await provider.sendPoll({
from: "573123456789",
poll: {
name: "¿Qué te parece el nuevo proveedor?",
values: ["Excelente", "Bueno", "Mejorable"],
selectableCount: 1 // Optional, default: 1
}
});Locations
await provider.sendLocation({
from: "573123456789",
name: "Our Office",
address: "123 Main St, Bogotá",
latitude: 4.711,
longitude: -74.0721,
});Reactions
await provider.sendReaction({
key: {
remoteJid: "[email protected]",
fromMe: false,
id: "MESSAGE_ID",
},
reaction: "👍",
});Mark as Read
await provider.readMessages({
from: "[email protected]",
messageId: "MESSAGE_ID",
});🧠 Intelligent Message Merging
When mergeMessage is enabled, rapid messages from the same user are merged into a single message.
const provider = createSendWaveProvider({
message: {
mergeMessage: true,
timeMergeMessage: 4,
maxWaitTime: 30,
shortMessageThreshold: 10,
adaptiveTimer: true,
}
});Example:
- User sends "Hola" then "como estas"
- Result: single message with body
"Hola como estas"
🔄 Queue Flow System
Automatic session management for inactive users.
const provider = createSendWaveProvider({
queueFlow: {
enabled: true,
warningTimeout: 30 * 60 * 1000, // 30 mins
endTimeout: 2 * 60 * 1000, // 2 mins after warning
warningMessage: "⏳ You seem inactive. Still there?",
},
});
// Listen to inactivity events
provider.onQueueFlowEvent("userInactive-573123456789", (data) => {
console.log(data.isActive ? "User warned" : "Session ended");
});🎯 Event System
provider.on("ready", (isReady) => console.log("Connected:", isReady));
provider.on("message", (ctx) => console.log(`From ${ctx.from}: ${ctx.body}`));
provider.on("user-message", (data) => console.log("User message:", data));
provider.on("flow-message", (data) => console.log("Flow message:", data));
provider.on("auth_failure", (payload) => console.error("Auth failed:", payload));
provider.on("notice", ({ title, instructions }) => console.log(title, instructions));🏗️ Architecture
The project is organized in modular layers:
config/: Default values and constants.domain/: Pure types and interfaces.infrastructure/: HTTP client, API repository, media detection, message parser.application/: Business logic: message strategies, buffer merging, connection polling, queue flow.presentation/: Provider and core classes, HTML pages.shared/: Common utilities and exceptions.
Adding a New Message Type
- Create a strategy in
src/application/messaging/strategies/. - Implement the
SendStrategy<T>interface. - Register it in
MessageSenderService. - Add the public method to
SendWaveProvider. - Add the type to
ProviderInterfaceandmessage.types.ts.
📜 License
ISC License © 2026 - Ameth Galarcio
