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 🙏

© 2026 – Pkg Stats / Ryan Hefner

callmebot-notifier

v1.10.2

Published

Typed notification library for Node.js with WhatsApp, Telegram, Signal, Email, Discord, Slack, Google Chat, and Microsoft Teams.

Downloads

611

Readme

callmebot-notifier

npm version npm downloads Marketplace language Socket Badge Known Vulnerabilities coverage

Multi-channel notification delivery for Node.js. Send alerts to WhatsApp, Telegram, Web Push, Discord, Slack, Teams, Google Chat and Email with retry, fallback and severity routing.

CallMeBot is not the official WhatsApp API. Use this package for personal and low-risk notifications.

Subpath imports

Use HTTP-only entrypoints for Cloudflare Workers, edge runtimes, and serverless environments:

import { whatsapp } from "callmebot-notifier/whatsapp";
import { telegram } from "callmebot-notifier/telegram";
import { telegram } from "callmebot-notifier/telegram";

export default {
  async fetch(_request: Request, env: { TELEGRAM_BOT_TOKEN: string; TELEGRAM_CHAT_ID: string }) {
    const channel = telegram({
      botToken: env.TELEGRAM_BOT_TOKEN,
      chatId: env.TELEGRAM_CHAT_ID
    });
    await channel.send("Hello from Cloudflare Workers");
    return new Response("sent");
  }
};

Additional entrypoints are available from callmebot-notifier/core, /email, /webpush, and /express. The email, webpush, and express entrypoints are Node-specific. The root import remains fully supported for backward compatibility.

Donation:

You can buy me a coffee or two if you find helpfull my node.

If you buy me a coffee I would like to thank you in advance for your donation. Donate

Supported Channels

  • WhatsApp via CallMeBot
  • Telegram
  • Web Push
  • Email
  • Discord
  • Slack
  • Google Chat
  • Microsoft Teams
  • Signal (via signal-cli-rest-api)

Features

| Feature | Supported | | ---------------------- | --------- | | WhatsApp via CallMeBot | Yes | | Telegram | Yes | | Web Push | Yes | | Discord | Yes | | Slack | Yes | | Google Chat | Yes | | Microsoft Teams | Yes | | Signal via signal-cli | Yes | | Email | Yes | | Retry | Yes | | Fallback | Yes | | Severity routing | Yes | | Templates | Yes | | Express API | Yes | | GitHub Action | Yes |

Install

npm install callmebot-notifier

Quick Start

PHONE=393331112223
APIKEY=your-callmebot-apikey
TELEGRAM_BOT_TOKEN=1234567980:XXXX5x0XX2XxxXxx1XXXxxXxXXxXX6X-Tho
TELEGRAM_CHAT_ID=990099009
DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/...
SLACK_WEBHOOK_URL=https://hooks.slack.com/services/...
GCHAT_WEBHOOK_URL=https://chat.googleapis.com/v1/spaces/.../messages?key=...&token=...
TEAMS_WEBHOOK_URL=https://...
SIGNAL_API_URL=http://localhost:8080
SIGNAL_NUMBER=+391234567890
SIGNAL_RECIPIENTS=+399876543210
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_SECURE=false
[email protected]
SMTP_PASS=xxxx xxxx xxxx xxxx
[email protected]
[email protected]
import { fromEnv } from "callmebot-notifier";

const notifier = fromEnv();
await notifier.send("Deployment done");

Basic notify()

import { notify, whatsapp, telegram } from "callmebot-notifier";

await notify({
  channels: [
    whatsapp({ phone: process.env.PHONE ?? "", apikey: process.env.APIKEY ?? "" }),
    telegram({
      botToken: process.env.TELEGRAM_BOT_TOKEN ?? "",
      chatId: process.env.TELEGRAM_CHAT_ID ?? ""
    })
  ],
  message: "Server is down"
});

Web Push

Create VAPID keys once, keep private key server-side, and store each browser subscription in your application database. Then pass one subscription to webpush():

import { webpush } from "callmebot-notifier";

const channel = webpush({
  subscription, // Browser PushSubscription serialized with JSON.stringify()
  vapidDetails: {
    subject: "mailto:[email protected]",
    publicKey: process.env.VAPID_PUBLIC_KEY ?? "",
    privateKey: process.env.VAPID_PRIVATE_KEY ?? ""
  },
  ttl: 60,
  urgency: "high"
});

await channel.send("Deployment complete");

See Web Push setup for browser subscription and service-worker setup.

Fallback Example

import { notify, whatsapp, telegram } from "callmebot-notifier";

await notify({
  primary: whatsapp({ phone: process.env.PHONE ?? "", apikey: process.env.APIKEY ?? "" }),
  fallback: telegram({
    botToken: process.env.TELEGRAM_BOT_TOKEN ?? "",
    chatId: process.env.TELEGRAM_CHAT_ID ?? ""
  }),
  message: "Server is down"
});

Severity Routing

import { notify, whatsapp, telegram, email, gchat, teams } from "callmebot-notifier";

await notify({
  routes: {
    info: [
      telegram({
        botToken: process.env.TELEGRAM_BOT_TOKEN ?? "",
        chatId: process.env.TELEGRAM_CHAT_ID ?? ""
      })
    ],
    warn: [gchat({ webhookUrl: process.env.GCHAT_WEBHOOK_URL ?? "" })],
    critical: [
      whatsapp({ phone: process.env.PHONE ?? "", apikey: process.env.APIKEY ?? "" }),
      teams({ webhookUrl: process.env.TEAMS_WEBHOOK_URL ?? "" }),
      email({
        host: process.env.SMTP_HOST ?? "",
        port: Number(process.env.SMTP_PORT || 587),
        secure: process.env.SMTP_SECURE === "true",
        user: process.env.SMTP_USER ?? undefined,
        pass: process.env.SMTP_PASS ?? undefined,
        from: process.env.EMAIL_FROM ?? "",
        to: process.env.EMAIL_TO ?? ""
      })
    ]
  },
  message: {
    title: "CPU high",
    message: "Load spike on api-1",
    severity: "critical"
  }
});

Templates

import { notify, whatsapp } from "callmebot-notifier";

await notify.alert(
  {
    title: "Deploy",
    message: "Application deployed",
    source: "GitHub Actions"
  },
  {
    channels: [whatsapp({ phone: process.env.PHONE ?? "", apikey: process.env.APIKEY ?? "" })]
  }
);

await notify.incident(
  {
    title: "Database down",
    message: "Primary DB unavailable",
    source: "api"
  },
  {
    channels: [whatsapp({ phone: process.env.PHONE ?? "", apikey: process.env.APIKEY ?? "" })]
  }
);

Retry Policy

import { notify, whatsapp, telegram, email } from "callmebot-notifier";

await notify({
  channels: [
    whatsapp({ phone: process.env.PHONE ?? "", apikey: process.env.APIKEY ?? "" }),
    telegram({
      botToken: process.env.TELEGRAM_BOT_TOKEN ?? "",
      chatId: process.env.TELEGRAM_CHAT_ID ?? ""
    }),
    email({
      host: process.env.SMTP_HOST ?? "",
      port: Number(process.env.SMTP_PORT || 587),
      secure: process.env.SMTP_SECURE === "true",
      user: process.env.SMTP_USER ?? undefined,
      pass: process.env.SMTP_PASS ?? undefined,
      from: process.env.EMAIL_FROM ?? "",
      to: process.env.EMAIL_TO ?? ""
    })
  ],
  message: "Build failed",
  retry: { attempts: 3, delayMs: 1000 }
});

Hooks

import { notify, whatsapp } from "callmebot-notifier";

const channel = whatsapp({ phone: process.env.PHONE ?? "", apikey: process.env.APIKEY ?? "" });

await notify({
  channels: [channel],
  message: "Release done",
  logLevel: "info",
  onResult: (result) => {
    console.log("notify.result", result);
  },
  onError: (error, context) => {
    console.error("notify.error", { error, ...context });
  }
});

Express Usage

import { createExpressApp, FallbackChannel, whatsapp, telegram } from "callmebot-notifier";

const app = createExpressApp(
  new FallbackChannel([
    whatsapp({ phone: process.env.PHONE ?? "", apikey: process.env.APIKEY ?? "" }),
    telegram({
      botToken: process.env.TELEGRAM_BOT_TOKEN ?? "",
      chatId: process.env.TELEGRAM_CHAT_ID ?? ""
    })
  ])
);

app.listen(3000);

GitHub Action

Use published action:

- uses: F3rr1gn0/callmebot-notifier-action@v1
  with:
    message: "Build done"
    channel: "telegram"
  env:
    TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }}
    TELEGRAM_CHAT_ID: ${{ secrets.TELEGRAM_CHAT_ID }}

Secrets to set in consumer repo:

TELEGRAM_BOT_TOKEN
TELEGRAM_CHAT_ID
PHONE
APIKEY
DISCORD_WEBHOOK_URL
SLACK_WEBHOOK_URL
GCHAT_WEBHOOK_URL
TEAMS_WEBHOOK_URL
SMTP_HOST
SMTP_PORT
SMTP_SECURE
SMTP_USER
SMTP_PASS
EMAIL_FROM
EMAIL_TO

Smoke flow:

name: smoke-action

on:
  workflow_dispatch:

jobs:
  smoke:
    runs-on: ubuntu-latest
    steps:
      - uses: F3rr1gn0/callmebot-notifier-action@v1
        with:
          message: "Smoke from GitHub Action"
          channel: "telegram"
        env:
          TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }}
          TELEGRAM_CHAT_ID: ${{ secrets.TELEGRAM_CHAT_ID }}

Failure flow:

name: smoke-action-failure

on:
  workflow_dispatch:

jobs:
  smoke:
    runs-on: ubuntu-latest
    steps:
      - run: exit 1
      - if: ${{ failure() }}
        uses: F3rr1gn0/callmebot-notifier-action@v1
        with:
          message: "Build failed"
          channel: "telegram"
        env:
          TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }}
          TELEGRAM_CHAT_ID: ${{ secrets.TELEGRAM_CHAT_ID }}

Setup Guides

MCP Server Example

Expose send_notification to Claude Desktop, Cursor, or another MCP client:

Environment Variables

Common variables:

  • PHONE
  • APIKEY
  • TELEGRAM_BOT_TOKEN
  • TELEGRAM_CHAT_ID
  • VAPID_PUBLIC_KEY
  • VAPID_PRIVATE_KEY
  • DISCORD_WEBHOOK_URL
  • SLACK_WEBHOOK_URL
  • GCHAT_WEBHOOK_URL
  • TEAMS_WEBHOOK_URL
  • SIGNAL_API_URL
  • SIGNAL_NUMBER
  • SIGNAL_RECIPIENTS
  • SMTP_HOST
  • SMTP_PORT
  • SMTP_SECURE
  • SMTP_USER
  • SMTP_PASS
  • EMAIL_FROM
  • EMAIL_TO

Result Shape

notify() returns:

type NotifyResult = {
  ok: boolean;
  deliveredBy?: string;
  attempts: Array<{
    channel: string;
    ok: boolean;
    attempt: number;
    error?: string;
  }>;
};

Helper:

import { summarizeNotifyResult } from "callmebot-notifier";

const summary = summarizeNotifyResult(result);

Notes and Limitations

  • CallMeBot is a third-party WhatsApp bridge, not the official WhatsApp API
  • Intended for personal or low-risk alerts
  • Discord and Slack use webhook URLs only
  • Web Push subscriptions belong to browsers; store them in your app and remove subscriptions that return 404 or 410
  • fromEnv() is the quickest way to bootstrap a notifier from environment variables
  • Email examples assume Gmail app passwords
  • Coverage report is generated by npm run test:coverage

Roadmap

  • ntfy
  • Pushover
  • Mattermost
  • Matrix

License

MIT