Back

Wazzap AI API Documentation - Sending WhatsApp Messages

Complete Wazzap API documentation to automate WhatsApp message sending programmatically

Last updated :
View as .md

Wazzap AI API Documentation - Sending WhatsApp Messages

Table of Contents

  1. Introduction
  2. Prerequisites and API Key Generation
  3. Authentication
  4. Sending Messages
  5. Phone Number Format
  6. Immediate or Queued Sending (waitForSend)
  7. Disabling AI Automatic Response
  8. Tracking and Statistics
  9. Rate Limiting and Queue
  10. Code Examples
  11. Error Handling
  12. Best Practices

Introduction

This API allows you to send WhatsApp messages programmatically using an API key.

Main Features

  • Secure authentication via API key
  • Text message sending
  • Rate limiting: 100 requests/minute per key (default)
  • Automatic WhatsApp account detection
  • Automatic phone number verification and correction (see Phone Number Format)

Prerequisites and API Key Generation

Step 1: Have a Wazzap AI Premium Account

You or your users must have an active Premium subscription on Wazzap AI.

Step 2: Create an AI Agent

  1. Log in to your Wazzap AI account
  2. Create a new AI agent from your dashboard
  3. Configure your agent according to your needs

Step 3: Connect Your WhatsApp Number

  1. From your agent's page, connect your WhatsApp number
  2. Scan the QR Code with WhatsApp
  3. Wait for the connection to be established

Step 4: Generate Your API Key

  1. Go to your account Settings
  2. Access the API Keys section
  3. Click on Generate a new key
  4. Give your key a name (e.g., "Maketou Integration")
  5. Select the WhatsApp agent to associate
  6. Copy the key immediately (it will not be displayed again)

⚠️ Important: Keep this key secure, it will only be displayed once!


Authentication

All requests require an Authorization header with Bearer format:

Authorization: Bearer wz_your_complete_api_key

Key format: wz_xxxxxxxxxxxxxxxxxxxxxx (32 characters after the prefix)

Response language

API messages (the message field, and errorMessage in /stats) are in French by default. To get them in English, add this header to your requests:

Accept-Language: en

All examples in this documentation assume Accept-Language: en. Codes (errorCode, status) never change with the language: test them in your code rather than the message text.


Sending Messages

Endpoint

POST https://api21.wazzap.ai/api/wazzap/send-message

Required Headers

Authorization: Bearer wz_your_api_key
Content-Type: application/json
Accept-Language: en

Accept-Language: en is optional: it returns API messages in English (French by default).

Request Body

{
  "phoneNumber": "+33612345678",
  "message": "Your message here",
  "disableAiResponse": false
}

Parameters

Parameter Type Required Description Example
phoneNumber string Yes Recipient's number, in international format with the country code (see Phone Number Format) "+33612345678"
message string Yes Text message to send "Hello!"
disableAiResponse boolean No Disables the AI automatic response for this contact (default: false) true
waitForSend boolean No Wait for the actual send before responding, to get the messageId or the exact error (default: false) true
simulateTyping boolean No Shows "typing…" to the recipient before sending, duration proportional to the message (default: true) false
delayMs number No Delay before sending, in milliseconds (default: 0) 2000

Success Response (200)

By default, the API responds immediately: the number has been verified and the message accepted, then sent in the background (after delayMs and the typing simulation). The messageId is therefore not known yet:

{
  "success": true,
  "code": 200,
  "message": "Message accepted — sending in progress (typing simulation)",
  "data": {
    "status": "queued",
    "messageId": null,
    "phoneNumber": "+33612345678",
    "formattedPhoneNumber": "33612345678",
    "provider": "v2.5",
    "agentId": "agent_123",
    "organizationId": "org_456",
    "aiResponseDisabled": false
  }
}

With "waitForSend": true, the response arrives once the message has actually been sent, with its messageId:

{
  "success": true,
  "code": 200,
  "message": "Message sent successfully",
  "data": {
    "status": "sent",
    "messageId": "3EB0XXXXXXXXXXXX",
    "phoneNumber": "+33612345678",
    "formattedPhoneNumber": "33612345678",
    "provider": "v2.5"
  }
}

Error Response (4xx/5xx)

{
  "success": false,
  "code": 400,
  "errorCode": "MISSING_PHONE_NUMBER",
  "message": "The 'phoneNumber' parameter is required"
}

Phone Number Format

The right format

Always send the full number in international format, with the country code:

Country ✅ Expected format ❌ Avoid
France +33612345678 or 33612345678 0612345678
Côte d'Ivoire +2250701020304 0701020304
Senegal +221771234567 771234567
Mexico +5213112345678 3112345678

Spaces, dashes, parentheses and + are accepted and stripped automatically: "+33 6 12 34 56 78" works.

Automatic verification and correction

Before each send, Wazzap checks with WhatsApp that the number exists, then sends to the actual WhatsApp number:

  1. The number as provided is checked first. WhatsApp recognizes known variants: in Mexico, 523112345678 is registered as 5213112345678, so the message goes to the right number.
  2. 00 international prefix: 0033612345678 is read as 33612345678.
  3. Missing country code or national format: if the number doesn't exist as provided, it is re-read in the country of the WhatsApp number connected to your agent. With an agent connected on a French number, 0612345678 becomes 33612345678.

⚠️ Correction #3 only works when the recipient is in the same country as your agent's WhatsApp number. For contacts abroad, the country code is required.

The formattedPhoneNumber field in the response shows the number actually used.

Number not on WhatsApp

If no variant of the number exists on WhatsApp, nothing is sent and the API responds:

{
  "success": false,
  "code": 400,
  "errorCode": "NUMBER_NOT_ON_WHATSAPP",
  "message": "This number is not on WhatsApp. Check it and use the full number with the country code (e.g. 33612345678)."
}

Check the number in your database (country code, missing digit) before retrying.


Immediate or Queued Sending (waitForSend)

waitForSend: false (default) waitForSend: true
Response Immediate, status: "queued" After the actual send, status: "sent"
messageId null WhatsApp message ID
Number not on WhatsApp Immediate 400 error Immediate 400 error
Send fails after acceptance Visible afterwards in /stats (FAILED) Error directly in the response
Recommended for High-volume notifications CRM integrations that need to know whether each message was sent
{
  "phoneNumber": "+33612345678",
  "message": "Your order is ready",
  "waitForSend": true
}
Mode Usual response time Recommended client timeout
waitForSend: false (default) 1 to 3 seconds 15 seconds
waitForSend: true A few more seconds (typing simulation proportional to the message, then sending) 30 seconds, or "simulateTyping": false

A session error (SESSION_NOT_CONNECTED) or a WhatsApp restriction (WHATSAPP_RESTRICTED) is returned immediately: no need to retry in a loop.


Disabling AI Automatic Response

What is disableAiResponse?

The disableAiResponse parameter allows you to disable the automatic conversation handling by the AI agent connected to your WhatsApp account for a specific contact. When activated (true), the contact switches to human mode, which means:

  • Your message will be sent normally
  • The contact will be created and linked to your agent
  • The AI will NOT automatically respond to this contact's messages
  • You can respond manually from your Wazzap AI dashboard or from your WhatsApp on your smartphone.

Typical Use Cases

1. VIP Support or Escalation

// Important client requiring human attention
await sendMessage(
  '+3300000000',
  'Hello Mr. Smith, an advisor will respond to you shortly.',
  { disableAiResponse: true }
);

2. One-way Notifications Without Expecting Response

// Delivery notification without requiring AI response
await sendMessage(
  '+33698765432',
  'Your package has arrived at the pickup point.',
  { disableAiResponse: true }
);

3. Personalized Marketing Campaigns

// Send a special offer without activating AI
const clients = ['+33601...', '+33602...'];
for (const client of clients) {
  await sendMessage(
    client,
    'Exclusive offer: -20% this weekend!',
    { disableAiResponse: true }
  );
}

Complete Example

const response = await fetch('https://api21.wazzap.ai/api/wazzap/send-message', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer wz_your_api_key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    phoneNumber: '+3300000000',
    message: 'Hello, a human will respond to you quickly.',
    disableAiResponse: true  // AI will not automatically respond
  })
});

const data = await response.json();
console.log('AI Response Disabled:', data.data.aiResponseDisabled); // true

How to Reactivate AI for a Contact?

To reactivate automatic AI response for a contact:

  1. Log in to your Wazzap AI dashboard
  2. Access the contact's conversation
  3. Click on the "Reactivate AI" button or similar

Or simply send a new message without the disableAiResponse parameter (or with false):

await sendMessage(
  '+3300000000',
  'AI is now reactivated',
  { disableAiResponse: false }  // AI will respond normally
);

Important to Know

  • The parameter applies per contact and persists until reactivation
  • A contact with disableAiResponse: true will be marked as "Human mode" in your dashboard
  • You can always respond manually via the dashboard
  • AI remains active for all other contacts

Tracking and Statistics

Statistics Endpoint

Check your API key's performance in real-time:

GET https://api21.wazzap.ai/api/wazzap/stats
Authorization: Bearer wz_your_api_key

Response

{
  "success": true,
  "data": {
    "apiKey": {
      "id": "cm9xxx...",
      "name": "Production API",
      "agentId": "cm9yyy..."
    },
    "stats": {
      "totalRequests": 1250,
      "successRequests": 1200,
      "failedRequests": 50,
      "successRate": 96.0
    },
    "queue": {
      "processing": 2,
      "pending": 5,
      "maxConcurrent": 4
    },
    "rateLimit": {
      "limit": 100,
      "current": 45,
      "remaining": 55,
      "resetAt": "2025-10-15T15:30:00.000Z"
    },
    "recentRequests": [
      {
        "id": "req_xxx",
        "status": "COMPLETED",
        "statusCode": 200,
        "duration": 234,
        "provider": "v2.5",
        "errorMessage": null,
        "startedAt": "2025-10-15T15:25:00.000Z",
        "completedAt": "2025-10-15T15:25:00.234Z"
      }
      // ... 9 other recent requests
    ]
  }
}

Available Metrics

Metric Description
totalRequests Total number of requests made
successRequests Number of successful requests
failedRequests Number of failed requests
successRate Success rate as percentage
queue.processing Number of requests being processed
queue.pending Number of requests waiting
rateLimit.current Number of requests in current window
rateLimit.remaining Number of requests remaining before limit
recentRequests[].status COMPLETED = message sent, FAILED = message not sent
recentRequests[].errorMessage Reason for the failure when status is FAILED (e.g. number not on WhatsApp)

ℹ️ With a queued send (default), the request is first recorded as accepted. If the background send then fails, it switches to FAILED in /stats, with the reason in errorMessage.

Monitoring Example

async function monitorAPI() {
  const response = await fetch('https://api21.wazzap.ai/api/wazzap/stats', {
    headers: {
      'Authorization': 'Bearer wz_your_api_key'
    }
  });

  const { data } = await response.json();
  
  console.log(`Success rate: ${data.stats.successRate}%`);
  console.log(`Queue: ${data.queue.processing}/${data.queue.maxConcurrent} processing, ${data.queue.pending} pending`);
  console.log(`Rate limit: ${data.rateLimit.remaining}/${data.rateLimit.limit} remaining`);
  
  // Alert if issue detected
  if (data.stats.successRate < 90) {
    console.warn('Low success rate - check WhatsApp connection');
  }
}

// Monitor every 30 seconds
setInterval(monitorAPI, 30000);

Rate Limiting and Queue

Automatic Queue System

To ensure stability, each API key has an intelligent queue that processes maximum 4 requests in parallel.

How does it work?

Your requests → [Queue] → [4 processing slots] → WhatsApp Sending
                            ↑
                    Maximum 4 simultaneous
                    Others wait

Rate Limiting

Each API key has configurable limits:

Parameter Default Description
rateLimit 100 Requests per window
rateLimitWindow 60s Window duration

By default: 100 requests per minute

Handling Exceeded Limits

If you exceed the limit:

{
  "success": false,
  "code": 429,
  "errorCode": "RATE_LIMIT_EXCEEDED",
  "message": "Too many requests. Please wait.",
  "rateLimit": {
    "limit": 100,
    "remaining": 0,
    "reset": "2025-10-15T15:30:00.000Z"
  }
}

Best Practices to Avoid Rate Limiting

// 1. Check before bulk sending
async function sendIfPossible(phoneNumber, message) {
  const stats = await getStats();
  
  if (stats.data.rateLimit.remaining < 5) {
    const resetTime = new Date(stats.data.rateLimit.resetAt);
    const waitTime = resetTime.getTime() - Date.now();
    console.log(`Waiting ${Math.ceil(waitTime/1000)}s...`);
    await new Promise(r => setTimeout(r, waitTime));
  }
  
  return await sendMessage(phoneNumber, message);
}

// 2. Automatically space out sends
async function sendWithSpacing(contacts, intervalMs = 700) {
  for (const contact of contacts) {
    await sendMessage(contact.phone, contact.message);
    await new Promise(r => setTimeout(r, intervalMs));
  }
}

Increasing Your Rate Limit

To increase your rate limit, contact your administrator or upgrade to a higher plan.


Code Examples

Simple Message Sending


Error Handling

Error Codes

HTTP Code Error Code Description Solution
200 - Success -
400 MISSING_PHONE_NUMBER Missing number Add phoneNumber
400 MISSING_MESSAGE Missing message Add message
400 NUMBER_NOT_ON_WHATSAPP The number doesn't exist on WhatsApp, even after correction Check the number and its country code
400 INVALID_DELAY delayMs is not a positive number Fix delayMs
400 NO_WHATSAPP_PROVIDER No WhatsApp connected Connect WhatsApp
401 API_KEY_MISSING Missing key Add Authorization header
401 API_KEY_INVALID_FORMAT / API_KEY_INVALID_PREFIX Malformed key Copy the full key (wz_…)
401 API_KEY_INVALID_OR_EXPIRED Invalid key Verify key
403 NO_WHATSAPP_ACCOUNT_CONNECTED WhatsApp not connected Reconnect WhatsApp
403 WHATSAPP_RESTRICTED WhatsApp has temporarily restricted the number (anti-spam protection) Wait a few hours, avoid bulk sends to new contacts
409 SESSION_NOT_CONNECTED The agent's WhatsApp session got disconnected Re-scan the QR code in Wazzap AI
404 AGENT_NOT_FOUND Agent not found Verify agent
429 RATE_LIMIT_EXCEEDED Too many requests Wait until the window resets (rateLimit.reset)
500 MESSAGE_SEND_ERROR Server error Retry

Error Examples

Missing API Key

{
  "success": false,
  "code": 401,
  "errorCode": "API_KEY_MISSING",
  "message": "API key missing. Use the 'Authorization: Bearer YOUR_API_KEY' header"
}

Missing Phone Number

{
  "success": false,
  "code": 400,
  "errorCode": "MISSING_PHONE_NUMBER",
  "message": "The 'phoneNumber' parameter is required"
}

Number Not on WhatsApp

{
  "success": false,
  "code": 400,
  "errorCode": "NUMBER_NOT_ON_WHATSAPP",
  "message": "This number is not on WhatsApp. Check it and use the full number with the country code (e.g. 33612345678)."
}

WhatsApp Account Not Connected

{
  "success": false,
  "code": 403,
  "errorCode": "NO_WHATSAPP_ACCOUNT_CONNECTED",
  "message": "No WhatsApp account connected for this agent"
}

Best Practices

1. Security

Do:

  • Store the key in environment variables
  • Never expose the key on client-side
  • Use HTTPS only
  • Regenerate the key if compromised

Don't:

  • Hardcode the key in code
  • Commit the key to Git
  • Share the key publicly

Secure Example:

// .env
WAZZAP_AI_API_KEY=wz_your_api_key
WAZZAP_AI_API_URL=https://api21.wazzap.ai

// config.js
require('dotenv').config();

module.exports = {
  apiKey: process.env.WAZZAP_AI_API_KEY,
  apiUrl: process.env.WAZZAP_AI_API_URL
};

2. Rate Limiting

  • Default: 100 requests per minute per API key
  • Implement a queue for bulk sends

3. Data Validation

// Normalize the number to international format (E.164)
function validateNumber(phoneNumber) {
  let cleaned = phoneNumber.replace(/[^\d+]/g, '');
  if (cleaned.startsWith('00')) cleaned = '+' + cleaned.slice(2);
  if (!/^\+?\d{8,15}$/.test(cleaned)) {
    throw new Error('Invalid number');
  }
  // A number starting with 0 is in national format: add the country code
  if (/^0\d/.test(cleaned)) {
    throw new Error('Missing country code (e.g. +33 for France)');
  }
  return cleaned.startsWith('+') ? cleaned : '+' + cleaned;
}

// Handle the "number not on WhatsApp" case
const result = await sendMessage(number, message);
if (result.errorCode === 'NUMBER_NOT_ON_WHATSAPP') {
  // Flag the contact as "no WhatsApp" in your CRM
}

// Validate message
function validateMessage(message) {
  if (!message || typeof message !== 'string') {
    throw new Error('Invalid message');
  }
  if (message.length > 4096) {
    throw new Error('Message too long (max 4096 characters)');
  }
  return message.trim();
}

📚 Use Cases

Sending Personalized Notifications

const clients = [
  { name: 'John Smith', phone: '+3300000000', order: '#12345' },
  { name: 'Mary Johnson', phone: '+33698765432', order: '#12346' }
];

async function sendNotifications(clients) {
  for (const client of clients) {
    const message = `
Hello ${client.name},

Your order ${client.order} has been confirmed.

Thank you!
    `.trim();
    
    await sendMessage(client.phone, message);
    await new Promise(r => setTimeout(r, 3000)); // Wait 3s
  }
}

Support

Common Issues

Message doesn't arrive:

  1. Check that the number is in international format with the country code (see Phone Number Format)
  2. Check /stats: a FAILED request gives the reason in errorMessage
  3. Use "waitForSend": true to get the send result directly in the response
  4. Check that your agent's WhatsApp number is connected (version 2.5) in Wazzap AI

"Rate limit exceeded":

  1. Reduce sending frequency
  2. Wait 1 minute
  3. Implement a queue

Invalid API key:

  1. Verify you copied the complete key
  2. Verify the key hasn't expired
  3. Regenerate a new key if necessary

Contact

For any questions:


APIWhatsAppIntegrationDevelopment

Create your AI assistant for free

Transform your WhatsApp conversations into business opportunities, qualify your leads and schedule appointments automatically

Amadou Fall
Kaaramoo
Bestilia
Joel Toulan
4.8 / 5
Used by + 40 125 users

No credit card required ·

Wazzap AI API Documentation - Sending WhatsApp Messages | Wazzap AI - The #1 AI Setter built for Agencies.