WhatsApp API
Examples

Examples

Practical examples showing how to integrate the WhatsApp API into common use cases.

Complete Workflow Example

This example demonstrates the full process from authentication to sending a message. This class will be used in all examples that follow.

class WhatsAppAPI {
  constructor(apiKey, apiSecret, baseUrl = "https://whatsapp.smsleopard.com") {
    this.credentials = btoa(`${apiKey}:${apiSecret}`);
    this.baseUrl = baseUrl;
    this.headers = {
      Authorization: `Basic ${this.credentials}`,
      "Content-Type": "application/json",
    };
  }
 
  async getPhoneNumbers() {
    const response = await fetch(`${this.baseUrl}/v1/phone_number_ids`, {
      method: "GET",
      headers: this.headers,
    });
    return await response.json();
  }
 
  async getTemplates(phoneNumberId) {
    const response = await fetch(
      `${this.baseUrl}/v1/phone_number_ids/${id}/templates`,
      {
        method: "GET",
        headers: this.headers,
      }
    );
    return await response.json();
  }
 
  async sendMessage({
    destination,
    templateId,
    phoneNumberId,
    variables = [],
  }) {
    const payload = {
      destination,
      template_id: templateId,
      phone_number_id: phoneNumberId,
      component_list: {
        components: [
          {
            component_type: "BODY",
            fields: variables.map((value, index) => ({
              name: (index + 1).toString(),
              value: value.toString(),
            })),
          },
        ],
      },
    };
 
    const response = await fetch(`${this.baseUrl}/v1/whatsapp/send`, {
      method: "POST",
      headers: this.headers,
      body: JSON.stringify(payload),
    });
 
    return await response.json();
  }
}
 
// Usage
const api = new WhatsAppAPI("your_api_key", "your_api_secret");
 
// Get available phone numbers
const phoneNumbers = await api.getPhoneNumbers();
const phoneNumberId = phoneNumbers[0].phone_number_id;
 
// Get templates for the phone number
const templates = await api.getTemplates(phoneNumbers[0].id);
const authTemplate = templates.find((t) => t.type === "AUTHENTICATION");
 
// Send OTP message
const result = await api.sendMessage({
  destination: "254720000000",
  templateId: authTemplate.id,
  phoneNumberId: phoneNumberId,
  variables: ["123456"], // OTP code
});
 
console.log("Message sent:", result);

Use Case Examples

1. User Authentication System

Send OTP codes for user verification during login or registration.

class AuthService {
  constructor(whatsappAPI) {
    this.whatsappAPI = whatsappAPI; // defined at the top
    this.otpStore = new Map(); // In production, use Redis or database
  }
 
  generateOTP() {
    return Math.floor(100000 + Math.random() * 900000).toString();
  }
 
  async sendOTP(phoneNumber, phoneNumberId, templateId) {
    const otp = this.generateOTP();
 
    // Store OTP with expiration (5 minutes)
    this.otpStore.set(phoneNumber, {
      code: otp,
      expires: Date.now() + 5 * 60 * 1000,
    });
 
    try {
      const result = await this.whatsappAPI.sendMessage({
        destination: phoneNumber,
        templateId: templateId,
        phoneNumberId: phoneNumberId,
        variables: [otp],
      });
 
      return {
        success: true,
        messageId: result.recipients[0].id,
        cost: result.recipients[0].cost,
      };
    } catch (error) {
      console.error("Failed to send OTP:", error);
      return { success: false, error: error.message };
    }
  }
 
  verifyOTP(phoneNumber, userOTP) {
    const stored = this.otpStore.get(phoneNumber);
 
    if (!stored) {
      return { valid: false, reason: "OTP not found" };
    }
 
    if (Date.now() > stored.expires) {
      this.otpStore.delete(phoneNumber);
      return { valid: false, reason: "OTP expired" };
    }
 
    if (stored.code !== userOTP) {
      return { valid: false, reason: "Invalid OTP" };
    }
 
    this.otpStore.delete(phoneNumber);
    return { valid: true };
  }
}
 
// Usage
const authService = new AuthService(api);
 
// Send OTP
const otpResult = await authService.sendOTP(
  "254720000000",
  "phone_number_id",
  "auth_template_id"
);
 
// Later, verify OTP
const verification = authService.verifyOTP("254720000000", "123456");
console.log("OTP valid:", verification.valid);

2. E-commerce Order Notifications

Send order confirmations, shipping updates, and delivery notifications.

class OrderNotificationService {
  constructor(whatsappAPI) {
    this.whatsappAPI = whatsappAPI; // defined at the top
    this.templates = {
      ORDER_CONFIRMATION: "order_confirmation_template_id",
      SHIPPING_UPDATE: "shipping_update_template_id",
      DELIVERY_CONFIRMATION: "delivery_confirmation_template_id",
    };
    this.phoneNumberId = "your_phone_number_id";
  }
 
  async sendOrderConfirmation(order) {
    // Template: "Hi {{1}}, your order #{{2}} worth {{3}} has been confirmed. Expected delivery: {{4}}"
    return await this.whatsappAPI.sendMessage({
      destination: order.customerPhone,
      templateId: this.templates.ORDER_CONFIRMATION,
      phoneNumberId: this.phoneNumberId,
      variables: [
        order.customerName,
        order.orderNumber,
        order.totalAmount,
        order.expectedDelivery,
      ],
    });
  }
 
  async sendShippingUpdate(order, trackingNumber) {
    // Template: "Hi {{1}}, your order #{{2}} has been shipped! Track it with: {{3}}"
    return await this.whatsappAPI.sendMessage({
      destination: order.customerPhone,
      templateId: this.templates.SHIPPING_UPDATE,
      phoneNumberId: this.phoneNumberId,
      variables: [order.customerName, order.orderNumber, trackingNumber],
    });
  }
 
  async sendDeliveryConfirmation(order) {
    // Template: "Hi {{1}}, your order #{{2}} has been delivered! Thank you for shopping with us."
    return await this.whatsappAPI.sendMessage({
      destination: order.customerPhone,
      templateId: this.templates.DELIVERY_CONFIRMATION,
      phoneNumberId: this.phoneNumberId,
      variables: [order.customerName, order.orderNumber],
    });
  }
}
 
// Usage
const orderService = new OrderNotificationService(api);
 
const order = {
  customerName: "John Doe",
  customerPhone: "254720000000",
  orderNumber: "ORD-2025-001",
  totalAmount: "KES 2,500",
  expectedDelivery: "June 30, 2025",
};
 
// Send order confirmation
await orderService.sendOrderConfirmation(order);
 
// Later, when shipped
await orderService.sendShippingUpdate(order, "TRK123456789");
 
// Finally, when delivered
await orderService.sendDeliveryConfirmation(order);

3. Appointment Reminders

Send appointment confirmations and reminders for healthcare, beauty salons, etc.

class AppointmentService {
  constructor(whatsappAPI) {
    this.whatsappAPI = whatsappAPI; // defined at the top
    this.reminderTemplate = "appointment_reminder_template_id";
    this.confirmationTemplate = "appointment_confirmation_template_id";
    this.phoneNumberId = "your_phone_number_id";
  }
 
  async sendAppointmentConfirmation(appointment) {
    // Template: "Hi {{1}}, your appointment with Dr. {{2}} is confirmed for {{3}} at {{4}}."
    return await this.whatsappAPI.sendMessage({
      destination: appointment.patientPhone,
      templateId: this.confirmationTemplate,
      phoneNumberId: this.phoneNumberId,
      variables: [
        appointment.patientName,
        appointment.doctorName,
        appointment.date,
        appointment.time,
      ],
    });
  }
 
  async sendAppointmentReminder(appointment) {
    // Template: "Reminder: Hi {{1}}, you have an appointment tomorrow at {{2}} with Dr. {{3}}."
    return await this.whatsappAPI.sendMessage({
      destination: appointment.patientPhone,
      templateId: this.reminderTemplate,
      phoneNumberId: this.phoneNumberId,
      variables: [
        appointment.patientName,
        appointment.time,
        appointment.doctorName,
      ],
    });
  }
 
  // Schedule reminder to be sent 24 hours before appointment
  scheduleReminder(appointment) {
    const appointmentTime = new Date(appointment.datetime);
    const reminderTime = new Date(appointmentTime - 24 * 60 * 60 * 1000); // 24 hours before
 
    const delay = reminderTime.getTime() - Date.now();
 
    if (delay > 0) {
      setTimeout(() => {
        this.sendAppointmentReminder(appointment);
      }, delay);
    }
  }
}
 
// Usage
const appointmentService = new AppointmentService(api);
 
const appointment = {
  patientName: "Alice Johnson",
  patientPhone: "254720000000",
  doctorName: "Smith",
  date: "July 1, 2025",
  time: "2:00 PM",
  datetime: "2025-07-01T14:00:00",
};
 
// Send confirmation immediately
await appointmentService.sendAppointmentConfirmation(appointment);
 
// Schedule reminder for 24 hours before
appointmentService.scheduleReminder(appointment);

4. Banking and Financial Notifications

Send transaction alerts, balance updates, and payment confirmations.

class BankingNotificationService {
  constructor(whatsappAPI) {
    this.whatsappAPI = whatsappAPI; // defined at the top
    this.templates = {
      TRANSACTION_ALERT: "transaction_alert_template_id",
      BALANCE_INQUIRY: "balance_inquiry_template_id",
      PAYMENT_CONFIRMATION: "payment_confirmation_template_id",
    };
    this.phoneNumberId = "your_phone_number_id";
  }
 
  async sendTransactionAlert(transaction) {
    // Template: "Transaction Alert: {{1}} {{2}} {{3}} on {{4}}. Balance: {{5}}"
    const transactionType = transaction.amount > 0 ? "Credit" : "Debit";
 
    return await this.whatsappAPI.sendMessage({
      destination: transaction.customerPhone,
      templateId: this.templates.TRANSACTION_ALERT,
      phoneNumberId: this.phoneNumberId,
      variables: [
        transactionType,
        Math.abs(transaction.amount).toFixed(2),
        transaction.currency,
        transaction.date,
        transaction.balance.toFixed(2),
      ],
    });
  }
 
  async sendBalanceInquiry(customer) {
    // Template: "Hi {{1}}, your account balance is {{2}} {{3}} as of {{4}}"
    return await this.whatsappAPI.sendMessage({
      destination: customer.phone,
      templateId: this.templates.BALANCE_INQUIRY,
      phoneNumberId: this.phoneNumberId,
      variables: [
        customer.name,
        customer.balance.toFixed(2),
        customer.currency,
        new Date().toLocaleString(),
      ],
    });
  }
 
  async sendPaymentConfirmation(payment) {
    // Template: "Payment Confirmed: {{1}} {{2}} paid to {{3}} on {{4}}. Ref: {{5}}"
    return await this.whatsappAPI.sendMessage({
      destination: payment.payerPhone,
      templateId: this.templates.PAYMENT_CONFIRMATION,
      phoneNumberId: this.phoneNumberId,
      variables: [
        payment.currency,
        payment.amount.toFixed(2),
        payment.recipient,
        payment.date,
        payment.reference,
      ],
    });
  }
}
 
// Usage
const bankingService = new BankingNotificationService(api);
 
// Transaction alert
const transaction = {
  customerPhone: "254720000000",
  amount: -150.0, // Negative for debit
  currency: "KES",
  date: "2025-06-26 10:30 AM",
  balance: 5750.5,
};
 
await bankingService.sendTransactionAlert(transaction);

Error Handling Examples

Robust Error Handling

class WhatsAppAPIWithErrorHandling extends WhatsAppAPI {
  async sendMessageWithRetry(
    { destination, templateId, phoneNumberId, variables = [] },
    maxRetries = 3
  ) {
    let lastError;
 
    for (let attempt = 1; attempt <= maxRetries; attempt++) {
      try {
        const result = await this.sendMessage({
          destination,
          templateId,
          phoneNumberId,
          variables,
        });
 
        // Check if the response indicates success
        if (result.recipients && result.recipients[0].status === "Success") {
          return {
            success: true,
            data: result,
            attempt,
          };
        } else {
          throw new Error(`Message failed: ${result.recipients[0].status}`);
        }
      } catch (error) {
        lastError = error;
        console.log(`Attempt ${attempt} failed:`, error.message);
 
        // Don't retry on certain errors
        if (this.isNonRetryableError(error)) {
          break;
        }
 
        // Wait before retrying (exponential backoff)
        if (attempt < maxRetries) {
          await this.delay(Math.pow(2, attempt) * 1000);
        }
      }
    }
 
    return {
      success: false,
      error: lastError.message,
      attempts: maxRetries,
    };
  }
 
  isNonRetryableError(error) {
    const nonRetryableMessages = [
      "Invalid phone number",
      "Template not found",
      "Insufficient balance",
      "Invalid credentials",
    ];
 
    return nonRetryableMessages.some((msg) =>
      error.message.toLowerCase().includes(msg.toLowerCase())
    );
  }
 
  delay(ms) {
    return new Promise((resolve) => setTimeout(resolve, ms));
  }
 
  async validateBeforeSending({
    destination,
    templateId,
    phoneNumberId,
    variables,
  }) {
    const errors = [];
 
    // Validate phone number format
    if (!this.isValidPhoneNumber(destination)) {
      errors.push("Invalid phone number format");
    }
 
    // Validate template ID
    if (!templateId || templateId.trim() === "") {
      errors.push("Template ID is required");
    }
 
    // Validate phone number ID
    if (!phoneNumberId || phoneNumberId.trim() === "") {
      errors.push("Phone number ID is required");
    }
 
    // Validate variables
    if (!Array.isArray(variables)) {
      errors.push("Variables must be an array");
    }
 
    return {
      valid: errors.length === 0,
      errors,
    };
  }
 
  isValidPhoneNumber(phone) {
    // Basic phone number validation
    const phoneRegex = /^[+]?[\d\s\-\(\)]{10,15}$/;
    return phoneRegex.test(phone);
  }
}
 
// Usage with error handling
const robustAPI = new WhatsAppAPIWithErrorHandling("api_key", "api_secret");
 
async function sendNotificationSafely(messageData) {
  // Validate before sending
  const validation = await robustAPI.validateBeforeSending(messageData);
 
  if (!validation.valid) {
    console.error("Validation failed:", validation.errors);
    return { success: false, errors: validation.errors };
  }
 
  // Send with retry logic
  const result = await robustAPI.sendMessageWithRetry(messageData);
 
  if (result.success) {
    console.log(`Message sent successfully on attempt ${result.attempt}`);
    return result;
  } else {
    console.error(
      `Failed to send message after ${result.attempts} attempts:`,
      result.error
    );
    return result;
  }
}

Bulk Messaging Example

class BulkMessagingService {
  constructor(whatsappAPI, rateLimit = 10) {
    // 10 messages per second
    this.whatsappAPI = whatsappAPI; // defined at the top
    this.rateLimit = rateLimit;
    this.delayBetweenMessages = 1000 / rateLimit; // milliseconds
  }
 
  async sendBulkMessages(messages) {
    const results = [];
 
    console.log(`Starting bulk send of ${messages.length} messages...`);
 
    for (let i = 0; i < messages.length; i++) {
      const message = messages[i];
 
      try {
        const result = await this.whatsappAPI.sendMessage(message);
        results.push({
          index: i,
          destination: message.destination,
          success: true,
          result,
        });
 
        console.log(`Message ${i + 1}/${messages.length} sent successfully`);
      } catch (error) {
        results.push({
          index: i,
          destination: message.destination,
          success: false,
          error: error.message,
        });
 
        console.error(
          `Message ${i + 1}/${messages.length} failed:`,
          error.message
        );
      }
 
      // Rate limiting delay
      if (i < messages.length - 1) {
        await this.delay(this.delayBetweenMessages);
      }
    }
 
    return this.generateBulkReport(results);
  }
 
  generateBulkReport(results) {
    const successful = results.filter((r) => r.success);
    const failed = results.filter((r) => !r.success);
    const totalCost = successful.reduce(
      (sum, r) => sum + (r.result.recipients[0].cost || 0),
      0
    );
 
    return {
      total: results.length,
      successful: successful.length,
      failed: failed.length,
      successRate:
        ((successful.length / results.length) * 100).toFixed(2) + "%",
      totalCost: totalCost.toFixed(2),
      failedMessages: failed,
      results,
    };
  }
 
  delay(ms) {
    return new Promise((resolve) => setTimeout(resolve, ms));
  }
}
 
// Usage
const bulkService = new BulkMessagingService(api, 5); // 5 messages per second
 
const bulkMessages = [
  {
    destination: "254720000001",
    templateId: "marketing_template_id",
    phoneNumberId: "phone_number_id",
    variables: ["John", "Special Offer"],
  },
  {
    destination: "254720000002",
    templateId: "marketing_template_id",
    phoneNumberId: "phone_number_id",
    variables: ["Jane", "Special Offer"],
  },
  // ... more messages
];
 
const report = await bulkService.sendBulkMessages(bulkMessages);
console.log("Bulk messaging report:", report);

These examples provide a comprehensive foundation for integrating the WhatsApp API into various applications and use cases. Remember to always test with sandbox credentials before using production keys!