Skip to main content
Send WhatsApp template messages to hundreds or thousands of recipients with full tracking and statistics.

Complete workflow

// Step 1: Create broadcast
const createResponse = await fetch('https://api.kapso.ai/platform/v1/whatsapp/broadcasts', {
  method: 'POST',
  headers: {
    'X-API-Key': 'your-api-key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    whatsapp_broadcast: {
      name: 'July promo',
      phone_number_id: '1234567890',
      whatsapp_template_id: '7a8b9c0d-1e2f-3a4b-5c6d-7e8f9a0b1c2d'
    }
  })
});

const { data: broadcast } = await createResponse.json();
const broadcastId = broadcast.id;

// Step 2: Add recipients (repeat for batches > 1000)
await fetch(`https://api.kapso.ai/platform/v1/whatsapp/broadcasts/${broadcastId}/recipients`, {
  method: 'POST',
  headers: {
    'X-API-Key': 'your-api-key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    whatsapp_broadcast: {
      recipients: [
        {
          phone_number: '+14155550123',
          components: [
            {
              type: 'body',
              parameters: [
                { type: 'text', parameter_name: 'first_name', text: 'John' },
                { type: 'text', parameter_name: 'discount', text: '50%' }
              ]
            }
          ]
        }
      ]
    }
  })
});

// Step 3: Send broadcast
await fetch(`https://api.kapso.ai/platform/v1/whatsapp/broadcasts/${broadcastId}/send`, {
  method: 'POST',
  headers: { 'X-API-Key': 'your-api-key' }
});

// Step 4: Poll for progress
async function waitForCompletion(broadcastId) {
  while (true) {
    const statusResponse = await fetch(
      `https://api.kapso.ai/platform/v1/whatsapp/broadcasts/${broadcastId}`,
      { headers: { 'X-API-Key': 'your-api-key' } }
    );

    const { data } = await statusResponse.json();

    if (data.completed_at) {
      console.log(`Broadcast complete: ${data.sent_count}/${data.total_recipients} sent`);
      break;
    }

    console.log(`Progress: ${data.sent_count}/${data.total_recipients}`);
    await new Promise(resolve => setTimeout(resolve, 5000)); // Wait 5s
  }
}

await waitForCompletion(broadcastId);

Step 1: Create broadcast

const response = await fetch('https://api.kapso.ai/platform/v1/whatsapp/broadcasts', {
  method: 'POST',
  headers: {
    'X-API-Key': 'your-api-key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    whatsapp_broadcast: {
      name: 'July promo',
      phone_number_id: '1234567890',
      whatsapp_template_id: '7a8b9c0d-1e2f-3a4b-5c6d-7e8f9a0b1c2d'
    }
  })
});

const { data } = await response.json();
// data.id = broadcast ID for next steps
// data.status = 'draft'
Requirements:
  • Phone number must be production type (not sandbox)
  • Template must be approved

Step 2: Add recipients

Add up to 1,000 recipients per request. Repeat for batches over 1,000. Recipients use Meta’s component syntax to populate template variables.

Body parameters

For templates with body text variables:
await fetch(`https://api.kapso.ai/platform/v1/whatsapp/broadcasts/${broadcastId}/recipients`, {
  method: 'POST',
  headers: {
    'X-API-Key': 'your-api-key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    whatsapp_broadcast: {
      recipients: [
        {
          phone_number: '+14155550123',
          components: [
            {
              type: 'body',
              parameters: [
                { type: 'text', parameter_name: 'first_name', text: 'John' },
                { type: 'text', parameter_name: 'discount', text: '50%' }
              ]
            }
          ]
        },
        {
          phone_number: '+14155550124',
          components: [
            {
              type: 'body',
              parameters: [
                { type: 'text', parameter_name: 'first_name', text: 'Jane' },
                { type: 'text', parameter_name: 'discount', text: '40%' }
              ]
            }
          ]
        }
      ]
    }
  })
});

Button parameters

For templates with dynamic button URLs:
await fetch(`https://api.kapso.ai/platform/v1/whatsapp/broadcasts/${broadcastId}/recipients`, {
  method: 'POST',
  headers: {
    'X-API-Key': 'your-api-key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    whatsapp_broadcast: {
      recipients: [
        {
          phone_number: '+14155550123',
          components: [
            {
              type: 'body',
              parameters: [
                { type: 'text', parameter_name: 'first_name', text: 'Alicia' },
                { type: 'text', parameter_name: 'discount_code', text: 'JULY25' }
              ]
            },
            {
              type: 'button',
              sub_type: 'url',
              index: 0,
              parameters: [
                { type: 'text', text: 'promo-code-12345' }
              ]
            }
          ]
        }
      ]
    }
  })
});

Media headers

For templates with image/video/document headers:
await fetch(`https://api.kapso.ai/platform/v1/whatsapp/broadcasts/${broadcastId}/recipients`, {
  method: 'POST',
  headers: {
    'X-API-Key': 'your-api-key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    whatsapp_broadcast: {
      recipients: [
        {
          phone_number: '+14155550123',
          components: [
            {
              type: 'header',
              parameters: [
                {
                  type: 'image',
                  image: {
                    link: 'https://example.com/promo.jpg'
                  }
                }
              ]
            },
            {
              type: 'body',
              parameters: [
                { type: 'text', parameter_name: 'first_name', text: 'Alicia' },
                { type: 'text', parameter_name: 'discount_code', text: 'JULY25' }
              ]
            }
          ]
        }
      ]
    }
  })
});

Response format

{
  "data": {
    "added": 495,
    "duplicates": 5,
    "errors": [
      "Recipient 3: template parameters invalid - Template requires 2 parameters but 1 provided",
      "Recipient 7: invalid phone number format"
    ]
  }
}

Step 3: Send broadcast

Trigger async send job:
const response = await fetch(
  `https://api.kapso.ai/platform/v1/whatsapp/broadcasts/${broadcastId}/send`,
  {
    method: 'POST',
    headers: {
      'X-API-Key': 'your-api-key'
    }
  }
);

const { data } = await response.json();
// data.status = 'sending'
// data.started_at = timestamp
The broadcast processes asynchronously in the background. Poll for progress.

Step 4: Track progress

const response = await fetch(
  `https://api.kapso.ai/platform/v1/whatsapp/broadcasts/${broadcastId}`,
  {
    headers: {
      'X-API-Key': 'your-api-key'
    }
  }
);

const { data } = await response.json();

Response metrics

{
  "data": {
    "id": "5f6a7b8c-9d0e-1f2a-3b4c-5d6e7f8a9b0c",
    "name": "July promo",
    "status": "sending",
    "total_recipients": 1000,
    "sent_count": 650,
    "failed_count": 50,
    "delivered_count": 600,
    "read_count": 320,
    "responded_count": 45,
    "pending_count": 300,
    "response_rate": 6.9,
    "started_at": "2025-07-15T10:00:00Z",
    "completed_at": null
  }
}

Status transitions

  • draftsendingcompleted or failed
  • Poll every 5-10 seconds during send
  • Check completed_at for completion

Additional features

List individual recipients

Get detailed per-recipient status:
const response = await fetch(
  `https://api.kapso.ai/platform/v1/whatsapp/broadcasts/${broadcastId}/recipients?page=1&per_page=20`,
  {
    headers: {
      'X-API-Key': 'your-api-key'
    }
  }
);

const { data, meta } = await response.json();

Recipient fields

{
  "id": "8c9d0e1f-2a3b-4c5d-6e7f-8a9b0c1d2e3f",
  "phone_number": "14155550123",
  "status": "sent",
  "sent_at": "2025-07-15T10:05:23Z",
  "delivered_at": "2025-07-15T10:05:30Z",
  "read_at": "2025-07-15T10:12:45Z",
  "responded_at": "2025-07-15T10:15:00Z",
  "error_message": null,
  "template_components": [
    {
      "type": "body",
      "parameters": [
        { "type": "text", "parameter_name": "first_name", "text": "John" },
        { "type": "text", "parameter_name": "discount", "text": "50%" }
      ]
    }
  ]
}

Batch processing (large campaigns)

For campaigns with 1,000+ recipients:
// Split recipients into chunks of 1000
const chunkSize = 1000;
for (let i = 0; i < allRecipients.length; i += chunkSize) {
  const chunk = allRecipients.slice(i, i + chunkSize);

  await fetch(`https://api.kapso.ai/platform/v1/whatsapp/broadcasts/${broadcastId}/recipients`, {
    method: 'POST',
    headers: {
      'X-API-Key': 'your-api-key',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ whatsapp_broadcast: { recipients: chunk } })
  });

  // Optional: small delay between batches
  await new Promise(resolve => setTimeout(resolve, 100));
}