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://app.kapso.ai/api/v1/whatsapp_broadcasts', {
  method: 'POST',
  headers: {
    'X-API-Key': 'your-api-key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    whatsapp_broadcast: {
      name: 'July promo',
      whatsapp_config_id: '4a5b6c7d-8e9f-0a1b-2c3d-4e5f6a7b8c9d',
      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://app.kapso.ai/api/v1/whatsapp_broadcasts/${broadcastId}/recipients`, {
  method: 'POST',
  headers: {
    'X-API-Key': 'your-api-key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    recipients: [
      {
        phone_number: '+14155550123',
        template_parameters: { customer_name: 'John', discount: '50%' }
      }
    ]
  })
});

// Step 3: Send broadcast
await fetch(`https://app.kapso.ai/api/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://app.kapso.ai/api/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://app.kapso.ai/api/v1/whatsapp_broadcasts', {
  method: 'POST',
  headers: {
    'X-API-Key': 'your-api-key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    whatsapp_broadcast: {
      name: 'July promo',
      whatsapp_config_id: '4a5b6c7d-8e9f-0a1b-2c3d-4e5f6a7b8c9d',
      whatsapp_template_id: '7a8b9c0d-1e2f-3a4b-5c6d-7e8f9a0b1c2d'
    }
  })
});

const { data } = await response.json();
// data.id = broadcast ID for next steps
// data.status = 'draft'
Requirements:
  • WhatsApp config must be production type
  • Template must be approved and linked to the config

Step 2: Add recipients

Add up to 1,000 recipients per request. Repeat for batches over 1,000.

Positional parameters

For templates with {{1}}, {{2}} placeholders:
await fetch(`https://app.kapso.ai/api/v1/whatsapp_broadcasts/${broadcastId}/recipients`, {
  method: 'POST',
  headers: {
    'X-API-Key': 'your-api-key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    recipients: [
      {
        phone_number: '+14155550123',
        template_parameters: ['John', '50% off']
      },
      {
        phone_number: '+14155550124',
        template_parameters: ['Jane', '40% off']
      }
    ]
  })
});

Named parameters

For templates with {{customer_name}}, {{discount_code}} placeholders:
await fetch(`https://app.kapso.ai/api/v1/whatsapp_broadcasts/${broadcastId}/recipients`, {
  method: 'POST',
  headers: {
    'X-API-Key': 'your-api-key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    recipients: [
      {
        phone_number: '+14155550123',
        template_parameters: {
          customer_name: 'Alicia',
          discount_code: 'JULY25',
          expiry: '2025-07-31'
        }
      }
    ]
  })
});

Media headers

For templates with image/video/document headers:
await fetch(`https://app.kapso.ai/api/v1/whatsapp_broadcasts/${broadcastId}/recipients`, {
  method: 'POST',
  headers: {
    'X-API-Key': 'your-api-key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    recipients: [
      {
        phone_number: '+14155550123',
        template_parameters: {
          header_url: 'https://example.com/promo.jpg',
          header_filename: 'promo.jpg',
          customer_name: 'Alicia',
          discount_code: '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://app.kapso.ai/api/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://app.kapso.ai/api/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://app.kapso.ai/api/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
}

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://app.kapso.ai/api/v1/whatsapp_broadcasts/${broadcastId}/recipients`, {
    method: 'POST',
    headers: {
      'X-API-Key': 'your-api-key',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ recipients: chunk })
  });

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