npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@gymspace/evolution

v1.7.1

Published

Unofficial SDK for the Evolution Whatsapp API v2

Readme

Installation

npm install @gymspace/evolution
// or
yarn add @gymspace/evolution
// or
bun add @gymspace/evolution

Getting Started

import { EvolutionClient } from "@gymspace/evolution";

const client = new EvolutionClient({
  serverUrl: "Your server url",
  token: "Global api key or instance token",
  instance: "Your instance", // optional
});

Usage Examples

Sending a Text Message

client.setInstance("my-instance-01");

await client.messages.sendText({
  number: "5511999999999",
  text: "Hello from the SDK!",
});

Using Different Instances

You can override the default instance for any method call:

// Send message using a different instance
await client.messages.sendText(
  {
    number: "5511999999999",
    text: "Hello from another instance!",
  },
  { instance: "different-instance-name" }
);

// Check numbers on a specific instance
await client.chats.check(["5511999999999"], { instance: "my-instance" });

// Works with all methods across all modules
await client.groups.create(
  {
    subject: "My Group",
    participants: ["5511999999999"],
  },
  { instance: "work-instance" }
);

await client.profile.updateName(
  {
    name: "New Name",
  },
  { instance: "personal-instance" }
);

Sending an Image

await client.messages.sendImage({
  number: "5511999999999",
  image: "https://i.imgur.com/REo1ODy.png",
  caption: "A cute cat",
});

Creating a Group

await client.groups.create({
  subject: "My Awesome Group",
  participants: ["5511999999999", "5522988888888"],
});

Checking if a Number has WhatsApp

const result = await client.chats.check(["5511999999999"]);
console.log(result);
// [{ jid: '[email protected]', exists: true }]

API Reference

💡 Pro Tip: All methods support an optional { instance: "instance-name" } parameter to override the default instance.

🔧 Instance Management

Create Instance

Basic Instance Creation
await client.instance.create({
  instanceName: "my-bot",
  token: "optional-token",
});
Comprehensive Instance Creation
await client.instance.create({
  instanceName: "my-advanced-bot",
  token: "your-secure-api-token",
  qrcode: true,
  number: "5511999999999",
  integration: "WHATSAPP-BAILEYS",
  webhook: "https://your-domain.com/webhook",
  webhook_by_events: true,
  events: [
    "APPLICATION_STARTUP",
    "QRCODE_UPDATED",
    "CONNECTION_UPDATE",
    "MESSAGES_UPSERT",
    "MESSAGES_UPDATE",
    "CONTACTS_UPSERT"
  ],
  reject_call: true,
  msg_call: "Sorry, I can't take calls right now. Please send a message.",
  groups_ignore: false,
  always_online: true,
  read_messages: true,
  read_status: true,
  websocket_enabled: false,
  websocket_events: ["APPLICATION_STARTUP"],
  rabbitmq_enabled: false,
  rabbitmq_events: ["APPLICATION_STARTUP"],
  sqs_enabled: false,
  sqs_events: ["APPLICATION_STARTUP"],
  typebot_url: "https://your-typebot-instance.com",
  typebot: "customer-service-flow",
  typebot_expire: 300,
  typebot_keyword_finish: "exit",
  typebot_delay_message: 1000,
  typebot_unknown_message: "I didn't understand. Can you rephrase?",
  typebot_listening_from_me: false,
  proxy: {
    host: "proxy.example.com",
    port: "8080",
    protocol: "http",
    username: "proxy-user",
    password: "proxy-password"
  },
  chatwoot_account_id: 12345,
  chatwoot_token: "your-chatwoot-token",
  chatwoot_url: "https://your-chatwoot-instance.com",
  chatwoot_sign_msg: true,
  chatwoot_reopen_conversation: true,
  chatwoot_conversation_pending: false
});
Instance Creation Parameters

| Parameter | Type | Required | Default | Description | |-----------|------|----------|---------|-------------| | instanceName | string | Yes | - | Unique name for your instance | | token | string | No | Auto-generated | API token for the instance | | qrcode | boolean | No | true | Generate QR code automatically after creation | | number | string | No | - | Instance owner number with country code (e.g., "5511999999999") | | integration | enum | No | "WHATSAPP-BAILEYS" | WhatsApp engine to use. Options: WHATSAPP-BAILEYS, WHATSAPP-BUSINESS | | webhook | string | No | - | Webhook URL to receive events | | webhook_by_events | boolean | No | true | Enable webhook by events | | events | enum[] | No | ["APPLICATION_STARTUP"] | Events to send to webhook | | reject_call | boolean | No | false | Reject WhatsApp calls automatically | | msg_call | string | No | "" | Message to send when rejecting calls | | groups_ignore | boolean | No | true | Ignore group messages | | always_online | boolean | No | false | Keep WhatsApp always online | | read_messages | boolean | No | false | Send read receipts for received messages | | read_status | boolean | No | false | Show read status for sent messages | | websocket_enabled | boolean | No | false | Enable WebSocket connection | | websocket_events | enum[] | No | ["APPLICATION_STARTUP"] | Events to send via WebSocket | | rabbitmq_enabled | boolean | No | false | Enable RabbitMQ integration | | rabbitmq_events | enum[] | No | ["APPLICATION_STARTUP"] | Events to send to RabbitMQ | | sqs_enabled | boolean | No | false | Enable SQS integration | | sqs_events | enum[] | No | ["APPLICATION_STARTUP"] | Events to send to SQS | | typebot_url | string | No | - | URL for the Typebot instance | | typebot | string | No | - | Typebot flow name | | typebot_expire | integer | No | - | Seconds to expire Typebot session | | typebot_keyword_finish | string | No | - | Keyword to finish the Typebot flow | | typebot_delay_message | integer | No | - | Default delay for Typebot messages (ms) | | typebot_unknown_message | string | No | - | Message for unrecognized input | | typebot_listening_from_me | boolean | No | - | Whether Typebot listens to own messages | | proxy.host | string | No | - | Proxy server host | | proxy.port | string | No | - | Proxy server port | | proxy.protocol | enum | No | "http" | Proxy protocol (http/https) | | proxy.username | string | No | - | Proxy authentication username | | proxy.password | string | No | - | Proxy authentication password | | chatwoot_account_id | integer | No | - | Chatwoot account ID | | chatwoot_token | string | No | - | Chatwoot authentication token | | chatwoot_url | string | No | - | Chatwoot server URL | | chatwoot_sign_msg | boolean | No | true | Send message signature on Chatwoot | | chatwoot_reopen_conversation | boolean | No | true | Reopen conversation on Chatwoot | | chatwoot_conversation_pending | boolean | No | true | Mark conversation as pending |

Available Events

You can configure the following events for webhooks, WebSocket, RabbitMQ, and SQS:

  • APPLICATION_STARTUP - API startup event
  • QRCODE_UPDATED - QR code update event
  • CONNECTION_UPDATE - Connection status change event
  • MESSAGES_SET - Initial message load event
  • MESSAGES_UPSERT - New message event
  • MESSAGES_UPDATE - Message status update event
  • MESSAGES_DELETE - Message deletion event
  • SEND_MESSAGE - Message sending event
  • CONTACTS_SET - Initial contacts load event
  • CONTACTS_UPSERT - New contact event
  • CONTACTS_UPDATE - Contact update event
  • PRESENCE_UPDATE - User presence change event
  • CHATS_SET - Initial chats load event
  • CHATS_UPDATE - Chat update event
  • CHATS_UPSERT - New chat event
  • CHATS_DELETE - Chat deletion event
  • GROUPS_UPSERT - New group event
  • GROUPS_UPDATE - Group update event
  • GROUP_PARTICIPANTS_UPDATE - Group member change event
  • NEW_TOKEN - JWT token update event
Response Structure

The instance creation returns a comprehensive response with the following structure:

{
  instance: {
    instanceName: string,
    instanceId: string,
    webhook_wa_business: string | null,
    access_token_wa_business: string,
    status: "created" | "connected" | "disconnected"
  },
  hash: {
    apikey: string
  },
  settings: {
    reject_call: boolean,
    msg_call: string,
    groups_ignore: boolean,
    always_online: boolean,
    read_messages: boolean,
    read_status: boolean,
    sync_full_history: boolean
  }
}
Authentication Requirements

All instance creation requests require authentication via:

const client = new EvolutionClient({
  serverUrl: "https://your-evolution-server.com",
  token: "your-global-api-key"
});

The token can be either:

  • A global API key with admin privileges
  • An instance-specific token (for existing instances)
Integration Examples
Typebot Integration
await client.instance.create({
  instanceName: "typebot-instance",
  token: "your-token",
  webhook: "https://your-domain.com/webhook",
  typebot_url: "https://your-typebot.com",
  typebot: "customer-support",
  typebot_expire: 300,
  typebot_keyword_finish: "exit,stop,end",
  typebot_delay_message: 1500,
  typebot_unknown_message: "I'm sorry, I didn't understand. Can you please rephrase?",
  typebot_listening_from_me: false
});
Chatwoot Integration
await client.instance.create({
  instanceName: "chatwoot-instance",
  token: "your-token",
  webhook: "https://your-domain.com/webhook",
  chatwoot_account_id: 12345,
  chatwoot_token: "your-chatwoot-api-token",
  chatwoot_url: "https://your-chatwoot-instance.com",
  chatwoot_sign_msg: true,
  chatwoot_reopen_conversation: true,
  chatwoot_conversation_pending: false
});
RabbitMQ Integration
await client.instance.create({
  instanceName: "rabbitmq-instance",
  token: "your-token",
  rabbitmq_enabled: true,
  rabbitmq_events: [
    "MESSAGES_UPSERT",
    "CONNECTION_UPDATE",
    "CONTACTS_UPSERT"
  ]
});
SQS Integration
await client.instance.create({
  instanceName: "sqs-instance",
  token: "your-token",
  sqs_enabled: true,
  sqs_events: [
    "MESSAGES_UPSERT",
    "CONNECTION_UPDATE",
    "CONTACTS_UPSERT"
  ]
});
Webhook Configuration Examples
Basic Webhook Setup
await client.instance.create({
  instanceName: "webhook-instance",
  token: "your-token",
  webhook: "https://your-domain.com/webhook",
  webhook_by_events: true,
  events: [
    "MESSAGES_UPSERT",
    "CONNECTION_UPDATE",
    "CONTACTS_UPSERT"
  ]
});
Advanced Webhook with All Events
await client.instance.create({
  instanceName: "full-webhook-instance",
  token: "your-token",
  webhook: "https://your-domain.com/webhook",
  webhook_by_events: true,
  events: [
    "APPLICATION_STARTUP",
    "QRCODE_UPDATED",
    "CONNECTION_UPDATE",
    "MESSAGES_SET",
    "MESSAGES_UPSERT",
    "MESSAGES_UPDATE",
    "MESSAGES_DELETE",
    "SEND_MESSAGE",
    "CONTACTS_SET",
    "CONTACTS_UPSERT",
    "CONTACTS_UPDATE",
    "PRESENCE_UPDATE",
    "CHATS_SET",
    "CHATS_UPDATE",
    "CHATS_UPSERT",
    "CHATS_DELETE",
    "GROUPS_UPSERT",
    "GROUPS_UPDATE",
    "GROUP_PARTICIPANTS_UPDATE",
    "NEW_TOKEN"
  ]
});
Use Case Examples
Customer Service Bot
await client.instance.create({
  instanceName: "customer-service",
  token: "secure-token",
  number: "5511999999999",
  webhook: "https://your-crm.com/webhook",
  webhook_by_events: true,
  events: ["MESSAGES_UPSERT", "CONTACTS_UPSERT"],
  reject_call: true,
  msg_call: "Please use our chat service. We don't accept calls.",
  groups_ignore: true,
  always_online: true,
  read_messages: true,
  read_status: true,
  chatwoot_account_id: 12345,
  chatwoot_token: "chatwoot-token",
  chatwoot_url: "https://chatwoot.your-crm.com",
  chatwoot_sign_msg: true,
  chatwoot_reopen_conversation: true
});
Notification Bot
await client.instance.create({
  instanceName: "notification-bot",
  token: "notification-token",
  webhook: "https://notification-service.com/webhook",
  webhook_by_events: true,
  events: ["CONNECTION_UPDATE", "MESSAGES_UPDATE"],
  qrcode: true,
  always_online: true,
  read_messages: false,
  read_status: true,
  groups_ignore: false,
  reject_call: true
});
E-commerce Bot with Typebot
await client.instance.create({
  instanceName: "ecommerce-bot",
  token: "ecommerce-token",
  number: "5511999999999",
  webhook: "https://ecommerce.com/webhook",
  typebot_url: "https://typebot.ecommerce.com",
  typebot: "shopping-assistant",
  typebot_expire: 600,
  typebot_keyword_finish: "checkout,exit,help",
  typebot_delay_message: 1200,
  typebot_unknown_message: "I'm here to help with your shopping. Can you tell me what you're looking for?",
  always_online: true,
  read_messages: true,
  read_status: true,
  reject_call: true,
  msg_call: "For assistance, please chat with us here. We don't accept calls."
});
High-Volume Instance with Queue
await client.instance.create({
  instanceName: "high-volume-bot",
  token: "high-volume-token",
  webhook: "https://high-volume-service.com/webhook",
  rabbitmq_enabled: true,
  rabbitmq_events: [
    "MESSAGES_UPSERT",
    "CONNECTION_UPDATE",
    "CONTACTS_UPSERT",
    "CHATS_UPSERT"
  ],
  always_online: true,
  read_messages: true,
  read_status: false,
  groups_ignore: false,
  reject_call: true,
  proxy: {
    host: "proxy.company.com",
    port: "8080",
    protocol: "https",
    username: "proxy-user",
    password: "proxy-pass"
  }
});

Setting the default Instance

await client.setInstance("InstanceName");

Connect to Instance

await client.instance.connect({ instanceName: "my-bot" });

Get Connection State

const state = await client.instance.connectionState({ instanceName: "my-bot" });

Manage Instance

// Logout
await client.instance.logout({ instanceName: "my-bot" });

// Restart
await client.instance.restart({ instanceName: "my-bot" });

// Delete
await client.instance.delete({ instanceName: "my-bot" });

// List all instances
const instances = await client.instance.fetchAll();

// Set presence
await client.instance.setPresence({
  instanceName: "my-bot",
  presence: "available",
});

💬 Chat Operations

Check WhatsApp Numbers

const result = await client.chats.check(["5511999999999", "5522888888888"]);
// Override instance: client.chats.check(numbers, { instance: "my-instance" })

Get All Chats

const chats = await client.chats.findAll();

Chat Actions

client.setInstance("my-instance-01");
// Update presence
await client.chats.updatePresence({
  number: "5511999999999",
  presence: "composing",
  delay: 1000,
});

// Mark as read
await client.chats.markAsRead({
  remoteJid: "[email protected]",
  fromMe: false,
  id: "message-id",
});

// Archive chat
await client.chats.archive({
  remoteJid: "[email protected]",
  archive: true,
});

Message Management

// Delete message
await client.chats.deleteMessage({
  remoteJid: "[email protected]",
  fromMe: true,
  id: "message-id",
});

// Find messages
const messages = await client.chats.findMessages({
  where: {
    key: {
      remoteJid: "[email protected]",
    },
  },
  offset: 10, // limit
  page: 1,
});

// Update message
await client.chats.updateMessage({
  remoteJid: "[email protected]",
  fromMe: true,
  id: "message-id",
  text: "Updated message",
});

// Get base64 from media message
const mediaBase64 = await client.chats.getBase64FromMediaMessage({
  message: {
    key: {
      id: "message-id",
    },
  },
  convertToMp4: true, // Optional: Convert video to MP4
});

// Response format:
// {
//   "mediaType": "audioMessage",
//   "fileName": "3A3B333C3EC7505284A8.oga",
//   "size": {"fileLength": "7905"},
//   "mimetype": "audio/mp4",
//   "base64": "AAAAIGZ0eXBpc2....=",
//   "buffer": null
// }

Contact & Profile

// Fetch profile picture
const profilePic = await client.chats.fetchProfilePicture({
  number: "5511999999999",
});

// Find contacts
const contacts = await client.chats.findContacts({
  where: { name: "John" },
});

📱 Messaging

Text Messages

await client.messages.sendText({
  number: "5511999999999",
  text: "Hello! 👋",
});

Media Messages

// Send image
await client.messages.sendImage({
  number: "5511999999999",
  image: "https://example.com/image.jpg",
  caption: "Check this out!",
});

// Send video
await client.messages.sendVideo({
  number: "5511999999999",
  video: "https://example.com/video.mp4",
  caption: "Amazing video!",
});

// Send document
await client.messages.sendDocument({
  number: "5511999999999",
  document: "https://example.com/document.pdf",
  fileName: "report.pdf",
});

// Send audio
await client.messages.sendAudio({
  number: "5511999999999",
  audio: "https://example.com/audio.mp3",
});

Interactive Messages

// Send location
await client.messages.sendLocation({
  number: "5511999999999",
  latitude: -23.5505,
  longitude: -46.6333,
  name: "São Paulo",
});

// Send contact
await client.messages.sendContact({
  number: "5511999999999",
  contact: [
    {
      fullName: "John Doe",
      phones: ["5511999999999"],
    },
  ],
});

// Send reaction
await client.messages.sendReaction({
  reactionMessage: {
    key: { remoteJid: "[email protected]", id: "message-id" },
    text: "👍",
  },
});

Advanced Messages

// Send list
await client.messages.sendList({
  number: "5511999999999",
  title: "Choose an option",
  description: "Select from the options below",
  sections: [
    {
      title: "Options",
      rows: [
        { title: "Option 1", description: "First option" },
        { title: "Option 2", description: "Second option" },
      ],
    },
  ],
});

// Send template
await client.messages.sendTemplate({
  number: "5511999999999",
  template: {
    name: "hello_world",
    language: { code: "en_US" },
  },
});

👥 Group Management

Group Operations

// Create group
await client.groups.create({
  subject: "My Awesome Group",
  participants: ["5511999999999", "5522888888888"],
});

// Get all groups
const groups = await client.groups.findAll(false); // without participants
const groupsWithMembers = await client.groups.findAll(true); // with participants

// Find group by invite code
const group = await client.groups.findByInviteCode("invite-code-here");

// Find group by JID
const group = await client.groups.findByJid("[email protected]");

Group Settings

// Update group subject
await client.groups.updateSubject({
  groupJid: "[email protected]",
  subject: "New Group Name",
});

// Update group description
await client.groups.updateDescription({
  groupJid: "[email protected]",
  description: "New group description",
});

// Update group picture
await client.groups.updatePicture({
  groupJid: "[email protected]",
  image: "https://example.com/group-pic.jpg",
});

Group Members

// Add/remove members
await client.groups.updateMembers({
  groupJid: "[email protected]",
  action: "add",
  participants: ["5511999999999"],
});

// Get group members
const members = await client.groups.findMembers({
  groupJid: "[email protected]",
});

// Leave group
await client.groups.leave({
  groupJid: "[email protected]",
});

Group Invites

// Get invite code
const inviteCode = await client.groups.fetchInviteCode({
  groupJid: "[email protected]",
});

// Revoke invite code
await client.groups.revokeInviteCode({
  groupJid: "[email protected]",
});

// Accept invite
await client.groups.acceptInviteCode({
  inviteCode: "invite-code-here",
});

👤 Profile Management

Profile Information

// Get profile
const profile = await client.profile.fetchProfile({
  number: "5511999999999",
});

// Get business profile
const businessProfile = await client.profile.fetchBusinessProfile({
  number: "5511999999999",
});

Update Profile

// Update name
await client.profile.updateName({
  name: "My New Name",
});

// Update status
await client.profile.updateStatus({
  status: "Hey there! I'm using WhatsApp",
});

// Update picture
await client.profile.updatePicture({
  picture: "https://example.com/my-photo.jpg",
});

// Remove picture
await client.profile.removePicture();

Privacy Settings

// Get privacy settings
const privacy = await client.profile.fetchPrivacySettings();

// Update privacy settings
await client.profile.updatePrivacySettings({
  privacySettings: {
    readReceipts: "all",
    profile: "contacts",
    status: "contacts",
    online: "all",
    last: "contacts",
    groupAdd: "contacts",
  },
});

⚙️ Settings & Webhooks

Instance Settings

// Get settings
const settings = await client.settings.find();

// Update settings
await client.settings.set({
  reject_call: true,
  msg_call: "Sorry, I can't take calls right now",
  groups_ignore: false,
});

Webhook Configuration

// Get webhook settings
const webhook = await client.webhook.find();

// Set webhook
await client.webhook.set({
  url: "https://your-webhook-url.com/webhook",
  webhook_by_events: true,
  events: ["MESSAGES_UPSERT", "CONNECTION_UPDATE"],
});

🔄 Instance Override Examples

You can override the default instance for any method:

// Send message with different instance
await client.messages.sendText(
  {
    number: "5511999999999",
    text: "Hello from work bot!",
  },
  { instance: "work-instance" }
);

// Check numbers on personal instance
await client.chats.check(["5511999999999"], { instance: "personal-bot" });

// Create group on specific instance
await client.groups.create(
  {
    subject: "Team Meeting",
    participants: ["5511999999999"],
  },
  { instance: "team-bot" }
);

🔗 Webhook Integration

The SDK provides complete TypeScript support for handling webhooks from the Evolution API.

Basic Webhook Setup

import express from "express";
import {
  WebhookData,
  WebhookEvent,
  WebhookEventSetup,
  MessagePayload,
  ContactPayload,
  ConnectionUpdatePayload,
} from "@gymspace/evolution";

const app = express();
app.use(express.json());

// Webhook endpoint
app.post("/webhook", async (req, res) => {
  try {
    const webhookData: WebhookData = req.body;
    await processWebhook(webhookData);
    res.status(200).send("OK");
  } catch (error) {
    console.error("Webhook processing error:", error);
    res.status(500).send("Error");
  }
});

app.listen(3000, () => {
  console.log("Webhook server running on port 3000");
});

Processing Webhook Events

async function processWebhook(webhookData: WebhookData): Promise<void> {
  const { event, instance, data } = webhookData;

  console.log(`[WEBHOOK] Event: ${event} | Instance: ${instance}`);

  switch (event) {
    case WebhookEvent.MESSAGES_UPSERT:
      await handleNewMessage(data as MessagePayload, instance);
      break;

    case WebhookEvent.MESSAGES_UPDATE:
      await handleMessageUpdate(data as MessagePayload, instance);
      break;

    case WebhookEvent.CONNECTION_UPDATE:
      await handleConnectionUpdate(data as ConnectionUpdatePayload);
      break;

    case WebhookEvent.CONTACTS_UPSERT:
    case WebhookEvent.CONTACTS_UPDATE:
      await handleContact(data as ContactPayload, instance);
      break;

    case WebhookEvent.QRCODE_UPDATED:
      console.log(`[WEBHOOK] QR Code updated for instance: ${instance}`);
      break;

    default:
      console.log(`[WEBHOOK] Unhandled event: ${event}`);
  }
}

Message Handling Examples

async function handleNewMessage(
  messageData: MessagePayload,
  instance: string
): Promise<void> {
  const { key, message, pushName } = messageData;

  // Skip messages from groups (optional)
  if (key.remoteJid?.includes("@g.us")) {
    console.log("Skipping group message");
    return;
  }

  // Skip messages sent by bot itself
  if (key.fromMe) {
    console.log("Skipping outgoing message");
    return;
  }

  const from = key.remoteJid;
  const messageId = key.id;
  const contactName = pushName || "Unknown";

  console.log(`Message from ${contactName} (${from}): ${messageId}`);

  // Process different message types
  if (message?.conversation) {
    // Text message
    const text = message.conversation;
    console.log(`Text: ${text}`);

    // Auto-reply example
    if (text.toLowerCase() === "hello") {
      await client.messages.sendText(
        {
          number: from.replace("@s.whatsapp.net", ""),
          text: "Hello! How can I help you?",
        },
        { instance }
      );
    }
  } else if (message?.imageMessage) {
    // Image message
    console.log(`Received image from ${contactName}`);
    const imageUrl = message.imageMessage.url;
    // Process image...
  } else if (message?.audioMessage) {
    // Audio message
    console.log(`Received audio from ${contactName}`);
    // Process audio...
  }
}

async function handleMessageUpdate(
  messageData: MessagePayload,
  instance: string
): Promise<void> {
  const { key, status } = messageData;
  console.log(`Message ${key.id} status updated to: ${status}`);

  // Handle read receipts, delivery confirmations, etc.
  switch (status) {
    case MessageUpdateStatus.DELIVERY_ACK:
      console.log("Message delivered");
      break;
    case MessageUpdateStatus.READ:
      console.log("Message read by recipient");
      break;
    case MessageUpdateStatus.SERVER_ACK:
      console.log("Message sent to server");
      break;
  }
}

async function handleConnectionUpdate(
  connectionData: ConnectionUpdatePayload
): Promise<void> {
  const { instance, state, statusReason } = connectionData;

  console.log(`Instance ${instance} connection state: ${state}`);

  switch (state) {
    case "open":
      console.log(`✅ Instance ${instance} connected successfully`);
      break;
    case "close":
      console.log(`❌ Instance ${instance} disconnected (${statusReason})`);
      break;
    case "connecting":
      console.log(`🔄 Instance ${instance} connecting...`);
      break;
  }
}

async function handleContact(
  contactData: ContactPayload,
  instance: string
): Promise<void> {
  const { remoteJid, pushName, profilePicUrl } = contactData;

  console.log(`Contact update: ${pushName} (${remoteJid})`);

  // Store or update contact information
  // You might want to save this to your database
}

Advanced Webhook Processing

class WebhookProcessor {
  private messageQueue: MessagePayload[] = [];
  private processing = false;

  async processWebhook(webhookData: WebhookData): Promise<void> {
    const { event, data, instance } = webhookData;

    // Add message to queue for batch processing
    if (event === WebhookEvent.MESSAGES_UPSERT) {
      this.messageQueue.push(data as MessagePayload);
      this.processQueue();
    }
  }

  private async processQueue(): Promise<void> {
    if (this.processing || this.messageQueue.length === 0) return;

    this.processing = true;

    try {
      // Process messages in batches
      const batch = this.messageQueue.splice(0, 10);

      for (const message of batch) {
        await this.processMessage(message);
        // Add delay to avoid rate limiting
        await new Promise((resolve) => setTimeout(resolve, 100));
      }
    } finally {
      this.processing = false;

      // Continue processing if more messages arrived
      if (this.messageQueue.length > 0) {
        setTimeout(() => this.processQueue(), 1000);
      }
    }
  }

  private async processMessage(message: MessagePayload): Promise<void> {
    // Your message processing logic here
    console.log(`Processing message: ${message.key.id}`);
  }
}

Available Webhook Events

The SDK supports all Evolution API webhook events:

  • WebhookEvent.APPLICATION_STARTUP - API startup
  • WebhookEvent.QRCODE_UPDATED - QR code updates
  • WebhookEvent.CONNECTION_UPDATE - Connection status changes
  • WebhookEvent.MESSAGES_SET - Initial message load
  • WebhookEvent.MESSAGES_UPSERT - New messages
  • WebhookEvent.MESSAGES_UPDATE - Message status updates
  • WebhookEvent.MESSAGES_DELETE - Message deletions
  • WebhookEvent.SEND_MESSAGE - Message sending events
  • WebhookEvent.CONTACTS_SET - Initial contacts load
  • WebhookEvent.CONTACTS_UPSERT - New contacts
  • WebhookEvent.CONTACTS_UPDATE - Contact updates
  • WebhookEvent.PRESENCE_UPDATE - User presence changes
  • WebhookEvent.CHATS_SET - Initial chats load
  • WebhookEvent.CHATS_UPDATE - Chat updates
  • WebhookEvent.CHATS_UPSERT - New chats
  • WebhookEvent.CHATS_DELETE - Chat deletions
  • WebhookEvent.GROUPS_UPSERT - New groups
  • WebhookEvent.GROUPS_UPDATE - Group updates
  • WebhookEvent.GROUP_PARTICIPANTS_UPDATE - Group member changes
  • WebhookEvent.NEW_TOKEN - JWT token updates

Available Webhook Events to Setup

To setup the WebHook, the constants are these ones:

  • WebhookEventSetup.APPLICATION_STARTUP - API startup
  • WebhookEventSetup.QRCODE_UPDATED - QR code updates
  • WebhookEventSetup.CONNECTION_UPDATE - Connection status changes
  • WebhookEventSetup.MESSAGES_SET - Initial message load
  • WebhookEventSetup.MESSAGES_UPSERT - New messages
  • WebhookEventSetup.MESSAGES_UPDATE - Message status updates
  • WebhookEventSetup.MESSAGES_DELETE - Message deletions
  • WebhookEventSetup.SEND_MESSAGE - Message sending events
  • WebhookEventSetup.CONTACTS_SET - Initial contacts load
  • WebhookEventSetup.CONTACTS_UPSERT - New contacts
  • WebhookEventSetup.CONTACTS_UPDATE - Contact updates
  • WebhookEventSetup.PRESENCE_UPDATE - User presence changes
  • WebhookEventSetup.CHATS_SET - Initial chats load
  • WebhookEventSetup.CHATS_UPDATE - Chat updates
  • WebhookEventSetup.CHATS_UPSERT - New chats
  • WebhookEventSetup.CHATS_DELETE - Chat deletions
  • WebhookEventSetup.GROUPS_UPSERT - New groups
  • WebhookEventSetup.GROUPS_UPDATE - Group updates
  • WebhookEventSetup.GROUP_PARTICIPANTS_UPDATE - Group member changes
  • WebhookEventSetup.NEW_TOKEN - JWT token updates

Configure Webhook URL

Don't forget to configure your webhook URL in the Evolution API:

// Set your webhook endpoint
await client.webhook.set({
  url: "https://your-domain.com/webhook",
  webhook_by_events: true,
  events: [
    WebhookEventSetup.MESSAGES_UPSERT,
    WebhookEventSetup.MESSAGES_UPDATE,
    WebhookEventSetup.CONNECTION_UPDATE,
    WebhookEventSetup.CONTACTS_UPSERT,
  ],
});

API Documentation

Check the official API documentation for more information about their service.

Contributing

Feel free to contribute with suggestions or bug reports at our GitHub repository.

Authors