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

@plasm05280/whatsapp-sdk

v1.0.4

Published

A TypeScript SDK for Meta's WhatsApp Cloud API

Readme

WhatsApp API SDK

Un SDK TypeScript / JavaScript puissant et modulaire pour interagir facilement avec l'API WhatsApp Cloud (Meta Graph API). Conçu pour Bun et Node.js, il simplifie l'envoi de messages via des modèles (templates) et la gestion sécurisée des Webhooks.


📑 Table des matières


✨ Fonctionnalités

  • 🚀 Initialisation rapide avec support des variables d'environnement (.env).
  • 📄 Modèles WhatsApp (Templates) : Support complet des en-têtes texte, document (PDF), image et vidéo.
  • 🔒 Vérification Webhook sécurisée : Traitement des challenges GET et validation des signatures HMAC-SHA256 (x-hub-signature-256).
  • ⚡ Compatible avec les standards Web : Utilise l'API standard Request / Response (idéal pour Bun, Edge Functions, Next.js, Hono, etc.).
  • 🛠️ Gestion rigoureuse des erreurs avec l'exception dédiée WhatsAppAPIError.

📦 Installation

Avec Bun :

bun install whatsapp-api

Avec npm / yarn / pnpm :

npm install whatsapp-api

⚙️ Variables d'environnement

Créez un fichier .env à la racine de votre projet :

ACCESS_TOKEN=votre_jeton_dacces_meta
PHONE_NUMBER_ID=votre_id_de_numero_de_telephone
API_VERSION=v20.0 # Optionnel, par défaut v20.0

🚀 Utilisation Rapide

import { WhatsApp } from "whatsapp-api";

// Initialisation du client (charge les identifiants depuis le .env si non spécifiés)
const wa = new WhatsApp({
  accessToken: process.env.ACCESS_TOKEN,
  phoneNumberId: process.env.PHONE_NUMBER_ID,
});

// Envoi d'un template texte simple
const response = await wa.templates.withText.send({
  to: "243851234567",
  templateName: "hello_world",
  language: "fr",
});

console.log("Message envoyé avec succès. ID :", response.messages[0]?.id);

📩 Envoi de Templates (wa.templates)

Le module templates fournit des sous-modules spécialisés selon le type d'en-tête (header) du modèle Meta.

1. Template Texte (withText)

Utilisez withText pour les modèles n'ayant pas de média en en-tête (avec ou sans variables et texte dynamique de header).

await wa.templates.withText.send({
  to: "243851234567",
  templateName: "order_confirmation",
  language: "fr", // Par défaut: 'fr'
  headerText: "Commande #48592", // Optionnel (si le template accepte un header texte)
  parameters: {
    customer_name: "Jean Dupont",
    delivery_date: "15 août 2026",
  },
});

2. Template Document / PDF (withDocument)

Utilisez withDocument pour joindre un fichier (PDF, DOCX, etc.) dans l'en-tête du modèle.

await wa.templates.withDocument.send({
  to: "243851234567",
  templateName: "send_customer_invoice",
  language: "fr",
  documentUrl: "https://example.com/invoices/INV-001.pdf",
  filename: "Facture_INV001.pdf", // Optionnel, nom affiché sur WhatsApp
  parameters: {
    invoice_number: "INV-001",
    amount: "150.00 EUR",
  },
});

3. Template Image (withImage)

Utilisez withImage pour inclure une image en en-tête.

await wa.templates.withImage.send({
  to: "243851234567",
  templateName: "promo_banner",
  language: "fr",
  imageUrl: "https://example.com/images/banner.jpg",
  parameters: {
    discount_code: "SUMMER2026",
    expiry_date: "31 août 2026",
  },
});

4. Template Vidéo (withVideo)

Utilisez withVideo pour joindre une vidéo d'en-tête.

await wa.templates.withVideo.send({
  to: "243851234567",
  templateName: "welcome_onboarding",
  language: "fr",
  videoUrl: "https://example.com/videos/intro.mp4",
  parameters: {
    user_name: "Alice",
  },
});

5. Template Personnalisé (withCustom)

Utilisez withCustom pour construire manuellement la structure des composants d'un template (header, body, buttons) de façon simplifiée et intuitive.

await wa.templates.withCustom.send({
  to: "243851234567",
  templateName: "promo_notification",
  language: "fr",
  header: { type: "text", text: "Offre spéciale" },
  body: { customer_name: "Jean Dupont", discount: "20%" },
  buttons: [
    { type: "quick_reply", text: "J'en profite" },
    {
      type: "url",
      text: "Voir l'offre",
      url: "https://example.com/offre",
    },
  ],
});

Remarque: Vous pouvez aussi fournir directement le tableau complet components si vous souhaitez contrôler tous les détails.


🛡️ Gestion des Webhooks (WhatsAppVerifier)

Pour recevoir et valider les notifications envoyées par Meta vers votre serveur, utilisez la classe WhatsAppVerifier ou les fonctions helpers réexportées par la bibliothèque.

1. Gestionnaire automatique (handleWhatsAppRequest)

Cette méthode traite automatiquement :

  • Les requêtes GET de vérification de souscription (Challenge Meta).
  • Les requêtes POST de notification en contrôlant la signature HMAC-SHA256 (x-hub-signature-256).
import { WhatsAppVerifier } from "whatsapp-api";

const verifier = new WhatsAppVerifier({
  verifyToken:
    process.env.WEBHOOK_VERIFY_TOKEN || "mon_secret_verify_token",
  appSecret: process.env.META_APP_SECRET || "mon_meta_app_secret",
});

// Exemple avec le serveur HTTP natif de Bun ou un Edge Handler
Bun.serve({
  port: 3000,
  async fetch(req: Request) {
    const url = new URL(req.url);

    if (url.pathname === "/webhook") {
      return await verifier.handleWhatsAppRequest(req);
    }

    return new Response("Not Found", { status: 404 });
  },
});

2. Vérification manuelle du Challenge GET

Si vous souhaitez valider manuellement la requête GET de Meta lors de la configuration du Webhook :

import { verifyWebhookSubscription } from "whatsapp-api";

// Dans votre contrôleur GET /webhook :
const params = {
  mode: req.query["hub.mode"],
  verifyToken: req.query["hub.verify_token"],
  challenge: req.query["hub.challenge"],
};

try {
  const challengeResponse = verifyWebhookSubscription(
    params,
    "mon_secret_verify_token",
  );
  // Renvoyer challengeResponse avec un statut 200 HTTP
} catch (error) {
  // Renvoyer un statut HTTP 403 Forbidden
}

3. Vérification manuelle de la signature POST (HMAC-SHA256)

Pour valider l'authenticité des messages POST entrants de Meta :

import { verifyWebhookSignature } from "whatsapp-api";

const isValid = verifyWebhookSignature({
  rawBody: rawRequestBody, // Chaîne de caractères ou Buffer brut
  signatureHeader: req.headers["x-hub-signature-256"],
  appSecret: process.env.META_APP_SECRET!,
});

if (!isValid) {
  console.error("Signature du Webhook invalide !");
}

❌ Gestion des Erreurs

Lorsqu'une requête API échoue ou est rejetée par Meta, le SDK lève une instance de WhatsAppAPIError.

import { WhatsAppAPIError } from "whatsapp-api";

try {
  await wa.templates.withText.send({
    to: "243851234567",
    templateName: "invalid_template_name",
  });
} catch (error) {
  if (error instanceof WhatsAppAPIError) {
    console.error("Statut HTTP :", error.status); // ex: 400
    console.error("Code d'erreur Meta :", error.code); // ex: 100
    console.error("Message :", error.message);
    console.error("Détails bruts :", error.rawError);
  } else {
    console.error("Erreur inattendue :", error);
  }
}

🔌 Accès direct au Client HTTP

Si vous avez besoin d'effectuer des appels personnalisés vers des points de terminaison Graph API non couverts directement par les méthodes de haut niveau, vous pouvez utiliser la méthode request du client HTTP sous-jacent :

const result = await wa.client.request({
  messaging_product: "whatsapp",
  to: "243851234567",
  type: "text",
  text: {
    body: "Message texte direct sans template",
  },
});

🛠️ Build & Scripts

  • Construire la bibliothèque (dist/) :
    bun run build
  • Lancer l'exemple :
    bun run example