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

fonnte-wa

v1.1.0

Published

A modular WhatsApp integration package for the Fonnte API

Readme

Fonnte WhatsApp

A modular WhatsApp integration package for the Fonnte API. This package provides a simple and flexible way to integrate WhatsApp messaging into your JavaScript/TypeScript projects using the Fonnte service.

Features

  • Send text messages, media, documents, and interactive messages (buttons, lists)
  • Receive and process incoming messages via webhooks
  • TypeScript support with full type definitions
  • Modular architecture for flexible integration
  • Comprehensive error handling

Installation

npm install fonnte-wa

Usage

Sending Messages

import { FonnteClient } from 'fonnte-wa';

// Initialize the client
// Note: One API key corresponds to one device in Fonnte's system
const client = new FonnteClient({
  apiKey: 'your-api-key-from-fonnte-dashboard',
  // Optional parameters
  // baseUrl: 'https://api.fonnte.com', // Default API URL
  // timeout: 30000 // Request timeout in milliseconds
});

// Send a simple text message
async function sendTextMessage() {
  const response = await client.sendMessage({
    target: '628123456789', // Target phone number with country code
    message: 'Hello from Fonnte WhatsApp package!'
  });
  
  console.log(response);
}

// Send a media message (image, video, audio)
async function sendMediaMessage() {
  const response = await client.sendMedia({
    target: '628123456789',
    message: 'Check out this image!',
    url: 'https://example.com/image.jpg'
  });
  
  console.log(response);
}

// Send a document
async function sendDocument() {
  const response = await client.sendDocument({
    target: '628123456789',
    message: 'Here is the document you requested',
    url: 'https://example.com/document.pdf',
    filename: 'document.pdf'
  });
  
  console.log(response);
}

// Send a button message
async function sendButtonMessage() {
  const response = await client.sendButtons({
    target: '628123456789',
    message: 'Please select an option:',
    buttonTemplate: {
      buttons: [
        { display: 'Option 1', id: 'opt1' },
        { display: 'Option 2', id: 'opt2' },
        { display: 'Option 3', id: 'opt3' }
      ]
    },
    footer: 'Footer text (optional)',
    header: 'Header text (optional)'
  });
  
  console.log(response);
}

// Send a list message
async function sendListMessage() {
  const response = await client.sendList({
    target: '628123456789',
    message: 'Please select from the list:',
    listTemplate: {
      title: 'Available options',
      sections: [
        {
          title: 'Section 1',
          rows: [
            { title: 'Item 1', description: 'Description 1', id: 'item1' },
            { title: 'Item 2', description: 'Description 2', id: 'item2' }
          ]
        },
        {
          title: 'Section 2',
          rows: [
            { title: 'Item 3', description: 'Description 3', id: 'item3' },
            { title: 'Item 4', description: 'Description 4', id: 'item4' }
          ]
        }
      ]
    },
    footer: 'Footer text (optional)'
  });
  
  console.log(response);
}

// Check device status
async function checkDeviceStatus() {
  const response = await client.getDeviceStatus();
  console.log(response);
}

Receiving Messages (Webhook)

import { FonnteWebhook } from 'fonnte-wa';

// Initialize the webhook handler
const webhook = new FonnteWebhook({
  port: 3000, // Port to listen on
  path: '/webhook/fonnte', // Path to listen on
  secret: 'your-secret-token' // Optional secret token for verification
});

// Register message handler
webhook.onMessage(async (message) => {
  console.log('Received message:', message);
  
  // Access message properties
  const { sender, message: text, type, button_id, list_id } = message;
  
  // Handle different message types
  if (button_id) {
    console.log(`Button ${button_id} was clicked by ${sender}`);
  } else if (list_id) {
    console.log(`List item ${list_id} was selected by ${sender}`);
  } else {
    console.log(`Received ${type} message from ${sender}: ${text}`);
  }
});

// Register multiple handlers if needed
webhook.onMessage(async (message) => {
  // Another handler for the same message
  // For example, store in database
});

// Start the webhook server
webhook.start().then(() => {
  console.log('Webhook server started');
}).catch((error) => {
  console.error('Failed to start webhook server:', error);
});

// To stop the webhook server
// webhook.stop();

Advanced Usage

Using with Express

If you already have an Express application, you can mount the webhook handler on your existing app:

import express from 'express';
import { FonnteWebhook } from 'fonnte-wa';

const app = express();
const port = 3000;

// Your existing Express setup
app.use(express.json());
app.use(express.urlencoded({ extended: true }));

// Set up other routes
app.get('/', (req, res) => {
  res.send('Hello World!');
});

// Initialize the webhook handler with your existing Express app
const webhook = new FonnteWebhook({
  app: app, // Mount on existing app
  path: '/webhook/fonnte',
  secret: 'your-secret-token'
});

// Register message handler
webhook.onMessage(async (message) => {
  console.log('Received message:', message);
  // Process the message
});

// Start your Express server (webhook is already mounted)
app.listen(port, () => {
  console.log(`Server running on port ${port}`);
});

Configurable Logging

You can provide a custom logger instead of using console:

import { FonnteClient, Logger } from 'fonnte-wa';

// Create a custom logger
const customLogger: Logger = {
  info: (message, ...args) => {
    // Use your logging library
    myLogger.info(`[Fonnte] ${message}`, ...args);
  },
  error: (message, ...args) => {
    myLogger.error(`[Fonnte] ${message}`, ...args);
  },
  warn: (message, ...args) => {
    myLogger.warn(`[Fonnte] ${message}`, ...args);
  },
  debug: (message, ...args) => {
    myLogger.debug(`[Fonnte] ${message}`, ...args);
  }
};

const client = new FonnteClient({
  apiKey: 'your-api-key',
  logger: customLogger
});

Retry Logic

Configure automatic retry for failed requests:

import { FonnteClient } from 'fonnte-wa';

const client = new FonnteClient({
  apiKey: 'your-api-key',
  retry: {
    maxAttempts: 3,
    initialDelay: 1000,
    maxDelay: 10000,
    exponentialBackoff: true,
    retryableStatusCodes: [408, 429, 500, 502, 503, 504]
  }
});

// Failed requests will automatically retry up to 3 times
const response = await client.sendMessage({
  target: '628123456789',
  message: 'Hello!'
});

Request/Response Interceptors

Add interceptors for debugging or monitoring:

import { FonnteClient } from 'fonnte-wa';

const client = new FonnteClient({
  apiKey: 'your-api-key',
  onRequest: (config) => {
    console.log('Making request:', config.method, config.url);
    // You can modify the config here if needed
  },
  onResponse: (response) => {
    console.log('Received response:', response.status, response.data);
  },
  onError: (error) => {
    console.error('Request failed:', error);
    // Log to error tracking service
  }
});

Environment Variables

Configure the client using environment variables:

import { FonnteClient, createConfigFromEnv } from 'fonnte-wa';

// Read configuration from environment variables
// FONNTE_API_KEY, FONNTE_BASE_URL, FONNTE_TIMEOUT
const client = new FonnteClient(
  createConfigFromEnv({
    // Optional overrides
    timeout: 60000
  })
);

For webhooks:

import { FonnteWebhook, createWebhookConfigFromEnv } from 'fonnte-wa';

// Read configuration from environment variables
// FONNTE_WEBHOOK_PORT, FONNTE_WEBHOOK_PATH, FONNTE_WEBHOOK_SECRET
const webhook = new FonnteWebhook(
  createWebhookConfigFromEnv({
    // Optional overrides
    app: existingExpressApp
  })
);

Managing Webhook Handlers

You can add and remove handlers dynamically:

import { FonnteWebhook, WebhookHandler } from 'fonnte-wa';

const webhook = new FonnteWebhook({
  port: 3000,
  path: '/webhook/fonnte'
});

// Define a handler
const handler: WebhookHandler = async (message) => {
  console.log('Received:', message);
};

// Add handler
webhook.onMessage(handler);

// Remove specific handler
webhook.offMessage(handler);

// Remove all handlers
webhook.removeAllHandlers();

Error Handling

The package includes comprehensive error handling:

import { FonnteClient } from 'fonnte-wa';

const client = new FonnteClient({
  apiKey: 'your-api-key'
});

async function sendMessageWithErrorHandling() {
  try {
    const response = await client.sendMessage({
      target: '628123456789',
      message: 'Hello!'
    });
    
    if (!response.status) {
      console.error('Failed to send message:', response.message);
      return;
    }
    
    console.log('Message sent successfully:', response.data);
  } catch (error) {
    console.error('Error sending message:', error);
  }
}

TypeScript Support

This package is written in TypeScript and includes full type definitions:

import { FonnteClient, MessageOptions, FonnteResponse, WebhookMessage } from 'fonnte-wa';

// Use types in your code
const messageOptions: MessageOptions = {
  target: '628123456789',
  message: 'Hello with TypeScript!'
};

// Type-safe response handling
async function sendTypedMessage() {
  const response: FonnteResponse = await client.sendMessage(messageOptions);
  console.log(response);
}

// Type-safe webhook handling
function handleWebhookMessage(message: WebhookMessage) {
  // Access properties with type safety
  const { sender, message: text } = message;
  console.log(`Message from ${sender}: ${text}`);
}

License

MIT

Credits

This package is not officially affiliated with Fonnte. It is a community-developed wrapper for the Fonnte WhatsApp API.