Skip to main content

Text Messages

Text messages are the foundation of WhatsApp communication. The SDK provides a simple yet powerful interface for sending text messages with advanced features like URL previews and reply support.

Basic Usage

import { WhatsAppClient } from 'whatsapp-client-sdk';

const client = new WhatsAppClient({
  accessToken: process.env.WHATSAPP_ACCESS_TOKEN!,
  phoneNumberId: process.env.WHATSAPP_PHONE_NUMBER_ID!,
});

// Simple text message
await client.sendText('+1234567890', 'Hello, World!');

Method Signature

async sendText(
  to: string,
  text: string, 
  options?: TextOptions
): Promise<MessageResponse>

Parameters

  • to (string): Recipient phone number in international format
  • text (string): Message content (max 4,096 characters)
  • options (TextOptions, optional): Additional message options

TextOptions Interface

interface TextOptions {
  previewUrl?: boolean;      // Enable URL preview (default: false)
  replyToMessageId?: string; // Reply to specific message
}

Examples

Basic Text Message

const response = await client.sendText(
  '+1234567890',
  'Welcome to our service! We\'re excited to help you.'
);

console.log('Message ID:', response.messages[0].id);

Text with URL Preview

// Enable URL preview for shared links
await client.sendText(
  '+1234567890',
  'Check out our latest blog post: https://blog.example.com/latest-updates',
  { previewUrl: true }
);

Reply to Message

// Reply to a specific message
await client.sendText(
  '+1234567890',
  'Thanks for your question! Here\'s the answer...',
  { replyToMessageId: 'wamid.HBgLM2E5YzE3...' }
);

Formatted Text with Emojis

await client.sendText(
  '+1234567890',
  '🎉 Congratulations! 🎉\n\n' +
  'Your order has been confirmed:\n' +
  '• Order ID: #12345\n' +
  '• Total: $29.99\n' +
  '• ETA: 2-3 business days\n\n' +
  'Track your order: https://track.example.com/12345'
);

Multi-line Messages

const orderDetails = `
📦 Order Confirmation

Order #: 123456
Date: ${new Date().toLocaleDateString()}
Total: $99.99

Items:
• Product A - $49.99
• Product B - $39.99
• Shipping - $10.00

Delivery Address:
123 Main St
New York, NY 10001

Expected delivery: 3-5 business days
`.trim();

await client.sendText('+1234567890', orderDetails);

Character Limits and Validation

Maximum Length

Text messages are limited to 4,096 characters. The SDK automatically validates this:
try {
  const longMessage = 'A'.repeat(5000); // Too long
  await client.sendText('+1234567890', longMessage);
} catch (error) {
  if (error instanceof MessageValidationError) {
    console.error('Message too long:', error.message);
    // Output: "Text exceeds 4096 characters limit"
  }
}

Character Counting

const message = 'Your message content here...';

// Check message length before sending
if (message.length > 4096) {
  console.error(`Message too long: ${message.length} characters (max 4096)`);
  return;
}

console.log(`Message is valid (${message.length} characters)`);
await client.sendText('+1234567890', message);

URL Preview Feature

When previewUrl is enabled, WhatsApp will generate a preview for the first URL found in the message.

URL Preview Examples

// News article with preview
await client.sendText(
  '+1234567890',
  'Breaking: Important announcement from our team.\n\n' +
  'Read the full story: https://news.example.com/breaking-news\n\n' +
  'Let us know what you think!',
  { previewUrl: true }
);

// Product link with preview
await client.sendText(
  '+1234567890',
  'Check out this amazing product we found for you!\n\n' +
  'https://shop.example.com/product/amazing-widget\n\n' +
  '💰 Special discount code: SAVE20',
  { previewUrl: true }
);

URL Preview Best Practices

  • ✅ Good Practices
  • ❌ Avoid
// Single URL for clean preview
await client.sendText(to, 
  'Article: The Future of Technology\n\n' +
  'https://blog.example.com/future-tech',
  { previewUrl: true }
);

// Descriptive context before URL
await client.sendText(to,
  'Your invoice is ready for download:\n' +
  'https://billing.example.com/invoice/123',
  { previewUrl: true }
);

Reply Messages

Reply to specific messages to maintain conversation context:

Basic Reply

// In webhook handler, get the message ID
const webhookProcessor = client.createWebhookProcessor({
  onTextMessage: async (message) => {
    // Reply to the user's message
    await client.sendText(
      message.from,
      'Thanks for your message! We received: "' + message.text + '"',
      { replyToMessageId: message.id }
    );
  }
});

Contextual Replies

// Support conversation example
const webhookProcessor = client.createWebhookProcessor({
  onTextMessage: async (message) => {
    const userText = message.text.toLowerCase();
    
    if (userText.includes('help')) {
      await client.sendText(
        message.from,
        '🆘 Our support team will assist you shortly.\n\n' +
        'In the meantime, check our FAQ: https://help.example.com',
        { 
          replyToMessageId: message.id,
          previewUrl: true 
        }
      );
    } else if (userText.includes('order')) {
      await client.sendText(
        message.from,
        '📦 Please provide your order number and I\'ll look it up for you.',
        { replyToMessageId: message.id }
      );
    }
  }
});

Text Formatting and Styling

Emoji Usage

// Effective emoji usage
await client.sendText('+1234567890', 
  '🎉 Welcome to our service!\n\n' +
  '✅ Account created successfully\n' +
  '📧 Confirmation email sent\n' +
  '🔗 Setup your profile: https://app.example.com/setup',
  { previewUrl: true }
);

// Status indicators
await client.sendText('+1234567890',
  '📊 System Status Update\n\n' +
  '✅ Website - Operational\n' +
  '✅ API - Operational\n' +
  '⚠️ Database - Degraded Performance\n' +
  '❌ Email Service - Down\n\n' +
  'Updates: https://status.example.com'
);

Text Structure

// Well-structured message
const structuredMessage = [
  '📋 Daily Report Summary',
  '',
  '📈 Metrics:',
  '• Sales: +15% vs yesterday',
  '• Traffic: 25,847 visitors',
  '• Conversion: 3.2%',
  '',
  '🎯 Top Performers:',
  '1. Product A - 127 sales',
  '2. Product B - 89 sales',
  '3. Product C - 56 sales',
  '',
  'Full report: https://dashboard.example.com/daily'
].join('\n');

await client.sendText('+1234567890', structuredMessage, { previewUrl: true });

Advanced Use Cases

Dynamic Content

async function sendPersonalizedWelcome(phoneNumber: string, userName: string) {
  const welcomeMessage = `
Hello ${userName}! 👋

Welcome to our platform. Here's what you can do:

🚀 Get started: Complete your profile
📚 Learn more: Check out our tutorials  
💬 Get help: Contact our support team

Ready to begin? https://app.example.com/onboarding
`.trim();

  return await client.sendText(phoneNumber, welcomeMessage, { previewUrl: true });
}

// Usage
await sendPersonalizedWelcome('+1234567890', 'John');

Conditional Messaging

async function sendOrderUpdate(phoneNumber: string, order: any) {
  let message = `📦 Order Update - #${order.id}\n\n`;
  
  switch (order.status) {
    case 'confirmed':
      message += '✅ Your order has been confirmed!\n';
      message += `💰 Total: $${order.total}\n`;
      message += `📅 Expected delivery: ${order.deliveryDate}`;
      break;
      
    case 'shipped':
      message += '🚚 Your order has shipped!\n';
      message += `📦 Tracking: ${order.trackingNumber}\n`;
      message += `🔗 Track here: ${order.trackingUrl}`;
      break;
      
    case 'delivered':
      message += '🎉 Your order has been delivered!\n';
      message += 'We hope you love your purchase.\n\n';
      message += '⭐ Rate your experience: https://review.example.com';
      break;
  }
  
  return await client.sendText(phoneNumber, message, { previewUrl: true });
}

Template-like Messages

class MessageTemplates {
  static appointmentReminder(name: string, date: string, time: string): string {
    return `
🏥 Appointment Reminder

Hi ${name},

This is a reminder about your upcoming appointment:

📅 Date: ${date}
🕐 Time: ${time}
📍 Location: Main Clinic

Need to reschedule? Reply "RESCHEDULE"
Questions? Call us at (555) 123-4567
`.trim();
  }
  
  static paymentReceived(amount: string, invoice: string): string {
    return `
💳 Payment Received

Thank you! We've received your payment:

💰 Amount: $${amount}
📄 Invoice: #${invoice}
📅 Date: ${new Date().toLocaleDateString()}

Receipt: https://billing.example.com/receipt/${invoice}
`.trim();
  }
}

// Usage
await client.sendText(
  '+1234567890',
  MessageTemplates.appointmentReminder('John Doe', 'March 15', '2:30 PM')
);

Error Handling

Common Errors

import { 
  MessageValidationError, 
  WhatsAppApiError 
} from 'whatsapp-client-sdk';

try {
  await client.sendText(to, message);
} catch (error) {
  if (error instanceof MessageValidationError) {
    switch (error.field) {
      case 'to':
        console.error('Invalid phone number:', error.value);
        break;
      case 'text.body':
        console.error('Invalid text content:', error.message);
        break;
    }
  } else if (error instanceof WhatsAppApiError) {
    switch (error.code) {
      case 131:
        console.error('Number not on WhatsApp');
        break;
      case 132:
        console.error('Message undeliverable');
        break;
      default:
        console.error('API error:', error.details);
    }
  }
}

Retry Logic

async function sendTextWithRetry(
  to: string, 
  text: string, 
  options?: TextOptions,
  maxRetries: number = 3
): Promise<MessageResponse> {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      return await client.sendText(to, text, options);
    } catch (error) {
      if (attempt === maxRetries) throw error;
      
      // Wait before retry (exponential backoff)
      const delay = Math.pow(2, attempt) * 1000;
      await new Promise(resolve => setTimeout(resolve, delay));
    }
  }
  
  throw new Error('Max retries exceeded');
}

Best Practices

1. Message Length

// ✅ Good: Concise and clear
await client.sendText(to, 
  'Order #12345 confirmed! 📦\n' +
  'Tracking: https://track.example.com/12345'
);

// ❌ Avoid: Too verbose
await client.sendText(to,
  'We are pleased to inform you that your order number 12345 has been successfully confirmed and is now being processed by our fulfillment team...'
);

2. URL Preview Usage

// ✅ Good: Enable for important links
await client.sendText(to,
  'Your invoice is ready: https://billing.example.com/invoice/123',
  { previewUrl: true }
);

// ❌ Avoid: Preview for every URL
await client.sendText(to,
  'Contact us at https://contact.example.com or https://support.example.com',
  { previewUrl: true } // Only first URL gets preview
);

3. Reply Context

// ✅ Good: Meaningful replies
await client.sendText(to,
  'Thanks for your order inquiry! Here are the details you requested...',
  { replyToMessageId: originalMessageId }
);

// ❌ Avoid: Generic replies
await client.sendText(to,
  'OK',
  { replyToMessageId: originalMessageId }
);

Next Steps

I